算法 - 使用重力

时间:2017-01-10 19:15:47

标签: c# algorithm sorting matrix boggle

我正在尝试制作一个算法来填充方形矩阵中给定单词的列表,其中字母数量等于矩阵大小。

这里的诀窍是你应该能够连接每个单词(每个单词后面的字母都在同一个单词中),并且在连接结束时应该清除单板。 (每个单词都是独立的 - 不与其他单词连接)。

你可以连接一个单词:如果它的字母是邻居 - (邻居可以是:左,右,顶部,底部,左上角,右上角,左下角,右下角)。你应该按顺序连接字母,不能跳过字母。 (比如在没有取下铅笔的情况下在纸上画一条线)并且在连接单词时你不能从另一个单词的其他字母上面去。

当一个单词被连接时,它被从棋盘上移除 - 并且其字母上方的每个字母都会掉下来取而代之(如:字母无法飞行)。每个都将落在另一个之上而不是矩阵中的相同位置。

首先看一下电路板,不必全部连接 - 所以:它们应该是可连接的,而其他字是连接的 - 那么它的字母将是邻居。

这是董事会应该如何显示的一个例子:

Board Solving Example - GIF

图像中的电路板是由我写的算法生成的,它会在1-10秒内生成5X5电路板,这对于计算机而言太过分了。我遇到的问题是7X7和更大的电路板会产生“无限”时间,但我无法生成任何7X7电路板。

另一个注意事项:董事会不应该遵循在所有董事会上重复的模式,并且首选不遵循模式。

我在互联网上搜索了几天,找不到解决此类问题的文章。启动代码时我的CPU使用率约为1.1%。我不知道为什么需要花费很多时间。

我正在使用递归算法,这是控制世代的主要功能:

public void Build()
    {
        // Sort words from The longest to the shortest
        sortWords();

        //convert list of words to string
        string words = ListToString(this.words);

        // Get The Result of the generation function.
        bool result = Generate(words, null);
    }



    private Random random = new Random();
    private bool Generate(string words, Word word)
    {
        // If [words = null], Then The function failed to generate a board from no words.
        if (words == null)
            return false;

        // If got to the end of the words, Then succedd to fill all words in the board
        if (words.Length == 0)
            return true;

        // If Got [" "] blank letter, Then should switch to the next word. 
        if (words[0].ToString() == " ")
        {
            board.changedWord(); // Delegate: Update UI
            return Generate(words.Substring(1, words.Length - 1), null);
        }

        // If [word = null], Then we are creating a new word
        if (word == null)
            word = new Word(board);

        // Check If there is a group of letters that can't connect with other letters
        // and they cann't contain any word in them.
        if (board.isLocked(minInString(words)))
            return false;

        // Store all available legal neighbours to the previus added letter
        List<Location> neighbours = new List<Location>();


        if (word.Length == 0) { // This is a new word -> Any Cell would be legal
            neighbours = board.FreeLocations();
        }

        else { // This word is in progress. Neighbours rules should be applied
            neighbours = board.Neighbours(word.Letters.Last().Location);
        }

        if (neighbours.Count == 0) { // If found no neighbours, Then cant continue with the current word
            return false;
        }

        int index = 0; // Shoiuld hold letter index in word - has nothing to do right now. initail value [0].

        while (neighbours.Count > 0)
        { // Try each one of the suggested neighbours

            // Get a random neighbour from available legal neighbours
            int randLocationIndex = random.Next(neighbours.Count);
            Location location = neighbours[randLocationIndex];

            // If word wasn't added to the words, add it!
            if (!board.Words.Contains(word))
                board.Words.Add(word);

            // Add the current letter to the related word in board
            board.Add(new Letter(word, location, words[0].ToString(), index), word);

            if (!word.isValid()) {
                // Check if current word can be connected,
                //Its own letters doesn't make any problem to each other.
                board.Remove(word.Letter(word.Length - 1));
                neighbours.RemoveAt(randLocationIndex);
                continue;
            }

            if (!board.Solved()) {
                // Check if the board is solvable [Gravity cases]
                // -> Check each word that devides the connection between current word, that its connectable 
                board.Remove(word.Letter(word.Length - 1));
                neighbours.RemoveAt(randLocationIndex);
                continue;
            }

            // Try the letters after me.
            bool result = Generate(words.Substring(1, words.Length - 1), word);

            // If all words after this, succeded, then me and sons succeded, return true.
            if (result == true)
                return true;

            else { // Remove added point from word's path, Remove it from available neighbours
                board.Remove(word.Letter(word.Length - 1));
                neighbours.RemoveAt(randLocationIndex);
            }
        }

        // If Current Word has added no letters to board: then remove it from board
        // we dont need any empty useless word in the board.
        if (word.Length == 0) {
            //board.CancelWord(); Delegate: Update Board UI
            board.Words.Remove(word);
        }

        // Tryed all sugested neighbours for current letter, all of them has failed
        // retuen false - Thats a fail :(
        return false;
    }

我可以读/写c#,C ++,C,Java,Swift和Objective-C。

0 个答案:

没有答案