扫雷(C语言)

思路:
进行扫雷游戏,每次点击,若该位置有雷,则游戏结束,若无雷,则显示周围雷的数量,一直进行循环直至游戏结束(胜利或失败);

但一般情况下,第一次点到雷不会显示游戏结束,而是会把雷移到别的位置,不会让用户第一次落子就游戏结束;

另外,若用户点击,该位置及周围都没有雷就将附近没有雷的地方都展开。

在设计过程中,设计者和用户看到的是两个不同的棋盘,但是大小都是12 x 12的,设计者布雷的区域和用户排雷的区域都是中间10 x 10的部分;

用到的函数:

void Menu();//菜单
void Setmine(char show[][COL], int row, int col);//布雷
void Show(char show[][COL], int row, int col);//显示游戏过程
int Getmine(char mine[][COL], int row, int col);//获取雷的数量
void Openmine(char mine[ROW][COL], char show[ROW][COL], int row, int col, int x, int y);//展开没有雷的区域
void Game();//游戏逻辑

各部分代码及作用:
Menu()函数:

这一部分就是用简单的printf语句来显示菜单的;

void Menu()
{
	printf("\t\t\t*******************************************************\n\n\n");
	printf("\t\t\t******************** 欢迎来到扫雷游戏 *******************\n\n\n");
	printf("\t\t\t****************** 1、Play   2、Exit ******************\n\n\n");
	printf("\t\t\t*******************************************************\n\n");
}

Setmine(char mine[][COL], int row, int col)函数:

这一部分是用来布雷的,在这里用了随机数,随机的布雷,通过对10取余,再加1的操作,控制雷落下的坐标在1和10之间;

void Setmine(char mine[][COL], int row, int col)
{
	int count = NUM;
	while (count > 0){
		int x = rand() % (row - 2) + 1;
		int y = rand() % (col - 2) + 1;
		if (mine[x][y] == '0'){
			mine[x][y] = '1';
			count--;
		}
	}
}

Show(char show[][COL], int row, int col)函数:

这一部分是用于显示用户看到的扫雷界面(一个10*10的界面),通过不断使用for循环实现扫雷界面的输出;

void Show(char show[][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("    ");
	for (i = 1; i <= 10; i++){
		printf("  %d ", i);
	}
	printf("\n");
	for (i = 1; i <= 10; i++){
		printf("----");
	}
	printf("----\n");
	for (i = 1; i <= 10; i++){
		printf(" %2d |", i);
		for (j = 1; j <= 10; j++){
			printf(" %c |", show[i][j]);
		}
		printf("\n");
		int k = 0;
		for (k = 1; k <= 10; k++){
			printf("----");
		}
		printf("----\n");
	}
}

Getmine(char mine[][COL], int x, int y)函数:

这一部分是用于表示用户排雷坐标周围的类的数量的,这里只是简单地将用户排雷坐标周围的八个位置相加再减去字符’0’的个数即可;

int Getmine(char mine[][COL], int x, int y)
{ 
	return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1]\
		+ mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] \
		+ mine[x + 1][y] + mine[x + 1][y + 1]-8*'0';
}

Openmine(char mine[ROW][COL], char show[ROW][COL], int row, int col, int x, int y)函数:

这一部分用于展开用户排雷坐标周围没有雷的情况,在这里用到了递归函数;首先,对用户排雷坐标进行判断,若确定在此坐标周围没有雷,那么就将该坐标的’*‘换成’0’,然后继续判断,若该坐标周围的坐标,坐标合法且没有被排过,则继续调用该函数,进行如上操作,若该坐标周围有雷,则将雷的个数显示在界面上该坐标处

void Openmine(char mine[ROW][COL], char show[ROW][COL], int row, int col, int x, int y)
{
	int m = 0;
	m = Getmine(mine, x, y);
	if (m == 0){
		show[x][y] = '0';
		if (x - 1 > 0 && y - 1 > 0 && show[x - 1][y - 1] == '*'){
			Openmine(mine, show, row, col, x - 1, y - 1);
		}
		if (x - 1 > 0 && y  > 0 && show[x - 1][y] == '*'){
			Openmine(mine, show, row, col, x - 1, y );
		}
		if (x - 1 > 0 && y + 1 > 0 && show[x - 1][y + 1] == '*'){
			Openmine(mine, show, row, col, x - 1, y + 1);
		}
		if (x > 0 && y - 1 > 0 && show[x][y - 1] == '*'){
			Openmine(mine, show, row, col, x , y - 1);
		}
		if (x  > 0 && y + 1 > 0 && show[x ][y + 1] == '*'){
			Openmine(mine, show, row, col, x , y + 1);
		}
		if (x + 1 > 0 && y - 1 > 0 && show[x + 1][y - 1] == '*'){
			Openmine(mine, show, row, col, x + 1, y - 1);
		}
		if (x + 1 > 0 && y > 0 && show[x + 1][y ] == '*'){
			Openmine(mine, show, row, col, x + 1, y );
		}
		if (x + 1 > 0 && y + 1 > 0 && show[x + 1][y + 1] == '*'){
			Openmine(mine, show, row, col, x + 1, y + 1);
		}
	}
	else{
		show[x][y] = Getmine(mine, x, y)+'0';
	}
}

