扫雷程序,意外的输出
Minesweeper Program, unexpected output
我正在做一个来自 Steven Skiena(编程挑战)的问题(扫雷)。您必须在其中输出与该方块相邻的地雷数量。
#include<iostream>
using namespace std;
int main()
{
int n,m;
cin>>m>>n;
char a[m][n];
for(int i=0;i<m;i++)
{
for (int j = 0; j < n; j++)
{
cin>>a[i][j];
}
}
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if(a[i][j]!='*')
{
int no=0;
if(a[i-1][j-1]=='*')
no++;
else if(a[i][j-1]=='*')
no++;
else if(a[i+1][j-1]=='*')
no++;
else if(a[i+1][j]=='*')
no++;
else if(a[i+1][j+1]=='*')
no++;
else if(a[i][j+1]=='*')
no++;
else if(a[i-1][j+1]=='*')
no++;
else if(a[i-1][j]=='*')
no++;
a[i][j]=(char)no;
}
}
}
for(int i=0;i<m;i++)
{
for (int j=0; j<n; j++)
{
cout<<a[i][j];
}
cout<<endl;
}
return 0;
}
当我尝试运行这个程序时,没有放置地雷的数组是空白的。是不是和整数转字符有关?
一个错误是:
a[i][j]=(char)no;
这不是将一位整数转换为 char
表示的方式。
正确的方法是在整数上加上'0'
:
a[i][j] = no + '0';
之所以可行,是因为数字的字符表示与实际数字值不同。例如,ASCII 整理序列使用 48 作为字符 '0'
,49 用于 '1'
,50 用于 '2'
,等等
因此添加 '0'
,即 48,将为您提供数字的字符表示。
您可以像这样更改您的程序:
我把你的数组改成了整型数组,所有地雷都是-1
。因此,您不必在一个数组中混合使用 int 值和 char 值。有了这个,你必须在输出中用 if 条件处理这个。
#include<iostream>
using namespace std;
int main()
{
int n,m;
cin>>m>>n;
char a[m][n];
for(int i=0;i<m;i++)
{
for (int j = 0; j < n; j++)
{
char in;
cin>>in;
if(in == '*') {
a[i][j] = -1;
} else {
a[i][j] = 0;
}
}
}
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if(a[i][j]!=-1)
{
int no=0;
if(a[i-1][j-1]==-1)
no++;
else if(a[i][j-1]==-1)
no++;
else if(a[i+1][j-1]==-1)
no++;
else if(a[i+1][j]==-1)
no++;
else if(a[i+1][j+1]==-1)
no++;
else if(a[i][j+1]==-1)
no++;
else if(a[i-1][j+1]==-1)
no++;
else if(a[i-1][j]==-1)
no++;
a[i][j]=no;
}
}
}
for(int i=0;i<m;i++)
{
for (int j=0; j<n; j++)
{
if(a[i][j] == -1) {
cout<<" * ";
} else {
cout<<" "<<a[i][j]<<" ";
}
}
cout<<endl;
}
return 0;
}
既然看起来人们在给男人送鱼,我看不出有什么理由不这样做。在计算上更改 no 开始的方式以获得一个很好的解决方案。
char no='0';
我在这里看到一些单独的问题,它们共同导致了您 运行 遇到的问题。
首先,如上所述,一旦您计算了与每个地雷相邻的地雷数量,您当前存储结果的方式将不会按照您期望的方式打印。这里的其他答案建议了几种不同的方法。
其次,您计算相邻地雷的方法(稍微)不正确。让我们看看这段代码:
if(a[i-1][j-1]==-1)
no++;
else if(a[i][j-1]==-1)
no++;
else if(a[i+1][j-1]==-1)
no++;
else if(a[i+1][j]==-1)
no++;
else if(a[i+1][j+1]==-1)
no++;
else if(a[i][j+1]==-1)
no++;
else if(a[i-1][j+1]==-1)
no++;
else if(a[i-1][j]==-1)
no++;
这里你使用的模式 if
/ else if
/ else if
/ ... 意味着 至多一个 这些分支将执行。也就是说,一旦此代码找到地雷,它就会停止查看单元格周围的其他位置以查找其他地雷。解决此问题的一种方法是使其不是 if
/ else if
的链,而只是 if
s:
的常规链
if(a[i-1][j-1]==-1)
no++;
if(a[i][j-1]==-1)
no++;
if(a[i+1][j-1]==-1)
no++;
if(a[i+1][j]==-1)
no++;
if(a[i+1][j+1]==-1)
no++;
if(a[i][j+1]==-1)
no++;
if(a[i-1][j+1]==-1)
no++;
if(a[i-1][j]==-1)
no++;
您甚至可能想考虑改变您的结构,这样您就可以使用双重嵌套的 for 循环一步一步地枚举所有位置,而不是使用一长串 if
语句从你。这将压缩代码并使其更清楚地匹配 "for each adjacent location, if it's a mine, count it as such."
的模式
希望对您有所帮助!
我正在做一个来自 Steven Skiena(编程挑战)的问题(扫雷)。您必须在其中输出与该方块相邻的地雷数量。
#include<iostream>
using namespace std;
int main()
{
int n,m;
cin>>m>>n;
char a[m][n];
for(int i=0;i<m;i++)
{
for (int j = 0; j < n; j++)
{
cin>>a[i][j];
}
}
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if(a[i][j]!='*')
{
int no=0;
if(a[i-1][j-1]=='*')
no++;
else if(a[i][j-1]=='*')
no++;
else if(a[i+1][j-1]=='*')
no++;
else if(a[i+1][j]=='*')
no++;
else if(a[i+1][j+1]=='*')
no++;
else if(a[i][j+1]=='*')
no++;
else if(a[i-1][j+1]=='*')
no++;
else if(a[i-1][j]=='*')
no++;
a[i][j]=(char)no;
}
}
}
for(int i=0;i<m;i++)
{
for (int j=0; j<n; j++)
{
cout<<a[i][j];
}
cout<<endl;
}
return 0;
}
当我尝试运行这个程序时,没有放置地雷的数组是空白的。是不是和整数转字符有关?
一个错误是:
a[i][j]=(char)no;
这不是将一位整数转换为 char
表示的方式。
正确的方法是在整数上加上'0'
:
a[i][j] = no + '0';
之所以可行,是因为数字的字符表示与实际数字值不同。例如,ASCII 整理序列使用 48 作为字符 '0'
,49 用于 '1'
,50 用于 '2'
,等等
因此添加 '0'
,即 48,将为您提供数字的字符表示。
您可以像这样更改您的程序:
我把你的数组改成了整型数组,所有地雷都是-1
。因此,您不必在一个数组中混合使用 int 值和 char 值。有了这个,你必须在输出中用 if 条件处理这个。
#include<iostream>
using namespace std;
int main()
{
int n,m;
cin>>m>>n;
char a[m][n];
for(int i=0;i<m;i++)
{
for (int j = 0; j < n; j++)
{
char in;
cin>>in;
if(in == '*') {
a[i][j] = -1;
} else {
a[i][j] = 0;
}
}
}
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if(a[i][j]!=-1)
{
int no=0;
if(a[i-1][j-1]==-1)
no++;
else if(a[i][j-1]==-1)
no++;
else if(a[i+1][j-1]==-1)
no++;
else if(a[i+1][j]==-1)
no++;
else if(a[i+1][j+1]==-1)
no++;
else if(a[i][j+1]==-1)
no++;
else if(a[i-1][j+1]==-1)
no++;
else if(a[i-1][j]==-1)
no++;
a[i][j]=no;
}
}
}
for(int i=0;i<m;i++)
{
for (int j=0; j<n; j++)
{
if(a[i][j] == -1) {
cout<<" * ";
} else {
cout<<" "<<a[i][j]<<" ";
}
}
cout<<endl;
}
return 0;
}
既然看起来人们在给男人送鱼,我看不出有什么理由不这样做。在计算上更改 no 开始的方式以获得一个很好的解决方案。
char no='0';
我在这里看到一些单独的问题,它们共同导致了您 运行 遇到的问题。
首先,如上所述,一旦您计算了与每个地雷相邻的地雷数量,您当前存储结果的方式将不会按照您期望的方式打印。这里的其他答案建议了几种不同的方法。
其次,您计算相邻地雷的方法(稍微)不正确。让我们看看这段代码:
if(a[i-1][j-1]==-1)
no++;
else if(a[i][j-1]==-1)
no++;
else if(a[i+1][j-1]==-1)
no++;
else if(a[i+1][j]==-1)
no++;
else if(a[i+1][j+1]==-1)
no++;
else if(a[i][j+1]==-1)
no++;
else if(a[i-1][j+1]==-1)
no++;
else if(a[i-1][j]==-1)
no++;
这里你使用的模式 if
/ else if
/ else if
/ ... 意味着 至多一个 这些分支将执行。也就是说,一旦此代码找到地雷,它就会停止查看单元格周围的其他位置以查找其他地雷。解决此问题的一种方法是使其不是 if
/ else if
的链,而只是 if
s:
if(a[i-1][j-1]==-1)
no++;
if(a[i][j-1]==-1)
no++;
if(a[i+1][j-1]==-1)
no++;
if(a[i+1][j]==-1)
no++;
if(a[i+1][j+1]==-1)
no++;
if(a[i][j+1]==-1)
no++;
if(a[i-1][j+1]==-1)
no++;
if(a[i-1][j]==-1)
no++;
您甚至可能想考虑改变您的结构,这样您就可以使用双重嵌套的 for 循环一步一步地枚举所有位置,而不是使用一长串 if
语句从你。这将压缩代码并使其更清楚地匹配 "for each adjacent location, if it's a mine, count it as such."
希望对您有所帮助!