PTA 扫雷游戏 纯c语言


题目概述:

扫雷是一款经典游戏,也是Windows操作系统最早引入的一款游戏,其最为经典的版本是Windows XP操作系统自带的扫雷游戏,曾风靡一个时代,是一代人的永恒记忆。

简单来说,其游戏界面由n行m列方格组成,其中k个方格后面隐藏着地雷。当用户点击一个方格时:

(1)如果该方格后面隐藏着地雷,则游戏结束,用户失败。

(2)如果该方格不是地雷,则该方格被打开:

若该方格与地雷相邻(即该方格上、下、左、右、左上、左下、右上、右下相邻的8个方格内有地雷),则该方格处显示一个数字,表示其周围8个方格中的地雷数。
若该方格未与地雷相邻(即该方格周围8个格子内没有地雷),则该方格的未被打开的邻居(即与该方格上、下、左、右、左上、左下、右上、右下相邻的方格)、邻居的邻居、邻居的邻居的邻居……都会被逐级打开,直到某方格与地雷相邻。这期间每个方格的处理方式同(2)。
(3)当所有没隐藏地雷的方格均被打开(即所有没打开的方格后都有地雷),则游戏结束,用户获胜。

请编写程序从初始界面开始,对于一系列用户的点击,求出点击之后的游戏界面。未打开的方格用-1表示,即游戏初始时为n行m列-1。已打开且未与雷相邻的方格用0表示,已打开且与雷相邻的方格用数字a (1≤ a ≤ 8)表示,即与之相邻的地雷数。

输入格式:

输入第一行是4个正整数n、m、k和l,其中n、m、k的含义如前所述。接下来k行,每行2个整数i和j,表示每个雷的坐标,即雷在第i行第j列的方格里。接下来l行,每行2个整数i和j,表示用户点击信息,即用户点击了第i行第j列的方格。m,n不超过20,k不超过50,l不超过200,0≤i

输出格式:

对于用户的每个点击:(1)如果用户点击的方格是已被打开的方格,则点击无效,忽略该点击。(2)如果点击的方格是地雷,则输出“You lose”,程序退出;(3)如果点击的方格不是地雷,则输出点击后的游戏界面,即n行m列整数,每个整数后一个空格,此时若用户获胜,则再输出“You win”。注:对用户每个有效点击所输出的信息用一个空行间隔。

输入样例1:

5 5 1 1
0 0
4 4

输出样例1:

-1 1 0 0 0 
1 1 0 0 0 
0 0 0 0 0 
0 0 0 0 0 
0 0 0 0 0 
You win

输入样例2:

4 5 1 2
1 2
3 0
1 2

输出样例2:

0 1 -1 1 0 
0 1 -1 1 0 
0 1 1 1 0 
0 0 0 0 0 

You lose

输入样例3:

4 5 1 2
1 2
3 0
0 2

输出样例3:

0 1 -1 1 0 
0 1 -1 1 0 
0 1 1 1 0 
0 0 0 0 0 

0 1 1 1 0 
0 1 -1 1 0 
0 1 1 1 0 
0 0 0 0 0 
You win
#include
#define Rows 22
#define Cols 22
int n,m,k,l;
int data[Rows][Cols];  //数据数组 
int game[Rows][Cols];  //玩家界面数组 

void Init();
void disp();
void dispdata();
void setboom(int a,int b);
void setnumber();
void swap(int x,int y);
int tongji();

//初始化玩家界面 
void Init()
{
	for (int i = 0; i n||y<1||y>m){
        return ;
    }else{
        game[x][y]=data[x][y];
    } 
	if(game[x][y]==0){
		for(int i=x-1;i<=x+1;i++){
			for(int j=y-1;j<=y+1;j++){
				swap(i,j);
			}
		} 
	 }
}

//设置后台元素数据 
void setnumber()
{
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(data[i][j]!=-1)
			{
				if(data[i-1][j-1]==-1)
				   data[i][j]++;
				   
				if(data[i-1][j]==-1)
				   data[i][j]++;
				   
				if(data[i-1][j+1]==-1)
				   data[i][j]++;
				   
				if(data[i][j-1]==-1)
				   data[i][j]++;
				   
				if(data[i][j+1]==-1)
				   data[i][j]++;
				   
				if(data[i+1][j-1]==-1)
				   data[i][j]++;
				   
				if(data[i+1][j]==-1)
				   data[i][j]++;
				   
				if(data[i+1][j+1]==-1)
				   data[i][j]++; 
			}
		}
	} 
}

//统计还有多少个位置没开
int tongji()
{
	int sum=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(game[i][j]==-1){
				sum++;
			} 
		}
	}
	return sum;
}


int main()
{
	Init();
	scanf("%d %d %d %d",&n,&m,&k,&l);//输入数据 
	if(n>=0&&n<=20&&m>=0&&m<=20&&k>=0&&k<=50&&l>=0&&l<=200){
    //将炸弹保存进后台数组 
	for(int i=0;i=0&&a<=n&&b>=0&&b<=m){
            setboom(a,b);
        }
	} 
        
	//设置后台元素 
    setnumber();
    
    //玩家操作
    int x,y;
	for(int i=0;i=0&&x<=n&&y>=0&&y<=m){
          if(data[x+1][y+1]==-1){
			printf("You lose\n"); 
			break;
		}
        //判断重复输入
        if(game[x+1][y+1]!=-1){
            continue;
        }else{
            swap(x+1,y+1);
            dispgame();
            if((tongji())==k){
               printf("You win\n");
               break;
            }else{
                printf("\n");
            }
        }
    }
  }
}
	return 0;
}