Crossword game algorithm in C #

I am doing a crossword puzzle for my uni assignment. Almost done, but here's the problem I can't seem to solve.

We need to download a csv file that contains the completed crossword puzzle game, but we need to do some checking to make sure the crossword file is valid.

Limitations:

  • Words cannot be repeated.
  • Words can be placed horizontally, but only from left to right.
  • Words can be placed vertically, but only from high to low.
  • A horizontal word must intersect one or more vertical words.
  • A vertical word must intersect one or more horizontal words.
  • Each word must be separated by spaces or the edge of the grid.

I did all the restrictions above but I am stuck here

  • You can only have one group of related words, i.e. a group of connected words cannot be disconnected from another group of connected words.

Part of the crossword file looks like this: (I cannot upload images due to 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 have done applies to this so far:

  • A class named Crozzle represents this crossword file. One of the properties is the public CrozzleWords List containing all the words in the file.

  • The WordInCrozzle class name represents each word in Crozzle. Each word has an attribute to record the position of the intersection. for example, the word "ROBERT" has an intersection with the word "BILL", the position of the intersection is (int) [0,3], the letter at the intersection is "B".

  • The word in the WordInCrozzle class has another Direction property, which represents the direction of the word, it can be either vertical or horizontal.

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 have a "System.InvalidOperationException", it tells me that I cannot change tempWords when I do foreach.

Can anyone tell me how to do this? or is there any algorithm for determining if there is only one group of words in the crossword file?

+3


source to share


3 answers


You cannot remove an item from an array when you are listing it. I usually make a copy of the array and list the following:



foreach (WordInCrozzle w in tempWords.ToArray())
{
    ...
    tempWords.Remove(w);
}

      

+3


source


As an exception, you say that you cannot change the list that IEnumerable implements while walking through it. The solution would be to create a separate list and add all the items you want to remove. When you are done looping, remove each item in the new list from the original list.



You can also move the original loop backwards (plus some other parameters): How do I remove items from the general list while iterating over it?

+4


source


My algorithm for this limitation

You can only have one group of related words. That is, a group of related words cannot be disconnected from another group of related words.

is an:

  • Take the first word and place it in the collection of "related words".
  • Go through all the remaining words, and if some of them are related to "Related words" → also put it in "Related words".
  • Do the 2nd step until you put at least one word in the "connected words".
  • When the cycle is over → If there are still leftover words that were not associated with the "linked words", it means you have multiple groups.
0


source







All Articles