C语言:用函数和数组实践-扫雷游戏

https://mp.csdn.net/mp_blog/creation/editor/135676438

1.扫雷游戏分析和设计。

  ●使用控制台实现经典扫雷游戏

  ●游戏可以通过菜单进行开始游戏还是退出游戏

  ●扫雷的棋盘是9*9的格子中进行

  ●默认随机布置十个雷

●可以排查雷

        ○如果所排查位置不是雷,就显示周围有几个雷

        ○如果位置是雷,就炸死游戏结束

        ○把十个雷的位置都找出来,则排雷成功,游戏结束

游戏界面:

游戏初始界面

 

游戏开始排雷界面   

    

                                             游戏排雷失败界面       

2.游戏分析和设计

扫雷过程布置的雷和排查出的雷需要储存起来。所以我们需要数据结构来储存这些信息。因为是在9*9的格子中进行扫雷,所以我们联想到可以用二维数组来储存这些信息 。       

那我们如何在这空格中确定是雷还是不是雷呢?

于是我们可以把不是雷的地方用0代替,把雷的地方用1代替。这样就可以更好的排查雷了。

     

如果我们要排查(2,5)这个坐标是不是雷(为0不是雷) ,于是我们就要把这个坐标周围八个位置(如图黄色的一圈)的雷的个数统计出来。

如果排查(8,6)这个位置的雷,此时我们会发现一个问题,如果(8,6)这个位置不是雷,统计周围雷的数量时(如上图所示)会发现下面一部分已经越界了,为了解决这个问题,我们可以将二维数组扩大一圈(创建成11*11),但是雷还是布置在中间9*9的格子里面,周围的一圈不用布置雷就行啦。     

我们继续分析,当我们排查(3,6)的位置,这个坐标不是雷,统计周围雷的个数为1,并打印出来,作为排雷重要参考信息,但是打印在哪呢?如果还是打印在上面的数组中,(3,6)的位置就是1,那么这个1代表这个位置是雷还是代表周围雷的个数呢?这样就会产生混淆。

这里我们肯定有办法解决,比如:雷和非雷的信息不要使用数字,使用某些字符就行,这样就避免冲突了,但是这样做棋盘上有雷和非雷的信息,还有排查出的雷的个数信息,就比较混杂,不够方便。这里我们采用另外一种方案,我们专门给一个棋盘(对应一个数组mine)存放布置好的雷的信息,再给另外一个棋盘(对应另外一个数组show)存放排查出的雷的信息。这样就互不干扰了,把雷布置到mine数组,在mine数组中排查雷,排查出的数据存放在show数组,并且打印show数组的信息给后期排查参考。

同时为了保持神秘,show数组开始时初始化为字符'*,为了保持两个数组的类型一致,可以使用同一套函数处理,mine数组最开始也初始化为字符‘0',布置雷改成'1'。如下如:

                                                                mine数组                       

                                                

                                                              show数组

mine数组用来存放布置好的雷的信息,而show数组则是用来存放排查出雷的个数的信息。

同时show数组在每排完一颗雷后,都需要打印一次,让玩家继续排雷。但是mine由于存放着雷的位置信息,就不能打印出来(打印出来就算作弊啦)

下面是我的代码实现:

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS ROW+2
#define number 10
//排查雷
void findmind(char arr[ROWS][COLS],char show[ROWS][COLS],int x,int y);
//寻找周围的雷 
int getmind(char arr[ROWS][COLS],int x,int y); 
//开始埋雷
void setmind(char arr[ROWS][COLS],int row,int col);
//初始化棋盘函数
void csh(char arr[ROWS][COLS],int row,int col,char s);
//打印棋盘 
void display(char arr[ROWS][COLS],int row,int col);

void findmind(char arr[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
	int x,y;
	int win=0;
	while(win<ROW*COL-number)
	{
		printf("请输入你要排查的坐标,并用空格隔开:");
		scanf("%d%d",&x,&y);
		if(x<=ROW&&x>=1&&y<=COL&&y>=1)
		{
			if(arr[x][y]=='0')
			{//不是雷统计雷的个数
			 int z=getmind(arr,x,y);
				show[x][y]=z+'0';
				display(show,ROW,COL);
				 system("cls");
				 display(show,ROW,COL);
				win++;
			}
			else
			{
				printf("你已经被雷炸死了!!!\n");
				break;
			}
		}
		else
		{
			printf("输入错误,请重新输入:");
		}
	}
	if(win==ROW*COL-number) 
	{
		printf("恭喜你,扫雷游戏通关!!!");
		display(arr,ROW,COL);
	}
}

int getmind(char arr[ROWS][COLS],int x,int y)
{
  int z=arr[x-1][y-1]
+arr[x-1][y]
+arr[x-1][y+1]
+arr[x][y-1]
+arr[x][y+1]
+arr[x+1][y-1]
+arr[x+1][y]
+arr[x+1][y+1]-8*'0';
return z;
} 

void setmind(char arr[ROWS][COLS],int row,int col)
{
	int count=number;
	while(count)
	{
		int x=rand()%row+1;
		int y=rand()%col+1;
		if(arr[x][y]=='0')
		{
			arr[x][y]='1';
			count--;
		}
		
	}
 } 

void csh(char arr[ROWS][COLS],int row,int col,char s) 
{
	for(int i=0;i<=row;i++)
	{
		for(int j=0;j<=col;j++)
		{
			arr[i][j]=s;
		}
	}
}

void display(char arr[ROWS][COLS],int row,int col)
{
	int i=0,j=0;
	printf("-------扫雷游戏-------\n");
	for(i=0;i<=row;i++)
	{
		printf("%d ",i);
	}	
	printf("\n");
	for(i=1;i<=row;i++)
	{
		printf("%d ",i);
		for(j=1;j<=9;j++)
		{
			printf("%c ",arr[i][j]);
		}
		printf("\n");
	}
}
void game()
{
	 char mine[ROWS][COLS]={0};
	 char show[ROWS][COLS]={0};
	 //初始化数组
	 csh(mine,ROWS,COLS,'0'); 
	 csh(show,ROWS,COLS,'*');
	 //打印棋盘
	// display(mine,ROW,COL);
	 display(show,ROW,COL); 
	 //设置十个雷
	 setmind(mine,ROW,COL); 
	 //display(mine,ROW,COL);
	 //排查雷
	 findmind(mine,show,ROW,COL);
}

void menu()
{
	printf("******1.开始游戏******\n");
	printf("******0.退出游戏******\n");
}
void test()
{
	srand((unsigned int)time(NULL));//随机数的生成器,方便后续随机生成10个雷 
	int input=0;
	do
	{
		menu();
		printf("请做出你的选择:");
		scanf("%d",&input);
		switch(input)
		{
		 case 1: game ();break;
		 case 0:printf("退出游戏\n");break; 
		 default:printf("你输入的值有误,请重新输入\n"); 
		}
	}
	while(input);
} 
int main()
{
	test();
	return 0;
}

如果有什么问题希望大家能够提出来,谢谢大家。

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值