c语言 实现扫雷


前言

大家好呀!上篇博客中我们用c语言大致模拟出了三子棋,今天这篇博客又要介绍模拟实现扫雷了!!
大家伙都了解扫雷的规则吧?
这里简单介绍一下:
首先我们有一个棋盘,这个棋盘假设就是9x9的大小,这81个格子里面有10地雷。我们需要找出10个地雷的位置,这样我们就赢得胜利了。
当然扫雷也有简单或是相对困难的模式,就是调整棋盘的大小或是地雷的个数。


一、玩游戏的逻辑

1、菜单

我们先设计一个菜单,再选择玩游戏或是退出游戏

void menu()
{
	printf("******************************\n");
	printf("*********** 1.play  **********\n");
	printf("*********** 0.exit  **********\n");
	printf("******************************\n");
}

2、定义一个函数,实现玩游戏的逻辑

我们看见菜单后选择一个数字,1就是玩扫雷游戏。0就是退出游戏。其他的数字就输入错误,要重新输入。
来看代码:

void test()
{
	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);

}

这样我们就得到了扫雷游戏的简易界面。如果玩一把还没过瘾,输入1就还能继续玩!接下来就是扫雷的实现了

二、扫雷游戏的实现

我们先把大致的逻辑写出来吧!(封装为game函数)
第一步:初始化棋盘
第二步:打印棋盘
第三步:布置雷
第四步:排查雷
那么来看game函数的代码:

void game()
{
	//设置两个棋盘 一个雷盘, 一个显示
	char mine[ROWS][COLS] = { 0 };//雷用字符0表示
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘 
	InitBoard(mine,ROWS,COLS,'0');
	InitBoard(show, ROWS, COLS, '*');
	//打印棋盘
	Dispalyboard(show, ROW, COL);
	//布置雷
	Setmine(mine, ROW, COL);
	//排查雷
	Findmine(mine,show, ROW, COL);


}

1、初始化棋盘

看一看这个扫雷的棋盘:一开始,这个棋盘上什么也没有,那我们怎么知道地雷存放在那个位置呢?
所以我们需要两个棋盘,一个用来存地雷的位置(不显示),一个用来覆盖地雷的(就是只显示第二个棋盘)
在这里插入图片描述
经过思考,我们要定义两个数组
来看代码:

#define ROW 9  		//要显示的棋盘的行
#define COL 9			//要显示的棋盘的列
#define ROWS ROW+2		//实际的棋盘的行
#define COLS COL+2			//实际的棋盘的列
//这个后面再说明

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for (i = 0;i < rows;i++)
	{
		for (j = 0;j < cols;j++)
		{
			//这个传的什么就初始化什么
			board[i][j] = set;
		}
	}

}

现在我们已经可以初始化棋盘了,但是我们需要将两个数组初始化为什么呢?
我们将要显示的棋盘初始化为字符*,表示这个位置还没有被排查过。
存放地雷的棋盘就初始化字符0,地雷就用字符1表示
我们就用两个char 类型的数组存放棋盘内容
代码:

	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	InitBoard(mine,ROWS,COLS,'0');
	InitBoard(show, ROWS, COLS, '*');

2、打印棋盘

打印棋盘就很简单了,用两个for循环就行了

void Dispalyboard(char board[ROWS][COLS], int row, int  col)
{
	int i = 0;
	int j = 0;
	//打印列号
	printf("--------扫雷---------\n");//这是为了美观
	//打印出列号
	for (j = 0;j <= col;j++)
	{
		printf("%d ", j);
	}
	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");//这是为了美观

}

打印出来的效果:
在这里插入图片描述

3、布置雷

接下来就是布置雷了,我们可以用rand()生成随机数,再给它取模,让它生成1到9的随机数。
我们需要两个1到9的随机数,分别表示行号和列号
代码:

#define Easy_count 10 //布置雷的个数

//布置雷
void Setmine(char mine[ROWS][COLS], int row, int col)
{
	//雷的个数
	int count = Easy_count;
	while (count)
	{
		//生成1到9的随机数
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if(mine[x][y]=='0')
		{
			//每成功布置一个地雷
			mine[x][y] = '1';
			count--;
		}
	}
}

这样我们就可以用Easy_count控制地雷的个数了,很方便!!

4、排查地雷

经过一些列的操作,我们就完成了初始化棋盘、打印棋盘和布置地雷,接下来就是玩家的操作了。
玩家输入两个坐标,棋盘就要显示这个位置的信息。
如果这个位置为地雷,那玩家就被炸死了,游戏结束。
如果这个位置不是地雷就要显示这个位置的信息,然后继续输入两个坐标
代码:

//统计返回坐标周围八个位置的地雷的个数
int get_count_minenum(char mine[ROWS][COLS],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 + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] - 8 * '0';
}

