c语言扫雷游戏----(数组与循环的应用)

1. 扫雷游戏分析和设计

1.1 扫雷游戏的功能说明

(1) 使⽤控制台实现经典的扫雷游戏
(2) 游戏可以通过菜单实现继续玩或者退出游戏
(3 )扫雷的棋盘是9*9的格⼦
(4) 默认随机布置10个雷
(5)可以排查雷
◦ 如果位置不是雷,就显⽰周围有⼏个雷
◦ 如果位置是雷,就炸死游戏结束
◦ 把除10个雷之外的所有雷都找出来,排雷成功,游戏结束

2、设计程序的大体框架

1、首先是设计菜单,就是利用switch语句和do while循环来实现继续完或退出游戏。
2、设计棋盘,第一考虑就是如何存储信息,雷和非雷和隐藏时的标志还有该位置旁边有几个雷等等信息,不难发现我们需要一个二维数组的方式去存放,那么又该如何用不同的标志去区分它呢。
如果我们用一个二维数组,就会发现若用数字代表雷和非雷,就会出现与该位置有几个雷的信息重复的情况;若用字符代表,则程序的就会变得很复杂。
所以我们就想到了用两个二维数组,一个用来布置雷,一个用来显示信息。
3、定义好数组以后,就开始初始化棋盘,然后开始打印9*9的棋盘。利用for循环来打印二维数组。
4、有了棋盘以后,就开始存放雷,要做到随机存放,我们不难联想到了rand和srand两个函数,用来生成随机值,进行随机的放雷,利用while循环放n个雷。
5、布置好雷以后,就开始实现玩游戏的逻辑,因为出现了多个情况,所以用if-else if-else语句来执行。
如果这个位置是雷,就输出,break结束循环;如果这个位置不是雷就显示旁边有几个雷,这个计算的过程可以交给一个函数来实现,利用嵌套;把除10个雷之外的所有雷都找出来,排雷成功,游戏结束。这其中也是一个循环,可以用while循环来是实现

3、详细的代码分析

(1)游戏可以通过菜单实现继续玩或者退出游戏

#include <stdio.h>
void menu()
{
	printf("*********************\n");
	printf("******1.play*********\n");
	printf("******2.exit*********\n");
	printf("*********************\n");

}
int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请输入>:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			
			break;
		case 0:
			printf("游戏结束\n");
			break;
		default:
			printf("请重新输入\n");
			break;

		}
	} while (input);
}

在这里插入图片描述

(2)扫雷的棋盘是9*9的格子

