我正在尝试制作一个算法来填充方形矩阵中给定单词的列表,其中字母数量等于矩阵大小。
这里的诀窍是你应该能够连接每个单词(每个单词后面的字母都在同一个单词中),并且在连接结束时应该清除单板。 (每个单词都是独立的 - 不与其他单词连接)。
你可以连接一个单词:如果它的字母是邻居 - (邻居可以是:左,右,顶部,底部,左上角,右上角,左下角,右下角)。你应该按顺序连接字母,不能跳过字母。 (比如在没有取下铅笔的情况下在纸上画一条线)并且在连接单词时你不能从另一个单词的其他字母上面去。
当一个单词被连接时,它被从棋盘上移除 - 并且其字母上方的每个字母都会掉下来取而代之(如:字母无法飞行)。每个都将落在另一个之上而不是矩阵中的相同位置。
首先看一下电路板,不必全部连接 - 所以:它们应该是可连接的,而其他字是连接的 - 那么它的字母将是邻居。
这是董事会应该如何显示的一个例子:
图像中的电路板是由我写的算法生成的,它会在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。