如何计算给定索引周围 bool[] 中的真实值?
How to count true values in a bool[,] around a given index?
我找到了我几年前写的一个简单的扫雷程序,如果您可以优化以下代码,我很感兴趣,因为它看起来一点也不好。
以下方法用于检查索引是否超出范围和returns所请求索引的值:
private static bool IsMineOnCoords(bool[,] field, int posI, int posJ)
{
if (posI < 0 || posI > field.GetLength(0) - 1 || posJ < 0 || posJ > field.GetLength(1) - 1) return false;
return field[posI, posJ];
}
我在 8 个 if 语句中为给定索引周围的每个位置调用此方法:
int count = 0;
if (IsMineOnCoords(field, posI + 1, posJ)) count++;
if (IsMineOnCoords(field, posI - 1, posJ)) count++;
if (IsMineOnCoords(field, posI + 1, posJ + 1)) count++;
if (IsMineOnCoords(field, posI + 1, posJ - 1)) count++;
if (IsMineOnCoords(field, posI - 1, posJ + 1)) count++;
if (IsMineOnCoords(field, posI - 1, posJ - 1)) count++;
if (IsMineOnCoords(field, posI, posJ + 1)) count++;
if (IsMineOnCoords(field, posI, posJ - 1)) count++;
有没有更好的方法可以做到这一点?
使用这样的东西:
for (int i = posI - 1; i <= posI + 1; i++)
{
for (int j = posJ - 1; j <= posJ + 1; j++)
{
if (!(i == posI && j == posJ) && IsMineOnCoords(field, i, j))
{
count++;
}
}
}
我认为它很好,据我所知它应该执行得很快,尤其是因为短路。
条件或运算符 (||) 对其布尔操作数执行逻辑或。如果第一个操作数的计算结果为真,则不会计算第二个操作数。如果第一个操作数的计算结果为假,则第二个运算符会确定整个 OR 表达式的计算结果是真还是假。
像这样的东西应该适合你。基本上,您只需计算出周围单元格的 i
和 j
坐标的最小值和最大值,然后循环遍历这些单元格,将 true
值相加(但跳过传入的单元格):
private static int GetSurroundingBombCount(bool[,] field, int posI, int posJ)
{
var surroundingBombCount = 0;
// Get the minimum and maximum i and j coordinates of the surrounding cells
var iMin = posI - 1 < 0 ? 0 : posI - 1;
var iMax = posI + 1 > field.GetUpperBound(0) ? posI : posI + 1;
var jMin = posJ - 1 < 0 ? 0 : posJ - 1;
var jMax = posJ + 1 > field.GetUpperBound(1) ? posJ : posJ + 1;
// Loop through these cells and increment our counter for each true value
// unless we hit the initial cell, in which case we just continue
for (int i = iMin; i <= iMax; i++)
{
for (int j = jMin; j <= jMax; j++)
{
if (i == posI && j == posJ) continue;
if (field[i, j]) surroundingBombCount++;
}
}
return surroundingBombCount;
}
那么用法将类似于:
int surroundingBombCount = GetSurroundingBombCount(field, posI, posJ);
我用这段代码来测试它,它会生成一个 3x3 的网格(你可以随意调整它),在单元格上放置随机炸弹,然后显示两个网格,以便你可以直观地检查它们:一个网格与炸弹位置,以及另一个带有计数的网格:
private static void Main()
{
bool[,] field = new bool[3, 3];
Random rnd = new Random();
// The lower this number, the more bombs will be placed.
// Must be greater than one, should be greater than 2.
// If set to '2', all cells will contain a bomb, which isn't fun.
int bombScarcity = 10;
// Assign random bombs
for (int i = 0; i < field.GetLength(0); i++)
{
for (int j = 0; j < field.GetLength(1); j++)
{
field[i, j] = rnd.Next(1, bombScarcity) % (bombScarcity - 1) == 0;
}
}
// Show bomb locations
Console.WriteLine("\nBomb Locations:\n");
for (int i = 0; i < field.GetLength(0); i++)
{
for (int j = 0; j < field.GetLength(1); j++)
{
Console.Write(field[i, j] ? " T" : " F");
if ((j + 1) % field.GetLength(1) == 0) Console.WriteLine();
}
}
// Show bomb counts
Console.WriteLine("\nBomb Counts:\n");
for (int i = 0; i < field.GetLength(0); i++)
{
for (int j = 0; j < field.GetLength(1); j++)
{
Console.Write($" {GetSurroundingBombCount(field, i, j)}");
if ((j + 1) % field.GetLength(1) == 0) Console.WriteLine();
}
}
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
输出
为了好玩 10 x 10:
我找到了我几年前写的一个简单的扫雷程序,如果您可以优化以下代码,我很感兴趣,因为它看起来一点也不好。
以下方法用于检查索引是否超出范围和returns所请求索引的值:
private static bool IsMineOnCoords(bool[,] field, int posI, int posJ)
{
if (posI < 0 || posI > field.GetLength(0) - 1 || posJ < 0 || posJ > field.GetLength(1) - 1) return false;
return field[posI, posJ];
}
我在 8 个 if 语句中为给定索引周围的每个位置调用此方法:
int count = 0;
if (IsMineOnCoords(field, posI + 1, posJ)) count++;
if (IsMineOnCoords(field, posI - 1, posJ)) count++;
if (IsMineOnCoords(field, posI + 1, posJ + 1)) count++;
if (IsMineOnCoords(field, posI + 1, posJ - 1)) count++;
if (IsMineOnCoords(field, posI - 1, posJ + 1)) count++;
if (IsMineOnCoords(field, posI - 1, posJ - 1)) count++;
if (IsMineOnCoords(field, posI, posJ + 1)) count++;
if (IsMineOnCoords(field, posI, posJ - 1)) count++;
有没有更好的方法可以做到这一点?
使用这样的东西:
for (int i = posI - 1; i <= posI + 1; i++)
{
for (int j = posJ - 1; j <= posJ + 1; j++)
{
if (!(i == posI && j == posJ) && IsMineOnCoords(field, i, j))
{
count++;
}
}
}
我认为它很好,据我所知它应该执行得很快,尤其是因为短路。
条件或运算符 (||) 对其布尔操作数执行逻辑或。如果第一个操作数的计算结果为真,则不会计算第二个操作数。如果第一个操作数的计算结果为假,则第二个运算符会确定整个 OR 表达式的计算结果是真还是假。
像这样的东西应该适合你。基本上,您只需计算出周围单元格的 i
和 j
坐标的最小值和最大值,然后循环遍历这些单元格,将 true
值相加(但跳过传入的单元格):
private static int GetSurroundingBombCount(bool[,] field, int posI, int posJ)
{
var surroundingBombCount = 0;
// Get the minimum and maximum i and j coordinates of the surrounding cells
var iMin = posI - 1 < 0 ? 0 : posI - 1;
var iMax = posI + 1 > field.GetUpperBound(0) ? posI : posI + 1;
var jMin = posJ - 1 < 0 ? 0 : posJ - 1;
var jMax = posJ + 1 > field.GetUpperBound(1) ? posJ : posJ + 1;
// Loop through these cells and increment our counter for each true value
// unless we hit the initial cell, in which case we just continue
for (int i = iMin; i <= iMax; i++)
{
for (int j = jMin; j <= jMax; j++)
{
if (i == posI && j == posJ) continue;
if (field[i, j]) surroundingBombCount++;
}
}
return surroundingBombCount;
}
那么用法将类似于:
int surroundingBombCount = GetSurroundingBombCount(field, posI, posJ);
我用这段代码来测试它,它会生成一个 3x3 的网格(你可以随意调整它),在单元格上放置随机炸弹,然后显示两个网格,以便你可以直观地检查它们:一个网格与炸弹位置,以及另一个带有计数的网格:
private static void Main()
{
bool[,] field = new bool[3, 3];
Random rnd = new Random();
// The lower this number, the more bombs will be placed.
// Must be greater than one, should be greater than 2.
// If set to '2', all cells will contain a bomb, which isn't fun.
int bombScarcity = 10;
// Assign random bombs
for (int i = 0; i < field.GetLength(0); i++)
{
for (int j = 0; j < field.GetLength(1); j++)
{
field[i, j] = rnd.Next(1, bombScarcity) % (bombScarcity - 1) == 0;
}
}
// Show bomb locations
Console.WriteLine("\nBomb Locations:\n");
for (int i = 0; i < field.GetLength(0); i++)
{
for (int j = 0; j < field.GetLength(1); j++)
{
Console.Write(field[i, j] ? " T" : " F");
if ((j + 1) % field.GetLength(1) == 0) Console.WriteLine();
}
}
// Show bomb counts
Console.WriteLine("\nBomb Counts:\n");
for (int i = 0; i < field.GetLength(0); i++)
{
for (int j = 0; j < field.GetLength(1); j++)
{
Console.Write($" {GetSurroundingBombCount(field, i, j)}");
if ((j + 1) % field.GetLength(1) == 0) Console.WriteLine();
}
}
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
输出
为了好玩 10 x 10: