I'm doing a crossword game for my uni assignment. Almost done, but here is a problem that I can't solve it.
We need to load a csv file which contains a completed crossword game, but we need to do some validation to make sure the crossword file is valid.
The constraints are:
I've done all constraints above, but i'm stuck at here
Part of the crossword file is like this: (I can't upload images because lack of reputation)
R O B E R T
I
J I L L
E L J O H N
S A
S M A R Y R
I A O R
C R G A R Y
.......
What i've done relate to this so far:
A class named Crozzle represents this crossword file. One of the property is public List CrozzleWords, which contains all the word in the file.
A class name WordInCrozzle represents every single word in Crozzle. Every word has an attribute to record the intersection's position. e.g. the word 'ROBERT' has an intersection with the word 'BILL' the intersection's position is (int)[0,3], the letter at intersection is 'B'.
The word in WordInCrozzle class has another property named Direction, which represent the direction of the word, can be either vertically or horizontally.
Here is my solution:
public bool ContainsOneGroup()
{
bool flag = true;
// a temp crozzle word list
List<WordInCrozzle> tempWords = _crozzle.CrozzleWords;
// start from the first item in wordlist, whatever which word is using
WordInCrozzle word = tempWords[0];
if (word.IntersectionPosition.Count > 0)
{
// step1. get a word randomly 'Word' OK -- WordInCrozzle word = tempWords[0];
// step2. get wordInCrozzle List OK -- List<WordInCrozzle> tempWords = _crozzle.CrozzleWords;
// step3. find the intersection position(s) of the word 'Word' and store it to a temp list 'positionOfIntersection' OK -- List<int[]> positionOfIntersection = word.IntersectionPosition;
List<int[]> positionOfIntersection = word.IntersectionPosition;
// remove the first word
tempWords.Remove(word);
//crozzleBackup.CrozzleWords.Remove(word);
// step4. if can grab an intersection position from 'positionOfIntersection' (means any)
while (positionOfIntersection.Any())
{
foreach (WordInCrozzle w in tempWords)
{
for (int i = 0; i < w.IntersectionPosition.Count; i++)
{
if (ArraysEqual(w.IntersectionPosition[i], positionOfIntersection[0]))
{
w.IntersectionPosition.Remove(positionOfIntersection[0]);
positionOfIntersection.Remove(positionOfIntersection[0]);
//tempWords.CrozzleWords[i].IntersectionPosition.Remove(w.IntersectionPosition[i]);
if (w.IntersectionPosition.Count > 0)
{
// store the positionOfIntersections, if this is null, and still have word in tempWords, means there are more than one group of words
positionOfIntersection.AddRange(w.IntersectionPosition);
}
// after get the position, remove the word
tempWords.Remove(w);
}
}
}
}
// step9. if there is no more intersection position left, and no word in wordInCrozzle List, means only one group in the crozzle
// Otherwise, more than one group of word
if (tempWords.Any())
{
_errors.Add(new Error(ErrorType.CrozzleError, "More than one group of connected words found"));
flag = false;
}
}
else
{
_errors.Add(new Error(ErrorType.CrozzleError, "More than one group of connected words found")); // if there is no intersection in a word, means there must more than one group of words
flag = false;
}
return flag;
}
But when I run it, I've got a 'System.InvalidOperationException', it tells me I can't modify the tempWords when i'm doing foreach.
Anybody can tell me how to do that? or is there any algorithm to figure out is there only one group of words in the crossword file?
You aren't allowed to remove an element from an array while you enumerate it. What I usually do is just make a copy of the array and enumerate over that:
foreach (WordInCrozzle w in tempWords.ToArray())
{
...
tempWords.Remove(w);
}