清华2017上机题目-扫雷

14 篇文章 1 订阅

题目不难,就是比较耗时间,从看题目到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);

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值