我正在使用C#编写一个单词查找谜题,希望能够以一种优雅的方式搜索字符的二维数组中的单词。从左到右、从上到下等基本搜索不难实现,但当在这个数组中进行对角线搜索时,代码会变得有些冗长。我已经让它正常工作了,但我相信还有更好的解决方案。
以下是一个我正在尝试解决的谜题示例,非常感谢大家给出任何想法。
BXXD AXEX TRXX FXXX
要搜索的单词是BAT FRED。
编辑:感谢Steve提供了搜索罗盘点思路的建议。
编辑:搜索结果需要返回单词在数组中的x1、y1和x2、y2坐标。
编辑:感谢Antti提供了一个搜索数组的好算法。
这是我最终得出的结果。我基于Antti答案中的算法进行改进,使其返回任何找到的单词的开始和结束的数组偏移量。我正在使用这个算法编写一个Word Search游戏,用于我的孩子们的WPF。感谢大家的帮助,当这个应用达到可观状态时,我会在这里发布链接。
以下是一个我正在尝试解决的谜题示例,非常感谢大家给出任何想法。
BXXD AXEX TRXX FXXX
要搜索的单词是BAT FRED。
编辑:感谢Steve提供了搜索罗盘点思路的建议。
编辑:搜索结果需要返回单词在数组中的x1、y1和x2、y2坐标。
编辑:感谢Antti提供了一个搜索数组的好算法。
这是我最终得出的结果。我基于Antti答案中的算法进行改进,使其返回任何找到的单词的开始和结束的数组偏移量。我正在使用这个算法编写一个Word Search游戏,用于我的孩子们的WPF。感谢大家的帮助,当这个应用达到可观状态时,我会在这里发布链接。
public class Range
{
public Range(Coordinate start, Coordinate end)
{
Start = start;
End = end;
}
public Coordinate Start { get; set; }
public Coordinate End { get; set; }
}
public class Coordinate
{
public Coordinate(int x, int y)
{
X = x;
Y = y;
}
public int X { get; set; }
public int Y { get; set; }
}
public class WordSearcher
{
public WordSearcher(char[,] puzzle)
{
Puzzle = puzzle;
}
public char[,] Puzzle { get; set; }
// represents the array offsets for each
// character surrounding the current one
private Coordinate[] directions =
{
new Coordinate(-1, 0), // West
new Coordinate(-1,-1), // North West
new Coordinate(0, -1), // North
new Coordinate(1, -1), // North East
new Coordinate(1, 0), // East
new Coordinate(1, 1), // South East
new Coordinate(0, 1), // South
new Coordinate(-1, 1) // South West
};
public Range Search(string word)
{
// scan the puzzle line by line
for (int y = 0; y < Puzzle.GetLength(0); y++)
{
for (int x = 0; x < Puzzle.GetLength(1); x++)
{
if (Puzzle[y, x] == word[0])
{
// and when we find a character that matches
// the start of the word, scan in each direction
// around it looking for the rest of the word
var start = new Coordinate(x, y);
var end = SearchEachDirection(word, x, y);
if (end != null)
{
return new Range(start, end);
}
}
}
}
return null;
}
private Coordinate SearchEachDirection(string word, int x, int y)
{
char[] chars = word.ToCharArray();
for (int direction = 0; direction < 8; direction++)
{
var reference = SearchDirection(chars, x, y, direction);
if (reference != null)
{
return reference;
}
}
return null;
}
private Coordinate SearchDirection(char[] chars, int x, int y, int direction)
{
// have we ve moved passed the boundary of the puzzle
if (x < 0 || y < 0 || x >= Puzzle.GetLength(1) || y >= Puzzle.GetLength(0))
return null;
if (Puzzle[y, x] != chars[0])
return null;
// when we reach the last character in the word
// the values of x,y represent location in the
// puzzle where the word stops
if (chars.Length == 1)
return new Coordinate(x, y);
// test the next character in the current direction
char[] copy = new char[chars.Length - 1];
Array.Copy(chars, 1, copy, 0, chars.Length - 1);
return SearchDirection(copy, x + directions[direction].X, y + directions[direction].Y, direction);
}
}