扫雷游戏--C语言

1、扫雷游戏的要求

我们用控制台实现一个扫雷游戏

有菜单选项选择游戏功能

9*9的棋盘,我们要存放10个雷

如果排到雷,就被炸死了,退出游戏;

如果没有雷,就计算周围有几个雷;

2.基本框架

首先我们玩游戏时先玩一把再说的,那我们就用do...while循环;玩了一把,还能再玩一把;

再用函数封装一个菜单;选择,我们就用switch选择语句;如果是1;玩游戏;如果是0,退出游戏,如果输入的是其他,那就再输入一遍,那循环条件就是input;

void meun()
{
	printf("************************\n");
	printf("******* 1.play *********\n");
	printf("******* 0.exit *********\n");
	printf("************************\n");
}
int main()
{
	int input = 0;
	do
	{
		meun();
		printf("请选择:>");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			//game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default: 
			printf("选择错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

3、设计思路

3.1棋盘数组

我们做的事一个初级扫雷游戏,是在一个9*9的一个棋盘,那我们放雷,也就是要放入数据,我们就需要一个9*9的数组;

3.2放雷和排雷数组

假设我们再9*9的棋盘里面,用0表示非雷(没有雷),1表示雷;那么当这个位置不是雷,我们计算周围有几个雷,刚好这个位置周围有1个雷,那这个位置显示1;这就会产生歧义,这个位置是雷呢?还是周围有1个雷呢?,那我们这样,分为两个9*9的数组,一个能存放雷的信息的数组,一个是排查雷的数组,把周围有几个雷的信息,放到另一个数组里面去;

 3.3数组越界

假设我们计算这个几个位置周围有几个雷,最简单的方法就是计算周围8个坐标有没有雷,但是如果再这些位置,那怎么计算,你不会还要计算周围3个位置的雷,还要计算周围5个位置的雷,这样台麻烦了,我们直接再这个棋盘上扩大一圈;上面个下面扩大一行,左边和右边扩大一列;那就能再哪个位置都能计算周围8个位置有没有雷;解决了数组越界的问题;那么我们实际上是要创建两个11*11的数组,一个放雷,一个排雷;

 

3.4数组类型

我们创建数组,是整型数组,还是字符数组?用字符数组,再排雷数组里,我们除了打印排雷的信息,其他的位置我们用 * 星号来表示,增加神秘感,那放雷的数组我们就用' 0 '字符0表示非雷,

’1‘字符1表示雷;

         

4、游戏代码

我们采用多文件的方式去实现游戏,用game.c/game.h

4.1创建数组

创建两个11*11的数组;一个存放雷,一个排雷

void game()
{
	//创建数组
	char mine[11][11];//存放雷的信息的数组
	char show[11][11];//排查雷的信息的数组
	
}

4.2初始化数组

两数组都要初始化,我们用函数来实现,还能复用;

text.c

初始化函数需要数组参数,行和列,并把要初始化的内容变为一个参数,给方便;

void game()
{
	//创建数组
	char mine[11][11];//存放雷的信息的数组
	char show[11][11];//排查雷的信息的数组
	
	//初始化数组
	Initboard(mine,11,11,'0');
	Initboard(show,11,11,'1');
}

 game.h

//初始化
void Initboard(char board[11][11],int row, int col,char set);

game.c

void Initboard(char board[11][11], int row, int col,char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = set;
		}
	}
}

写到这里我们发现有很多的11,我们可以在game.c那里用define,进行更好的处理;ROWS表示行11,COLS表示列11;注意要包含game.c和text.c文件要包含game.h头文件,因为声明是在game.h头文件里面;

game.h


#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

//初始化
void Initboard(char board[ROWS][COLS],int row, int col,char set);

game.c

void Initboard(char board[ROWS][COLS], int row, int col,char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = set;
		}
	}
}

text.c

void game()
{
	//创建数组
	char mine[ROWS][COLS];//存放雷的信息的数组
	char show[ROWS][COLS];//排查雷的信息的数组
	
	//初始化数组
	Initboard(mine,ROWS,COLS,'0');
	Initboard(show,ROWS,COLS,'1');

	
}

4.3打印数组

我们初始化后,先打印看一下数组初始化对不对;也用函数来进行打印;

