我正在尝试使用2D矢量构建一个简单的扫雷应用程序。首先,我用1和0填充正方形(1' s表示地雷,0' s表示清楚)。
srand(time(NULL));
for (int i = 0; i < battlefield.size(); i++)
{
for (int j = 0; j < battlefield[i].size(); j++)
{
int num = (rand() % 2);
battlefield[i][j] = num;
}
}`
然后,我再次检查向量并计算周围地雷的数量。这就是我遇到问题的地方。我想当它试图检查一个超出界限的广场时,它会爆炸。但是,如果在任何这些检查之前失败。如果在尝试查看当前方块是否等于1时失败。
for (int i = 0; i < battlefield.size(); i++)
{
for (int j = 0; j < battlefield[i].size(); j++)
{
int count = 0;
if (battlefield[i][j] == 1)//mine square
{
if (battlefield[i - 1][j - 1] != 0)
{
count++;
}
if (battlefield[i][j - 1] != 0)
{
count++;
}
if (battlefield[i + 1][j - 1] != 0)
{
count++;
}
if (battlefield[i - 1][j] != 0)
{
count++;
}
if (battlefield[i + 1][j] != 0)
{
count++;
}
if (battlefield[i - 1][j + 1] != 0)
{
count++;
}
if (battlefield[i][j + 1] != 0)
{
count++;
}
if (battlefield[i + 1][j + 1] != 0)
{
count++;
}
battlefield[i][j] = count;
}
}
我不确定为什么会失败,有什么想法?
答案 0 :(得分:1)
制作“CheckTile”功能
bool CheckTile(int i, int j)
{
// check if both i and j are in the map bounds, return false if not
if(i < 0 || i >= battlefield.size() || j < 0 || j >= battlefield.size())
return false;
// return true if the tile is a mine, false if not
return (battlefield[i - 1][j - 1] != 0);
}
基本上用CheckTile调用替换所有if检查的内部。您当前的代码是破坏的,因为您没有对数组进行边界检查,所以当它读取时
if(battlefield[i - 1][j - 1] != 0)
第一次,它试图读取分配内存之外的数组位置(-1,-1),因此出错。用
替换它if(CheckTile(i - 1, j - 1))
它会做同样的事情,但是增加了边界检查保护。
答案 1 :(得分:1)
如果你的我的是0,0你执行的第一次检查将检查-1,-1这是超出范围,实际上炸毁了你的程序。
您需要先检查边界。
答案 2 :(得分:1)
你真的很幸运。访问std::vector
的边界是“未定义的行为”,只有幸运时程序才会停止。
当你运气不好的时候,程序显然“正常工作”而且你一直在添加功能,直到发货日......在股东大会期间它只会在客户机器的宽屏幕上爆炸: - )
在我看来,更简单的实现将是
int i0 = std::max(0, i-1), i1 = std::min(height-1, i+1);
int j0 = std::max(0, j-1); j1 = std::min(width-1, j+1);
int count = 0;
for (int i=i0; i<=i1; i++) {
for (int j=j0; j<=j1; j++) {
if (mine[i][j]) count++;
}
}
基本上首先计算安全边界然后在其中循环,而不是单独指定代码中的所有邻居。