//将棋盘初始化
void IntBoard(char board[ROWS][COLS],int rows, int cols, char set)
{
	int i = 0;
	for (i = 0;i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
//打印棋盘
void DispalyBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	printf("--------扫雷游戏-------\n");
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1;i <= row;i++)
	{
		printf("%d ", i);
		int j = 0;
		for(j = 1; j <=col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}
void game()
{
	/*定义数组存放创造棋盘*/
	char mine[ROWS][COLS];//存放布置好的雷
	char show[ROWS][COLS];//存放排查出的雷
	//初始化棋盘
	IntBoard(mine,ROWS,COLS,'0');
	IntBoard(show, ROWS, COLS, '*');
	/*打印棋盘*/
	DispalyBoard(show,ROW,COL);
	DispalyBoard(mine, ROW, COL);



}

这里需要注意的是
1、ROWS和COLS,还有ROW和COL都是在头文件里面宏定义好的,这样写的目的是为了使得代码更加灵活,可以改变棋盘的大小,这里面的ROWS=COLS=11,ROW=COL=9(为了避免角落里判断数组内容的时,出现越界的现象,所以定义要比我们实际使用的棋盘的行列数多)
2、函数传参的时候因为两个数组定义的都为char类型,为了初始化方便一些,所以就多传参了一个字符‘0’或‘*’,这样就用一个函数就实现了两个数组的初始化。
3、打印棋盘函数传参的时候要传ROWS和COLS,切记不可传参为ROW和COL

实现的效果如下:
在这里插入图片描述

(3)默认随机布置10个雷

这里用到两个函数rand和srand函数,这点已经在猜数字游戏已经具体讲解过了,这里就不再进行过多的阐述,感兴趣的可以看那一章节的内容。

//srand((unsigned int)time(NULL));放在主函数用一次就够了,
//与rand()一起产生随机数。
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int count = 10;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

注意:这里布置好雷以后可以用Display()来输出一下,看是否有10个雷,是否为随机值,这里检查好了以后才能更好的实现下面的逻辑

(4)排查雷

◦ 如果位置不是雷,就显⽰周围有⼏个雷
◦ 如果位置是雷,就炸死游戏结束
◦ 把除10个雷之外的所有雷都找出来,排雷成功,游戏结束

void FindMind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < row * col - 10)
	//只有被炸死或把十个雷排完才能结束循环,所以用棋盘的总数-雷的个数
	{
		printf("请输入你要排查的坐标>:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标是否合法
		{
			if (mine[x][y] == '1')//说明输入坐标的位置为雷
			{
				printf("                        \n");
				printf("很遗憾,你被炸死了\n");
				printf("                        \n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int count = GetMineCountine(mine, x, y);
				//统计周围坐标的雷的个数
				show[x][y] = count += '0';
				//由于我们定义的是字符类型,要想变为整型加上字符'0'即可,参考ASCLL码
				DisplayBoard(show, ROW, COL);
				win++;
			}

		}
		else
		{
			printf("坐标非法,请重新输入坐标:>\n");
		}
		if (win ==row * col - EASY_COUNT)
		{
			printf("恭喜你,排雷成功\n");
			DisplayBoard(mine, ROW, COL);

		}
	}
}
static int GetMineCountine(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y] +
		mine[x - 1][y - 1] +
		mine[x][y - 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] +
		mine[x][y + 1] +
		mine[x - 1][y + 1] - 8 * '0');
}
//判断该坐标旁边的雷的个数,由于雷为1,,不是雷是0,所以将周围的坐标相加,
//值为多少则有几个雷

4、完整版的代码的实现

(1)game.h

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void IntBoard(char board[ROWS][COLS], int rows, int cols, char set);
void DisplayBoard(char board[ROWS][COLS],int rows,int cols );
void SetMine(char mine[ROWS][COLS], int row, int col);
void FindMind(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);

(2)game.c

#include "game.h"
void IntBoard(char board[ROWS][COLS],int rows, int cols, char set)
{
	int i = 0;
	for (i = 0;i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}


void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	printf("--------扫雷游戏-------\n");
	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		int j = 0;
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("--------扫雷游戏-------\n");
	printf("                        \n");
}

void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;

	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

static int GetMineCountine(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y] +
		mine[x - 1][y - 1] +
		mine[x][y - 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] +
		mine[x][y + 1] +
		mine[x - 1][y + 1] - 8 * '0');
}

void FindMind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < row * col - EASY_COUNT)
	{
		printf("请输入你要排查的坐标>:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("                        \n");
				printf("很遗憾,你个菜逼,被炸死了\n");
				printf("                        \n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int count = GetMineCountine(mine, x, y);
				show[x][y] = count += '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}

		}
		else
		{
			printf("坐标非法,请重新输入坐标:>\n");
		}
		if (win ==row * col - EASY_COUNT)
		{
			printf("恭喜你,排雷成功\n");
			DisplayBoard(mine, ROW, COL);

		}
	}
}

(3)tset.c

#include "game.h"
void menu()
{
	printf("*********************\n");
	printf("******1.play*********\n");
	printf("******0.exit*********\n");
	printf("*********************\n");

}
void game()
{
	/*定义数组存放创造棋盘*/
	char mine[ROWS][COLS];//存放布置好的雷
	char show[ROWS][COLS];//存放排查出的雷
	//初始化棋盘
	IntBoard(mine,ROWS,COLS,'0');
	IntBoard(show, ROWS, COLS, '*');
	/*打印棋盘*/
	DisplayBoard(show,ROW,COL);
	//DispalyBoard(mine, ROW, COL);
	//布置雷
	SetMine(mine, ROW, COL);
	//DisplayBoard(mine, ROW, COL);
	//排雷
	FindMind(mine,show, ROW, COL);
}
int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请输入>:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("游戏结束\n");
			break;
		default:
			printf("请重新输入\n");
			break;

		}
	} while (input);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值