Game()函数:

在这个函数中,首先,对用于布雷和用于显示的数组进行初始化(在这里用了memset()函数,或者用for循环也可以),将布雷的界面初始化全都是’ 0 ‘,将显示的界面初始化为全部都是’ * ',然后调用Setmine(char mine[][COL], int row, int col)函数布雷,接下来用户就可以开始排雷了,若用户输入坐标不合法,跳出本次循环,进入下一次循环;若用户输入坐标合法,即判断该坐标是否有雷;若第一次输入坐标有雷,将雷挪开,随机放入一个没有雷的位置,若不是第一次输入有雷,则显示游戏失败,并显示雷的分布;若该坐标没有雷,则显示该坐标周围雷数;若雷全都排除则显示用户游戏成功,并显示雷的分布。

void Game()
{
	srand((unsigned)time(NULL));
	char mine[ROW][COL];
	char show[ROW][COL];
	int x = 0;
	int y = 0;
	int times = ROW*COL - NUM;
	memset(mine, '0', sizeof(mine));
	memset(show, '*', sizeof(show));
	Setmine(mine, ROW, COL);
	do{
		Show(show, ROW, COL);
		printf("请输入坐标(x,y) > ");
		scanf("%d %d", &x, &y);
		if (x<1 || x>10 || y<1 || y>10){
			printf("你输入的坐标有误,请重新输入坐标!\n");
			continue;
		}
		if (show[x][y] != '*'){
			printf("该位置已经排过了,请重新输入坐标!\n");
			continue;
		}
		if (mine[x][y] == '1'){
			if (times == ROW*COL - NUM){
				mine[x][y] = '0';
				int i = rand() % (ROW - 2) + 1;
				int j = rand() % (COL - 2) + 1;
				if (mine[i][j] == '0'){
					times--;
					mine[i][j] = '1';
				}
			}
			else{
				printf("真遗憾,你踩到雷了,游戏结束\n");
				printf("雷的分布图如下 > \n");
				Show(mine, ROW, COL);
				break;
			}
		}
		int mine_num = Getmine(mine, x, y);
		show[x][y] = mine_num + '0';
		Openmine(mine, show, ROW, COL, x, y);
		times--;
		
	} while (time > 0);
	if (times == 0){
		printf("恭喜,你赢了!\n");
		printf("雷的分布图如下 > \n");
		Show(mine, ROW, COL);
	}
}

要注意的地方

1、在布雷的时候,产生的随机数是从0开始的,但是我们要用的是1到10;所以要对10取余载加1;
2、布雷的时候,在合法的位置布雷时,要注意赋值的’ = ‘不要写成’ == ‘;
3、虽然输出的是一个10 x 10的界面,但是为了方便起见,设计的是12 x 12的数组。
4、由于定义的数组都是字符型的,所以显示用户排雷坐标周围雷数时,还要再加上’ 0 ’

可以改进的地方

1、为了更清楚明了,可以把用户排雷和第一步踩雷不死,写成单独的函数;
2、可以另加游戏难度的选项,让使用者有更多的选择。

运行结果:

最开始的菜单:
在这里插入图片描述

开始游戏,显示初始化界面:

在这里插入图片描述
开始排雷:
在这里插入图片描述
坐标周围没有雷,展开:
在这里插入图片描述
输入坐标已排过:
在这里插入图片描述
输入坐标有误:
在这里插入图片描述
踩到有雷的坐标,给出提示并输出雷的分布图:
在这里插入图片描述
选择2,退出:
在这里插入图片描述

完整代码:
本次程序使用多文件编译的,分别有game.h ;game.c ;main.c
game.h

#ifndef __GAME_H__
#define __GAME_H__

#include<stdio.h>
#include<windows.h>
#include<time.h>
#include<string.h>

#define ROW 12
#define COL 12
#define NUM 20
#pragma warning(disable:4996)

void Menu();
void Setmine(char show[][COL], int row, int col);
void Show(char show[][COL], int row, int col);
int Getmine(char mine[][COL], int row, int col);
void Openmine(char mine[ROW][COL], char show[ROW][COL], int row, int col, int x, int y);
void Game();

#endif

game.c