函数需要数组参数,虽然数组是一个11*11的数组,但是我们打印的是9*9的数组,我们只要看9行9列就行,ROW和COL作为行和列的参数;但是我们现在只是检查有没有成功初始化;现在还不是打印的时候;注释掉;

text.c

void game()
{
	//创建数组
	char mine[ROWS][COLS];//存放雷的信息的数组
	char show[ROWS][COLS];//排查雷的信息的数组
	
	//初始化数组
	Initboard(mine,ROWS,COLS,'0');
	Initboard(show,ROWS,COLS,'*');

	//打印数组
	//Displayboard(mine,ROW,COL);
	//Displayboard(show,ROW,COL);
	
}

game.h

//打印数组
void Displayboard(char board[ROWS][COLS],int row, int col);

game.c

打印数组,那就循环遍历数组的下标;打印完后,我们要修饰一下棋盘;然后我们再把每个行号打印出来,每个列号打印出来。因为我们到时候是根据坐标来排查雷的;

但是我们game.c有用printf函数,需要头文件,但是每个文件都有game.h头文件,可以把stdio.h头文件放在game.h头文件中;

void Displayboard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-------扫雷--------\n");
	for (i = 0; i <= col; i++)  //每一个列号
	{
		printf("%d ",i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ",i);   //每一个行号
		for (j = 1; j <= col; j++)
		{
			printf("%c ",board[i][j]);
		}
		printf("\n");
	}
	printf("-------扫雷--------\n");
}

4.4放雷

放雷用函数来完成

text.c

放雷是在mine数组里放的,虽然mine数组是11行11列,但是我们放雷是在9行9列;

void game()
{
	srand((unsigned int)time(NULL));

	//创建数组
	char mine[ROWS][COLS];//存放雷的信息的数组
	char show[ROWS][COLS];//排查雷的信息的数组
	
	//初始化数组
	Initboard(mine,ROWS,COLS,'0');
	Initboard(show,ROWS,COLS,'*');

	//打印数组
	//Displayboard(mine,ROW,COL);
	//Displayboard(show,ROW,COL);
	
	//放雷
	Setboard(mine,ROW,COL);
	//Displayboard(mine, ROW, COL);
}

game.c 

假设我们用count表示10个雷;每放一个雷,-1;连续放10个;我们用循环解决;

我们要随机放雷,那就需要随机的下标,要用到rand函数产生随机数,随机下标

如果这个位置不是雷(’ 1 ‘);那就放雷(’ 1 ‘);count--;

注意我们使用rand函数,只需要在main函数里面调用一次srand函数就行了;

count变量的值,我们也在game.h头文件中定义。

