コード例 #1
0
    public static List <List <CrosswordBuilder.Cell> > CopyCellsList(List <List <CrosswordBuilder.Cell> > cells)
    {
        List <List <CrosswordBuilder.Cell> > cellsCopy = new List <List <CrosswordBuilder.Cell> >();

        for (int i = 0; i < cells.Count; i++)
        {
            cellsCopy.Add(new List <CrosswordBuilder.Cell>());

            for (int j = 0; j < cells[i].Count; j++)
            {
                CrosswordBuilder.Cell cell     = cells[i][j];
                CrosswordBuilder.Cell cellCopy = new CrosswordBuilder.Cell();

                cellCopy.isBlock    = cell.isBlock;
                cellCopy.isNumbered = cell.isNumbered;
                cellCopy.character  = cell.character;

                cellCopy.startRowAcross = cell.startRowAcross;
                cellCopy.startColAcross = cell.startColAcross;
                cellCopy.acrossCount    = cell.acrossCount;
                cellCopy.hasAcrossWord  = cell.hasAcrossWord;

                cellCopy.startRowDown = cell.startRowDown;
                cellCopy.startColDown = cell.startColDown;
                cellCopy.downCount    = cell.downCount;
                cellCopy.hasDownWord  = cell.hasDownWord;

                cellsCopy[i].Add(cellCopy);
            }
        }

        return(cellsCopy);
    }
コード例 #2
0
    public List <string> GetPossibleWords(List <List <CrosswordBuilder.Cell> > cells, int startRow, int startCol, int length, bool isAcross)
    {
        if (!HasWordsOfLength(length))
        {
            // Return an empty list
            return(null);
        }

        string        wordDictKey   = "";
        List <string> possibleWords = null;

        for (int i = 0; i < length; i++)
        {
            int row = startRow + (isAcross ? 0 : i);
            int col = startCol + (isAcross ? i : 0);

            CrosswordBuilder.Cell cell = cells[row][col];

            if (cell.character != ' ')
            {
                wordDictKey = CBWordDict.AddToKey(wordDictKey, i, cell.character);

                if (length > CBUtilities.MaxLengthForFullWordMapping)
                {
                    List <string> words = GetMappedWords(length, wordDictKey);

                    // If there are no words with this key then there are no words that fit in the given cells
                    if (words == null)
                    {
                        return(null);
                    }

                    // If the new list is less than the one we have so far then lets use that one instead
                    if (possibleWords == null || words.Count < possibleWords.Count)
                    {
                        possibleWords = words;
                    }

                    wordDictKey = "";
                }
            }
        }

        // If possible words is not null then we still need to get the words
        if (possibleWords == null)
        {
            // If wordDictKey is empty then all the cells are blank
            if (string.IsNullOrEmpty(wordDictKey))
            {
                // Return all words of the given length
                return(loadedWords[length]);
            }

            // Return the words using the key
            return(GetMappedWords(length, wordDictKey));
        }

        return(possibleWords);
    }
コード例 #3
0
    public static void RemoveWord(List <List <CrosswordBuilder.Cell> > cells, int startRow, int startCol, int length, bool across)
    {
        bool removedOneChar = false;

        for (int i = 0; i < length; i++)
        {
            int row = startRow + (across ? 0 : i);
            int col = startCol + (across ? i : 0);

            CrosswordBuilder.Cell cell = cells[row][col];

            if (across)
            {
                CrosswordBuilder.Cell downStartCell = cells[cell.startRowDown][cell.startColDown];

                if (!downStartCell.hasDownWord)
                {
                    cell.character = ' ';
                    removedOneChar = true;
                }
            }
            else
            {
                CrosswordBuilder.Cell acrossStartCell = cells[cell.startRowAcross][cell.startColAcross];

                if (!acrossStartCell.hasAcrossWord)
                {
                    cell.character = ' ';
                    removedOneChar = true;
                }
            }
        }

        if (removedOneChar)
        {
            CrosswordBuilder.Cell startCell = cells[startRow][startCol];

            if (across)
            {
                startCell.hasAcrossWord = false;
                startCell.acrossWord    = "";
            }
            else
            {
                startCell.hasDownWord = false;
                startCell.downWord    = "";
            }
        }
    }
