我最近一直在学习Python,但是最近想做一个涉及2D数组的项目,所以我决定切换到C#(很抱歉,如果我的代码很差)
基本上我正在写一个为我做填字游戏的程序。
i
迭代顶部/底部j
从左到右迭代我发现i
想要的第一个字母 - 让我们称之为“keyletter”
现在我需要查看它周围的所有8个空格。如果i/j
位置是[1,2]
,我首先看[0,2]
。
在我的代码中,我想将i
从1
更改为0
,并打印,(如果这是正确的字母)第二个字母是:[0,2]
一旦我将i
从1
更改为0
并尝试打印,它就会吐出一百万次然后卡住了。
public static void Main(string[] args)
{
string keyLetter = "g";
string keyLetter2 = "b";
string[,] crossword = new string[,]
{
{ "a", "b", "c", "d" },
{ "e", "f", "g", "h" },
{ "a", "e", "b", "c" },
{ "i", "j", "k", "l" }
};
for (int i = 0; i < crossword.GetLength(0); i++)
{
for (int j = 0; j < crossword.GetLength(1); j++)
{
if (keyLetter == crossword[i, j])
{
Console.Write(keyLetter + " is [" + i + ", " + j + "]");
Console.WriteLine();
Console.WriteLine();
Console.Write("i is: " + i);
Console.WriteLine();
Console.Write("j is: " + j);
Console.WriteLine();
if (keyLetter2 == crossword[i - 1, j])
{
// i--;
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i + 1, j])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
/*
else if (keyLetter2 == crossword[i + 1, j - 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i, j - 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i - 1, j - 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i + 1, j + 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i, j + 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i - 1, j + 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}*/
Console.WriteLine();
}
}
}
}
我有它设置如下:
问题在于声明
// if(keyLetter2 == crossword [i-1,j])
这里,如果矩阵是这样的
"
a b c
d e f
我
"
并且假设你想要搜索模式“ba”,那么很明显你会找到b,因此我将为0而j将为1.现在,你要做(i-1)将为-1(那里)没有负面索引),因此错误。
执行此操作的最佳方法是检查i或j是否已经为0。如果它们是0,那么你不需要i-1或j-1,你可以像“if(i!= 0)然后if(keyLetter2 == crossword [i-1,j])... “
我看不到任何无限循环,但运行时异常(IndexOutOfRangeException
)at
if (keyLetter2 == crossword[i-1, j]) {...} // if i == 0
...
else if (keyLetter2 == crossword[i+1, j]) {...} // if i == crossword.GetLength(0) - 1
让我们摆脱这些异常并刷新循环:
for (int i = 0; i < crossword.GetLength(0); ++i)
for (int j = 0; j < crossword.GetLength(1); ++j)
if (keyLetter == crossword[i, j]) {
// Keep you messages being readable with a help of string interpolation - $""
Console.WriteLine(string.Join(Environment.NewLine,
$"{keyLetter} is [{i}, {j}]",
""
$"i is: {i}",
""
$"j is: {j}",
""
));
// Do not repeat yourself: if you want 4 neighbors to test
for (int neighbor = 0; neighbor < 4; ++neighbor) {
int ii = i + (neighbor % 2) * (neighbor - 1);
int jj = j + (1 - neighbor % 2) * (neighbor - 1);
// Check indexes ii, jj before addressing [ii, jj]
if (ii >= 0 && ii < crossword.GetLength(0) &&
jj >= 0 && jj < crossword.GetLength(1) &&
keyLetter2 == crossword[ii, jj]) {
Console.Write($"[i/j] position for {keyLetter2} is [{i}, {j}]");
// In case we want at most one neighbor; comment it out if we want all of them
break;
}
}
}
如果你有8
(不是4
)邻居检查
...
bool found = false;
for (int ii = Math.Max(0, i - 1); ii <= Math.Min(i + 1, crossword.GetLength(0)) && !found; ++ii)
for (int jj = Math.Max(0, j - 1); jj <= Math.Min(j + 1, crossword.GetLength(0)) && !found; ++jj) {
if ((ii != i || jj != j) && keyLetter2 == crossword[ii, jj])) {
Console.Write($"[i/j] position for {keyLetter2} is [{i}, {j}]");
// In case we want at most one neighbor; comment it out if we want all of them
found = true;
}
}
我会采取一种稍微不同的方法,即将“邻居搜索”委托给辅助方法。您可以将数组,应搜索其邻居的单元格以及您要搜索的值传递给此方法。
因为一个单元格项由两个整数坐标定义,并且因为有一个现有的Point
结构,我们可以使用它有两个整数属性(X
和Y
),我用它来表示我们数组中的一个单元格。
辅助函数的工作原理是确定X
和Y
的最小值,我们正在搜索的邻居通过从1
和X
值中减去Y
。然后我们需要确保这个结果不小于0
,以确保我们保持在数组的范围内。
同样,我们添加1
来获取最大值,并确保它不大于数组的上限。
最后,我们在List<Point>
中返回匹配列表(如果找到的话):
public static List<Point> GetNeighborMatches(string[,] grid, Point item, string valueToFind)
{
var result = new List<Point>();
// if our grid is empty or the item isn't in it, return an empty list
if (grid == null || grid.Length == 0 ||
item.X < 0 || item.X > grid.GetUpperBound(0) ||
item.Y < 0 || item.Y > grid.GetUpperBound(1))
{
return result;
}
// Get min and max values of x and y for searching
var minX = Math.Max(item.X - 1, 0);
var maxX = Math.Min(item.X + 1, grid.GetUpperBound(0));
var minY = Math.Max(item.Y - 1, 0);
var maxY = Math.Min(item.Y + 1, grid.GetUpperBound(1));
// Loop through all neighbors to find a match
for (int x = minX; x <= maxX; x++)
{
for (int y = minY; y <= maxY; y++)
{
// Continue looping if we're on the 'item'
if (x == item.X && y == item.Y) continue;
// If this is a match, add it to our list
if (grid[x, y] == valueToFind) result.Add(new Point(x, y));
}
}
// Return all the matching neighbors
return result;
}
现在我们可以在现有代码中使用这个辅助方法:
public static void Main(string[] args)
{
string keyLetter = "g";
string keyLetter2 = "b";
string[,] crossword = new string[,]
{
{ "a", "b", "c", "d" },
{ "e", "f", "g", "h" },
{ "a", "e", "b", "c" },
{ "i", "j", "k", "l" }
};
for (int i = 0; i < crossword.GetLength(0); i++)
{
for (int j = 0; j < crossword.GetLength(1); j++)
{
if (keyLetter == crossword[i, j])
{
// we found a match for our first letter!
Console.WriteLine("The first value (" + keyLetter + ") is at [" +
i + ", " + j + "]");
// get neighboring matches for keyLetter2
List<Point> matches = GetNeighborMatches(crossword,
new Point(i, j), keyLetter2);
// Output our matches if we found any
if (matches.Any())
{
foreach (var match in matches)
{
Console.WriteLine("The second value (" + keyLetter2 +
") is at [" + match.X + ", " + match.Y + "]");
}
}
else
{
Console.WriteLine("No match was found for '" + keyLetter2 +
"' near [" + i + ", " + j + "]");
}
}
}
}
}
产量