题目不难,就是比较耗时间,从看题目到debug我大概用了3个半小时
这里主要是记录一下我当时没看懂的点:
1.什么叫空白方块?
空白方块就是说对于每个方块来说,它有3种状态:
- 被标记为“探明”
- 被插了旗子
- 既没有被探明,也没有被插旗子,这种状态下的方块就叫空白方块
注意,方块的状态和这个方块有没有炸弹是无关的
上代码(测试用例我稍后会传到CSDN上):
(其实还有点小bug,过不了acwing的评测,但是还是可以过相当一部分测试用例的)
#include <bits/stdc++.h>
#define maxn 1005
using namespace std;
struct node{
int x,y,c;
};
bool comp(node a,node b){
if(a.x!=b.x)
return a.x<b.x;
else
return a.y<b.y;
}
int n,m;
char qipan[maxn][maxn];
char f_qipan[maxn][maxn];//带标记的棋盘,初始时全为0
int bombnum[maxn][maxn];
int flagnum[maxn][maxn];
char op[10];
int boom;
int finish;
int x,y;
int NUM_OF_CELLS;
vector<node> detec_cell;//装入那些探明的单元格
int TOTAL_STEP;
node tmp;
//判断x,y坐标是否合法
bool judge_x_y(int x,int y){
return x>=1&&x<=n&&y>=1&&y<=m;
}
void decflag(int x,int y){
f_qipan[x][y]=0;
if(judge_x_y(x-1,y-1)&&flagnum[x-1][y-1]>=1)
flagnum[x-1][y-1]--;
if(judge_x_y(x-1,y)&&flagnum[x-1][y]>=1)
flagnum[x-1][y]--;
if(judge_x_y(x-1,y+1)&&flagnum[x-1][y+1]>=1)
flagnum[x-1][y+1]--;
if(judge_x_y(x,y-1)&&flagnum[x][y-1]>=1)
flagnum[x][y-1]--;
if(judge_x_y(x,y+1)&&flagnum[x][y+1]>=1)
flagnum[x][y+1]--;
if(judge_x_y(x+1,y-1)&&flagnum[x+1][y-1]>=1)
flagnum[x+1][y-1]--;
if(judge_x_y(x+1,y)&&flagnum[x+1][y]>=1)
flagnum[x+1][y]--;
if(judge_x_y(x+1,y+1)&&flagnum[x+1][y+1]>=1)
flagnum[x+1][y+1]--;
}
void incflag(int x,int y){
f_qipan[x][y]='f';
if(judge_x_y(x-1,y-1))
flagnum[x-1][y-1]++;
if(judge_x_y(x-1,y))
flagnum[x-1][y]++;
if(judge_x_y(x-1,y+1))
flagnum[x-1][y+1]++;
if(judge_x_y(x,y-1))
flagnum[x][y-1]++;
if(judge_x_y(x,y+1))
flagnum[x][y+1]++;
if(judge_x_y(x+1,y-1))
flagnum[x+1][y-1]++;
if(judge_x_y(x+1,y))
flagnum[x+1][y]++;
if(judge_x_y(x+1,y+1))
flagnum[x+1][y+1]++;
}
bool judgefinish(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(qipan[i][j]=='.'&&f_qipan[i][j]!='d'){
finish=0;
return false;
}
}
}
finish=1;
return true;
}
void saolei(int x,int y){
if(!judge_x_y(x,y))
return;
if(qipan[x][y]=='*'){
printf("boom\n");
boom=1;
return;
}
if(f_qipan[x][y]=='d'){
return;
}
f_qipan[x][y]='d';
NUM_OF_CELLS++;
tmp.x=x;
tmp.y=y;
tmp.c=bombnum[x][y];
detec_cell.push_back(tmp);
if(bombnum[x][y]==0){
//对相邻的未探明方块开始扫雷
if(judge_x_y(x-1,y-1)&&f_qipan[x-1][y-1]!='d'){
if(f_qipan[x-1][y-1]=='f')
decflag(x-1,y-1);
saolei(x-1,y-1);
}
if(judge_x_y(x-1,y)&&f_qipan[x-1][y]!='d'){
if(f_qipan[x-1][y]=='f')
decflag(x-1,y);
saolei(x-1,y);
}
if(judge_x_y(x-1,y+1)&&f_qipan[x-1][y+1]!='d'){
if(f_qipan[x-1][y+1]=='f')
decflag(x-1,y+1);
saolei(x-1,y+1);
}
if(judge_x_y(x,y-1)&&f_qipan[x][y-1]!='d'){
if(f_qipan[x][y-1]=='f')
decflag(x,y-1);
saolei(x,y-1);
}
if(judge_x_y(x,y+1)&&f_qipan[x][y+1]!='d'){
if(f_qipan[x][y+1]=='f')
decflag(x,y+1);
saolei(x,y+1);
}
if(judge_x_y(x+1,y-1)&&f_qipan[x+1][y-1]!='d'){
if(f_qipan[x+1][y-1]=='f')
decflag(x+1,y-1);
saolei(x+1,y-1);
}
if(judge_x_y(x+1,y)&&f_qipan[x+1][y]!='d'){
if(f_qipan[x+1][y]=='f')
decflag(x+1,y);
saolei(x+1,y);
}
if(judge_x_y(x+1,y+1)&&f_qipan[x+1][y+1]){
if(f_qipan[x+1][y+1]=='f')
decflag(x+1,y+1);
saolei(x+1,y+1);
}
}
}
void flagOperate(int x,int y){
if(f_qipan[x][y]=='d'){
printf("swept\n");
return;
}
if(f_qipan[x][y]=='f'){
//对它的八联通块的个数进行消减
f_qipan[x][y]=0;
decflag(x,y);
printf("cancelled\n");
return;
}
if(f_qipan[x][y]!='f'&&f_qipan[x][y]!='d'){
incflag(x,y);
printf("success\n");
return;
}
}
void printResult(){
sort(detec_cell.begin(),detec_cell.end(),comp);
if(NUM_OF_CELLS==0){
printf("no_cell_detected\n");
}
else{
printf("%d cell(s) detected\n",NUM_OF_CELLS);
}
int len=detec_cell.size();
for(int i=0;i<len;i++){
printf("%d %d %d\n",detec_cell[i].x,detec_cell[i].y,detec_cell[i].c);
}
}
void sweepOperate(int x,int y){
NUM_OF_CELLS=0;
detec_cell.clear();
if(f_qipan[x][y]=='d'){
printf("swept\n");
return;
}
if(f_qipan[x][y]=='f'){
printf("flagged\n");
return;
}
saolei(x,y);
if(boom)
return;
//输出扫雷反馈
printResult();
//判断是否全部扫完了
judgefinish();
}
void dsweepOperate(int x,int y){
NUM_OF_CELLS=0;
detec_cell.clear();
if(f_qipan[x][y]!='d'){
printf("not swept\n");
return;
}
if(bombnum[x][y]==0||flagnum[x][y]!=bombnum[x][y]){
printf("failed\n");
return;
}
//对八连通块进行扫雷过程
if(judge_x_y(x-1,y-1)&&f_qipan[x-1][y-1]==0){
saolei(x-1,y-1);
if(boom)
return;
}
if(judge_x_y(x-1,y)&&f_qipan[x-1][y]==0){
saolei(x-1,y);
if(boom)
return;
}
if(judge_x_y(x-1,y+1)&&f_qipan[x-1][y+1]==0){
saolei(x-1,y+1);
if(boom)
return;
}
if(judge_x_y(x,y-1)&&f_qipan[x][y-1]==0){
saolei(x,y-1);
if(boom)
return;
}
if(judge_x_y(x,y+1)&&f_qipan[x][y+1]==0){
saolei(x,y+1);
if(boom)
return;
}
if(judge_x_y(x+1,y-1)&&f_qipan[x+1][y-1]==0){
saolei(x+1,y-1);
if(boom)
return;
}
if(judge_x_y(x+1,y)&&f_qipan[x+1][y]==0){
saolei(x+1,y);
if(boom)
return;
}
if(judge_x_y(x+1,y+1)&&f_qipan[x+1][y+1]==0){
saolei(x+1,y+1);
if(boom)
return;
}
//
printResult();
judgefinish();
}
void quitOperate(int x,int y){
}
int main(){
scanf("%d%d",&n,&m);
// getchar();
memset(qipan,'.',sizeof qipan);
memset(flagnum,0,sizeof flagnum);
memset(bombnum,0,sizeof bombnum);
for(int i=1;i<=n;i++){
scanf("%s",qipan[i]+1);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
//头上一行
bombnum[i][j]=(qipan[i-1][j-1]=='*')+
(qipan[i-1][j]=='*')+
(qipan[i-1][j+1]=='*')+
//这一行
(qipan[i][j-1]=='*')+
(qipan[i][j+1]=='*')+
//下一行
(qipan[i+1][j-1]=='*')+
(qipan[i+1][j]=='*')+
(qipan[i+1][j+1]=='*');
}
}
scanf("%s",op);
TOTAL_STEP=1;
while(strcmp(op,"Quit")!=0&&boom==0){
scanf("%d%d",&x,&y);
string sop=op;
if(sop=="Flag"){
flagOperate(x,y);
}
else if(sop=="Sweep"){
sweepOperate(x,y);
if(finish||boom)
break;
}
else if(sop=="DSweep"){
dsweepOperate(x,y);
if(finish||boom)
break;
}
scanf("%s",op);
TOTAL_STEP++;
}
if(strcmp(op,"Quit")==0){
printf("give up\n");
}
else if(boom==1){
printf("game over\n");
}
else if(finish==1){
printf("finish\n");
}
printf("total step %d\n",TOTAL_STEP);
}