//排查雷
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int ret = ROW * COL - Easy_count;
	while (1)
	{
		printf("请输入排查的位置:>");
		scanf("%d %d", &x, &y);
		//输入的坐标有效
		if (x >= 1 && x <= row && y >= 1 && y <= col &&show[x][y]=='*')
		{
			//如果坐标为地雷,游戏结束
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被雷炸死了\n");
				//打印一下全部地雷的位置
				Dispalyboard(mine, row, col);
				break;
			}
			else
			{
				int n = get_count_minenum(mine, x, y);
				show[x][y] = '0' + n;
				ret--;
				Dispalyboard(show, row, col);

				
			}
		}
		//输入的坐标无效
		else
		{
			printf("请输入正确的位置!!!\n");

		}

	}

}

这样最基础的扫雷就完成了。
先看完整的代码吧!!!
test.c(测试游戏的逻辑)

#include "game.h"


void menu()
{
	printf("******************************\n");
	printf("*********** 1.play  **********\n");
	printf("*********** 0.exit  **********\n");
	printf("******************************\n");
}

void game()
{
	//设置两个棋盘 一个雷盘, 一个显示
	char mine[ROWS][COLS] = { 0 };//雷用字符0表示
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘 
	InitBoard(mine,ROWS,COLS,'0');
	InitBoard(show, ROWS, COLS, '*');
	//打印棋盘
	//Dispalyboard(mine, ROW, COL);
	Dispalyboard(show, ROW, COL);
	//布置雷
	Setmine(mine, ROW, COL);
	Dispalyboard(mine, ROW, COL);
	//排查雷
	Findmine(mine,show, ROW, COL);


}




void test()
{
	//使用rand的条件,只需调用一次就可以用rand(),rand()生成随机数(0到0x7fff)
	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);

}

int main()
{

	test();
	return 0;
}

game.c(扫雷相关的函数定义)

#include "game.h"

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for (i = 0;i < rows;i++)
	{
		for (j = 0;j < cols;j++)
		{
			board[i][j] = set;
		}
	}

}

//显示棋盘
void Dispalyboard(char board[ROWS][COLS], int row, int  col)
{
	int i = 0;
	int j = 0;
	//打印列号
	printf("--------扫雷---------\n");
	for (j = 0;j <= col;j++)
	{
		printf("%d ", j);
	}
	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 Setmine(char mine[ROWS][COLS], int row, int col)
{
	//雷的个数
	int count = Easy_count;
	while (count)
	{
		//生成1到9的随机数
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if(mine[x][y]=='0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

//统计周围八个位置的雷的个数
int get_count_minenum(char mine[ROWS][COLS],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 + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] - 8 * '0';
}

//排查雷
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS],int row, int col)
{
	int x = 0;
	int y = 0;
	int ret = ROW * COL - Easy_count;
	while(ret)
	{
		printf("请输入排查的位置:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被雷炸死了\n");
				Dispalyboard(mine, row, col);
				break;
			}
			else
			{
				int n = get_count_minenum(mine, x, y);
				show[x][y] = '0' + n;
				ret--;
				Dispalyboard(show, row, col);
				Dispalyboard(mine, ROW, COL);
			}
		}
		else
		{
			printf("请输入正确的位置!!!\n");

		}

	}

	if (ret == 0)
		printf("恭喜,扫雷成功!\n");
}

game.h(扫雷相关的函数声明)

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 9	//设置行数
#define COL 9	//设置列数
#define ROWS ROW+2
#define COLS COL+2
#define Easy_count 10 //布置雷的个数


//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//显示棋盘
void Dispalyboard(char board[ROWS][COLS],int rows, int  cols);
//布置雷
void Setmine(char mine[ROWS][COLS],int rows,int cols);
//排查雷1.0
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS],int row,int col);

看看效果吧!为了展示效果我就把地雷的位置先打印出来,并且把地雷的个数设为80个。
运行结果:

看完这个视频,是不是觉得,这个扫雷怎么这么基础,接下来我们就一起来看看优化吧!!!

三、扫雷的简单优化

目前,我们输入两个数字后如果这个坐标不是地雷的话,它只能显示当前坐标的信息。
那么怎么优化呢?
如果输入表示的该坐标不是地雷,我们是不是可以显示周围八个不是地雷的信息(即周围八个位置再分别统计它们自己周围的地雷个数)