コード例 #4
0
    private bool TryWord(string word, int startRow, int startCol, bool isAcross, int depth, out int fitCount)
    {
        fitCount = 0;

        UsedWords.Add(word);

        List <CrosswordBuilder.Cell> changedCells = new List <CrosswordBuilder.Cell>();

        // Place the word, keeping track of the cells that where changed
        for (int i = 0; i < word.Length; i++)
        {
            int row = startRow + (isAcross ? 0 : i);
            int col = startCol + (isAcross ? i : 0);

            CrosswordBuilder.Cell cell = Cells[row][col];

            if (cell.character == ' ')
            {
                changedCells.Add(cell);
                cell.character = word[i];
            }
        }

        bool foundFitForAllChangedCells = true;

        // Check the perpendicular cells for all the cells what where blank, these are the ones without words on them
        for (int i = 0; i < changedCells.Count; i++)
        {
            if (Stopping)
            {
                // Threads are shutting down, we don't care about the state of Cells so just return
                return(false);
            }

            // Get the start row and col of the perpendicular word
            int sr = isAcross ? changedCells[i].startRowDown : changedCells[i].startRowAcross;
            int sc = isAcross ? changedCells[i].startColDown : changedCells[i].startColAcross;

            CrosswordBuilder.Cell startCell = Cells[sr][sc];

            int len = isAcross ? startCell.downCount : startCell.acrossCount;

            if (len == 1)
            {
                continue;
            }

            // Get the words that can fit in the cells given the characters that are already there
            List <string> wordsToTry = WordDictionary.GetPossibleWords(Cells, sr, sc, len, !isAcross);

            // If wordsToTry is null then there was no word that can fit in the cell
            if (wordsToTry == null)
            {
                foundFitForAllChangedCells = false;
                break;
            }

            fitCount += wordsToTry.Count;

            // If there were words that could fit in the cells and depth is 0 then dont check the individual words, just continue to the next changed cell
            if (depth >= CBUtilities.MaxCheckDepth && len <= CBUtilities.MaxLengthForFullWordMapping)
            {
                continue;
            }

            bool foundFit = false;

            for (int j = 0; j < wordsToTry.Count; j++)
            {
                if (Stopping)
                {
                    // Threads are shutting down, we don't care about the state of Cells so just return
                    return(false);
                }

                string wordToTry = wordsToTry[j];
                bool   fits      = true;

                // Don't reuse words
                if (UsedWords.Contains(wordToTry))
                {
                    continue;
                }

                if (len > CBUtilities.MaxLengthForFullWordMapping)
                {
                    for (int k = 0; k < len; k++)
                    {
                        int row = sr + (!isAcross ? 0 : k);
                        int col = sc + (!isAcross ? k : 0);

                        CrosswordBuilder.Cell cell = Cells[row][col];

                        if (cell.character != ' ' && cell.character != wordToTry[k])
                        {
                            fits = false;
                            break;
                        }
                    }
                }

                if (fits)
                {
                    int temp = 0;

                    // Check if this word will cause the baord to be unsolvable
                    if (depth >= CBUtilities.MaxCheckDepth || TryWord(wordToTry, sr, sc, !isAcross, depth + 1, out temp))
                    {
                        // This word doesn't cause the board to be unsolvable (alteast up to the depth that was set)
                        foundFit = true;

                        // If depth is one we want to count how many words fit so we can present the best ones to the user
                        break;
                    }
                }
            }

            // We could not fit a word without causing an unsolvable board, so the word we where given cannot be placed
            if (!foundFit)
            {
                foundFitForAllChangedCells = false;

                break;
            }
        }

        fitCount = (int)((float)fitCount / (float)changedCells.Count);

        // Set the changed cells back to blank
        for (int i = 0; i < changedCells.Count; i++)
        {
            changedCells[i].character = ' ';
        }

        UsedWords.Remove(word);

        return(foundFitForAllChangedCells);
    }
コード例 #5
0
    public static List <CrosswordBuilder.Cell> PlaceWordOnCell(string word, List <List <CrosswordBuilder.Cell> > cells, int startRow, int startCol, int length, bool across)
    {
        List <CrosswordBuilder.Cell> blankCells = new List <CrosswordBuilder.Cell>();

        CrosswordBuilder.Cell startCell = cells[startRow][startCol];

        if (across)
        {
            startCell.hasAcrossWord = true;
            startCell.acrossWord    = word;
            length = startCell.acrossCount;
        }
        else
        {
            startCell.hasDownWord = true;
            startCell.downWord    = word;
            length = startCell.downCount;
        }

        for (int i = 0; i < length; i++)
        {
            int row = startRow + (across ? 0 : i);
            int col = startCol + (across ? i : 0);

            CrosswordBuilder.Cell cell = cells[row][col];

            if (cell.character == ' ')
            {
                blankCells.Add(cell);
            }

            // Set the character in the cell
            cell.character = word[i];

            // Now we need to check if this created a crossing word
            bool crossAcross   = !across;
            int  crossRowStart = crossAcross ? cell.startRowAcross : cell.startRowDown;
            int  crossColStart = crossAcross ? cell.startColAcross : cell.startColDown;
            int  crossLength   = crossAcross ? cell.acrossCount : cell.downCount;

            string crossWord    = "";
            bool   setCrossWord = true;

            if (crossLength == 1)
            {
                setCrossWord = false;
            }
            else
            {
                for (int j = 0; j < crossLength; j++)
                {
                    int crossRow = crossRowStart + (crossAcross ? 0 : j);
                    int crossCol = crossColStart + (crossAcross ? j : 0);

                    CrosswordBuilder.Cell crossCell = cells[crossRow][crossCol];

                    if (crossCell.character == ' ')
                    {
                        setCrossWord = false;
                        break;
                    }

                    crossWord += crossCell.character;
                }
            }

            if (setCrossWord)
            {
                CrosswordBuilder.Cell crossStartCell = cells[crossRowStart][crossColStart];

                if (crossAcross)
                {
                    crossStartCell.hasAcrossWord = true;
                    crossStartCell.acrossWord    = crossWord;
                }
                else
                {
                    crossStartCell.hasDownWord = true;
                    crossStartCell.downWord    = crossWord;
                }
            }
        }

        return(blankCells);
    }