void Setboard(char mine[ROWS][COLS], int row, int col)
{
	int count = 10; //10个雷
	while (count)
	{
		//行1~9
		int x = rand() % 8 + 1;
		//列1~9
		int y = rand() % 8 + 1;
		if (mine[x][y] != '1')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

game.h

注意使用rand函数、srand函数、time函数的头文件;

EASY表示10;

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define EASY 10


//放雷
void Setboard(char mine[ROWS][COLS],int row, int col);

4.5排查雷

 text.c

我们在mine数组里排查雷,把排查完雷的信息放在show数组里;

//排查雷
Findboard(mine,show,ROW,COL);

game.h

//排查雷
void Findboard(char mine[ROWS][COLS],char show[ROWS][COLS],int row, int col);

game.c

 我们排查雷是多次的排查过程,我们先写一次;输入坐标;判断你这个坐标是否在范围内;如果不是;就重新输入;如果是,则判断此处是不是雷,如果是,就被炸死,退出游戏;如果不是,则判断周围有几个雷;我们用函数来计算;计算你输入的坐标在mine数组里面的其他的8个坐标;

但是我们是字符数组,那数字0-数字0是0;那字符0-字符0也是0;字符1-字符0是1;因为字符0的ASCII码是48,字符1的ASCII码是49;49-48=1;所以我们把每个坐标都减去字符0;再全部加起来;全部加起来减去8个字符0;8个字符0 == 8 * ’ 0 ‘ 。那这个Getboard函数的返回值是int,但是放在show数组的是字符,所以我们将返回的值加上字符'  0 ' 。

注意我们只是写了排查一次的情况,但是我们要排查多次,需要循环;我们一直在9*9的棋盘范围内排查下去,那就有81个位置,再减去10个雷的位置,那就是71个位置,也就是说我们需要排查71个位置后,才能完成游戏;那么循环条件就是row*col - EASY,排查完一个win++;如果排查到雷,break跳到下面,循环结束也跳到下面,但是循环结束的话,就是排查完71个位置了,所以我们在下面还需要一个判断排查完的情况;

我们调试看是否能正常排查完71个位置游戏结束,我们可以把EASY改为80个,表示这个棋盘81个位置存放80个雷,这样就更好调试出来了;

int Getboard(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 Findboard(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)   //71个位置
	{
		printf("请输入坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) //判断坐标是否在范围内
		{
			if (mine[x][y] == '1')
			{
				printf("此处是雷,你被炸死了!\n");
				Displayboard(mine, ROW, COL);
				break;
			}
			else
			{	
				win++;
				printf("你还有%d个位置需要排查\n",row*col-EASY-win);
				int c = Getboard(mine,x,y);
				show[x][y] = c + '0';
				Displayboard(show, ROW, COL);
			}
		}
		else
		{
			printf("输入错误,请重新输入!\n");
		}
	}
	if(win == row*col-EASY)
	{
		printf("恭喜你完成扫雷游戏!\n");
		Displayboard(mine, ROW, COL);
	}
}

5、完整的代码

game.h

 

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define EASY 10

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

//初始化
void Initboard(char board[ROWS][COLS],int row, int col,char set);

//打印数组
void Displayboard(char board[ROWS][COLS],int row, int col);

//放雷
void Setboard(char mine[ROWS][COLS],int row, int col);

//排查雷
void Findboard(char mine[ROWS][COLS],char show[ROWS][COLS],int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS

#include "game.h"

void Initboard(char board[ROWS][COLS], int row, int col,char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = set;
		}
	}
}


void Displayboard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-------扫雷--------\n");
	for (i = 0; i <= col; i++)  //每一个列号
	{
		printf("%d ",i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ",i);   //每一个行号
		for (j = 1; j <= col; j++)
		{
			printf("%c ",board[i][j]);
		}
		printf("\n");
	}
	printf("-------扫雷--------\n");
}

void Setboard(char mine[ROWS][COLS], int row, int col)
{
	int count = EASY; //10个雷
	while (count)
	{
		//行1~9
		int x = rand() % row + 1;
		//列1~9
		int y = rand() % col + 1;
		if (mine[x][y] != '1')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}



int Getboard(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 Findboard(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)   //71个位置
	{
		printf("请输入坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) //判断坐标是否在范围内
		{
			if (mine[x][y] == '1')
			{
				printf("此处是雷,你被炸死了!\n");
				Displayboard(mine, ROW, COL);
				break;
			}
			else
			{	
				win++;
				printf("你还有%d个位置需要排查\n",row*col-EASY-win);
				int c = Getboard(mine,x,y);
				show[x][y] = c + '0';
				Displayboard(show, ROW, COL);
			}
		}
		else
		{
			printf("输入错误,请重新输入!\n");
		}
	}
	if(win == row*col-EASY)
	{
		printf("恭喜你完成扫雷游戏!\n");
		Displayboard(mine, ROW, COL);
	}
}

text.c

#define _CRT_SECURE_NO_WARNINGS

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

void game()
{
	srand((unsigned int)time(NULL));

	//创建数组
	char mine[ROWS][COLS];//存放雷的信息的数组
	char show[ROWS][COLS];//排查雷的信息的数组
	
	//初始化数组
	Initboard(mine,ROWS,COLS,'0');
	Initboard(show,ROWS,COLS,'*');

	//打印数组
	//Displayboard(mine,ROW,COL);
	//Displayboard(show,ROW,COL);
	
	//放雷
	Setboard(mine,ROW,COL);
	//Displayboard(mine, ROW, COL);
	Displayboard(show, ROW, COL);

	//排查雷
	Findboard(mine,show,ROW,COL);
}

int main()
{
	int input = 0;
	do
	{
		meun();
		printf("请选择:>");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default: 
			printf("选择错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

 

感谢观看!感谢指正! 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值