//如果排查x,y不是雷,统计它周围八个位置周围的信息
void more_countmine(char mine[ROWS][COLS], char show[ROWS][COLS],int x,int y)
{
	if (mine[x][y] == '0')
	{
		//1
		if (mine[x-1][y-1] != '1')
		{
			show[x - 1][y - 1] = get_count_minenum(mine, x - 1,y-1) + '0';

		}
		//2
		if (mine[x - 1][y] != '1')
		{
			show[x - 1][y] = get_count_minenum(mine, x - 1, y) + '0';
		}
		//3
		if (mine[x - 1][y + 1] != '1')
		{
			show[x - 1][y + 1] = get_count_minenum(mine, x - 1, y + 1) + '0';
		}
		//4
		if (mine[x][y + 1] != '1')
		{
			show[x][y + 1] = get_count_minenum(mine, x, y + 1) + '0';
		}
		//5
		if (mine[x + 1][y + 1] != '1')
		{
			show[x + 1][y + 1] = get_count_minenum(mine, x + 1, y + 1) + '0';

		}
		//6
		if (mine[x + 1][y] != '1')
		{
			show[x + 1][y] = get_count_minenum(mine, x + 1, y) + '0';
		}
		//7
		if (mine[x + 1][y - 1] != '1')
		{
			show[x + 1][y - 1] = get_count_minenum(mine, x + 1, y - 1) + '0';
		}
		//8
		if (mine[x][y - 1] != '1')
		{
			show[x][y - 1] = get_count_minenum(mine, x, y - 1) + '0';
		}

	}

}

void Findmine2(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请输入排查的位置:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col &&show[x][y]=='*')
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被雷炸死了\n");
				Dispalyboard(mine, row, col);
				break;
			}
			else
			{
				int n = get_count_minenum(mine, x, y);
				show[x][y] = '0' + n;
				//周围八个位置再分别统计它们自己周围的地雷个数
				more_countmine(mine, show, x, y);
				Dispalyboard(show, row, col);
				int ret = is_win(mine, show, row, col);
				if (ret == 1)
					break;
			}
		}
		else
		{
			printf("请输入正确的位置!!!\n");

		}

	}

}

看看效果吧

排雷2


总结

以上就是扫雷游戏的模拟实现了,当然功能还没有齐全,有时间再来优化!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的扫雷程序的C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROWS 10 #define COLS 10 #define MINES 10 void print_board(char board[ROWS][COLS], int reveal_all); void place_mines(char board[ROWS][COLS]); int count_adjacent_mines(char board[ROWS][COLS], int row, int col); void reveal_cell(char board[ROWS][COLS], int row, int col, int *remaining_cells); void play_game(char board[ROWS][COLS]); int main() { char board[ROWS][COLS]; srand(time(NULL)); place_mines(board); print_board(board, 0); play_game(board); return 0; } void print_board(char board[ROWS][COLS], int reveal_all) { int i, j; printf(" "); for (i = 0; i < COLS; i++) { printf("%d ", i + 1); } printf("\n"); for (i = 0; i < ROWS; i++) { printf("%c ", 'A' + i); for (j = 0; j < COLS; j++) { if (board[i][j] == '*' && !reveal_all) { printf(". "); } else { printf("%c ", board[i][j]); } } printf("\n"); } } void place_mines(char board[ROWS][COLS]) { int i, j, count = 0; for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { board[i][j] = '.'; } } while (count < MINES) { i = rand() % ROWS; j = rand() % COLS; if (board[i][j] == '.') { board[i][j] = '*'; count++; } } } int count_adjacent_mines(char board[ROWS][COLS], int row, int col) { int i, j, count = 0; for (i = row - 1; i <= row + 1; i++) { for (j = col - 1; j <= col + 1; j++) { if (i >= 0 && i < ROWS && j >= 0 && j < COLS && board[i][j] == '*') { count++; } } } return count; } void reveal_cell(char board[ROWS][COLS], int row, int col, int *remaining_cells) { int i, j; if (board[row][col] == '.') { (*remaining_cells)--; board[row][col] = '0' + count_adjacent_mines(board, row, col); if (board[row][col] == '0') { for (i = row - 1; i <= row + 1; i++) { for (j = col - 1; j <= col + 1; j++) { if (i >= 0 && i < ROWS && j >= 0 && j < COLS) { reveal_cell(board, i, j, remaining_cells); } } } } } } void play_game(char board[ROWS][COLS]) { int row, col, remaining_cells = ROWS * COLS - MINES; while (remaining_cells > 0) { printf("Enter row and column: "); scanf("%d %d", &row, &col); row--; col--; if (row >= 0 && row < ROWS && col >= 0 && col < COLS) { if (board[row][col] == '*') { printf("Game over!\n"); print_board(board, 1); return; } else { reveal_cell(board, row, col, &remaining_cells); print_board(board, 0); } } } printf("You won!\n"); } ``` 这个程序使用了一个二维字符数组来表示扫雷的棋盘,其中每个字符表示该位置的状态,'.'表示未揭开,'*'表示地雷,'0'-'8'表示相邻地雷的数量。在程序开始时,使用`place_mines`函数随机放置地雷。然后使用`print_board`函数打印当前的棋盘。在玩家选择一个位置后,使用`reveal_cell`函数揭开该位置,如果该位置是地雷则游戏结束,否则更新棋盘并继续游戏,直到所有非地雷位置都被揭开。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值