#include"game.h"
void Menu()
{
	printf("\t\t\t*******************************************************\n\n\n");
	printf("\t\t\t******************* 欢迎来到扫雷游戏 ******************\n\n\n");
	printf("\t\t\t****************** 1、Play   2、Exit ******************\n\n\n");
	printf("\t\t\t*******************************************************\n\n");
}
void Setmine(char mine[][COL], int row, int col)
{
	int count = NUM;
	while (count > 0){
		int x = rand() % (row - 2) + 1;
		int y = rand() % (col - 2) + 1;
		if (mine[x][y] == '0'){
			mine[x][y] = '1';
			count--;
		}
	}
}
void Show(char show[][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("    ");
	for (i = 1; i <= 10; i++){
		printf("  %d ", i);
	}
	printf("\n");
	for (i = 1; i <= 10; i++){
		printf("----");
	}
	printf("----\n");
	for (i = 1; i <= 10; i++){
		printf(" %2d |", i);
		for (j = 1; j <= 10; j++){
			printf(" %c |", show[i][j]);
		}
		printf("\n");
		int k = 0;
		for (k = 1; k <= 10; k++){
			printf("----");
		}
		printf("----\n");
	}
}
int Getmine(char mine[][COL], int x, int y){ 
	return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1]\
		+ mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] \
		+ mine[x + 1][y] + mine[x + 1][y + 1]-8*'0';
}
void Openmine(char mine[ROW][COL], char show[ROW][COL], int row, int col, int x, int y)
{
	int m = 0;
	m = Getmine(mine, x, y);
	if (m == 0){
		show[x][y] = '0';
		if (x - 1 > 0 && y - 1 > 0 && show[x - 1][y - 1] == '*'){
			Openmine(mine, show, row, col, x - 1, y - 1);
		}
		if (x - 1 > 0 && y  > 0 && show[x - 1][y] == '*'){
			Openmine(mine, show, row, col, x - 1, y );
		}
		if (x - 1 > 0 && y + 1 > 0 && show[x - 1][y + 1] == '*'){
			Openmine(mine, show, row, col, x - 1, y + 1);
		}
		if (x > 0 && y - 1 > 0 && show[x][y - 1] == '*'){
			Openmine(mine, show, row, col, x , y - 1);
		}
		if (x  > 0 && y + 1 > 0 && show[x ][y + 1] == '*'){
			Openmine(mine, show, row, col, x , y + 1);
		}
		if (x + 1 > 0 && y - 1 > 0 && show[x + 1][y - 1] == '*'){
			Openmine(mine, show, row, col, x + 1, y - 1);
		}
		if (x + 1 > 0 && y > 0 && show[x + 1][y ] == '*'){
			Openmine(mine, show, row, col, x + 1, y );
		}
		if (x + 1 > 0 && y + 1 > 0 && show[x + 1][y + 1] == '*'){
			Openmine(mine, show, row, col, x + 1, y + 1);
		}
	}
	else{
		show[x][y] = Getmine(mine, x, y)+'0';
	}
}
void Game()
{
	srand((unsigned)time(NULL));
	char mine[ROW][COL];
	char show[ROW][COL];
	int x = 0;
	int y = 0;
	int times = ROW*COL - NUM;
	memset(mine, '0', sizeof(mine));
	memset(show, '*', sizeof(show));
	Setmine(mine, ROW, COL);
	do{
		Show(show, ROW, COL);
		printf("请输入坐标(x,y) > ");
		scanf("%d %d", &x, &y);
		if (x<1 || x>10 || y<1 || y>10){
			printf("你输入的坐标有误,请重新输入坐标!\n");
			continue;
		}
		if (show[x][y] != '*'){
			printf("该位置已经排过了,请重新输入坐标!\n");
			continue;
		}
		if (mine[x][y] == '1'){
			if (times == ROW*COL - NUM){
				mine[x][y] = '0';
				int i = rand() % (ROW - 2) + 1;
				int j = rand() % (COL - 2) + 1;
				if (mine[i][j] == '0'){
					times--;
					mine[i][j] = '1';
				}
			}
			else{
				printf("真遗憾,你踩到雷了,游戏结束\n");
				printf("雷的分布图如下 > \n");
				Show(mine, ROW, COL);
				break;
			}
		}
		int mine_num = Getmine(mine, x, y);
		show[x][y] = mine_num + '0';
		Openmine(mine, show, ROW, COL, x, y);
		times--;
		
	} while (time > 0);
	if (times == 0){
		printf("恭喜,你赢了!\n");
		printf("雷的分布图如下 > \n");
		Show(mine, ROW, COL);
	}
}

main.c

#include"game.h"
void main()
{
	int quit = 1;
	int select = 0;
	while (quit){
		Menu();
		printf("请输入你的选择 > ");
		scanf("%d", &select);
		switch (select){
		case 1:
			Game();
			break;
		case 2:
			quit = 0;
			break;
		default:
			printf("您的输入有误,请重新输入!");
			break;
		}
	}
	system("pause");
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值