C语言实现简单扫雷游戏

扫雷游戏的分析和设计:

1.棋盘是 9*9 的格子
2.随机布置 10 个雷
3.可以排查雷
   若位置不是雷,则显示周围有几个雷
   若位置是雷,则游戏结束
   找出所有的10个雷,游戏成功

设计思路:

设计mine数组(9*9)用来存放雷,规定1为雷,0为非雷。(注:这样设计便于后面对雷进行排查);

设计show数组(9*9)用来存放排查格子周围雷的信息,数字为雷的个数,'*'表示未排查,这个数组作为游戏界面。(注:分为两个数组进行存放,可以更好的设计雷,并且统计雷的个数);

注意事项:

在进行雷的排查时,对于中间部分的方格(红底),可以将方格周围的数字相加(注:雷是1,非雷是0),通过所得的值即为雷的数量。但对于边界方格(绿底),周围不存在方格,所以可以在方格外面加以一个边框,直接统计周围数值之和就可以排查雷的数量

 加上边框后:将边框设值为0,所以此时mine数组的大小为11*11,为了使两个数组一一对应。故将show数组也设置为11*11。并且统一将两个数组设置为char型,这样可以将一个函数作用于两个数组。

 游戏开始界面:

 用户需要选择玩游戏或者退出游戏,所以要给出一个菜单供选择。

void menu()
{
	printf("*****************************\n");
	printf("*****      1. play      *****\n");
	printf("*****      0. exit      *****\n");
	printf("*****************************\n");
}
int main()
{
	int input;
	
	do
	{
		menu();
		printf("请选择:>\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("扫雷游戏开始:\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误重新选择\n");
			break;
		}

	} while (input);
	return 0;
}

菜单执行结果:

 游戏的主程序设计:

定义行和列:

采用全局变量定义行(ROW)和列(COL),而ROWS和COLS是加了边框后的行和列。这样方便随时修改变量的大小。

#define ROW 9//行
#define COL 9//列

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

#define EASY_COUNT 10//十个雷

初始化数组:

首先建立两个char型的二维数组,mine数组(9*9)用来存放雷,规定1为雷,0为非雷show数组(9*9)用来存放排查格子周围雷的信息,数字为雷的个数,'*'表示未排查。创建函数InitBoard对两个数组初始化,由于初始化的值不同,固又要多加一个参数表示初始化的字符,但两个数组进行初始化时仍可以采用同一个函数。

 

 

 在mine数组中布置雷:

首先,雷是随机进行布置,所以要采用rand函数来布置,在使用rand函数前要使用time函数和srand函数,使其生成随机数。而time函数和srand函数只需使用一次,故放在main函数中

int main()
{
	int input;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("扫雷游戏开始:\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误重新选择\n");
			break;
		}

	} while (input);
	return 0;
}

 由于添加边界,所以在布置雷时仅仅将mine函数中间的值变为1即可,传参时传入ROW,COL即可。注意在布置雷时要先判断该方格中是否没有雷。

void SetMine(char mine[ROWS][COLS], int row, int col)//布置雷
{
	int count = EASY_COUNT;
	while (count)
	{//随机数布置雷
		int x = rand() % row + 1;
		int y = rand() % row + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}

	}
}

 棋盘的打印:

 show数组作为游戏界面,需进行打印,然而只用打印中间9*9的方格即可,为了方便坐标的输入,在打印时加入提示信息和数组下标。

void DisplayBoard(char board[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);//打印1行数
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("------------------------\n");
}

 

 雷的排查和数量统计:

数组mine用来存放雷。所以指定坐标后只需计算周围对应数值之和就是雷的数量,并且将这个和传入对应位置的show数组中。注意此处的和是int型,而show元素是char型,所以要实现数字向字符的转换,数字+字符'0'=该数字对应字符。

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排查雷
{
	int x = 0, y = 0;
	int num = 0;
	while (num<row*col-EASY_COUNT)
	{
		printf("请输入要排查的坐标:>\n");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= ROW && y >= 1 && y <= ROW)
		{
			if (mine[x][y] == '1')
			{
				printf("游戏失败,此处是雷!\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int count = GetMineCount(mine, x, y);
				show[x][y]=count + '0';//数字加上字符'0'对应数字对应字符
				// 1 + '0' = '1'     2 + '0' = '2'
				DisplayBoard(show, ROW, COL);
				num++;
			}
		}
		else
		{
			printf("坐标错误重新输入:>\n");
		}
	}
	if (num == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功!\n");
		DisplayBoard(show, ROW, COL);
	}
}

GetMineCount函数:

用来统计坐标周围雷的数量,mine数组(9*9)用来存放雷,规定1为雷,0为非雷所以只要计算周围对应数值之和就是雷的数量。

int GetMineCount(char mine[ROWS][COLS],int x,int y)//查找雷的数量
{
	//由于雷是1,非雷是0,可以使周围数字相加之和就是雷的数量
	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

运行结果:

mine数组是后台布置雷,而show数组则是游戏界面,通过对数组的初始化,对数组mine布置雷。通过用户的不断输入猜测坐标对数组mine排查周围雷的数量,并且将雷的数量赋值给在show数组对应位置上,通过show数组的不断改变从而达到游戏目的。

 

源码:

#define ROW 9//行
#define COL 9//列

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

#define EASY_COUNT 10//十个雷

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

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

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

void DisplayBoard(char board[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);//打印1行数
		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)
	{//随机数布置雷
		int x = rand() % row + 1;
		int y = rand() % row + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}

	}
}

int GetMineCount(char mine[ROWS][COLS],int x,int y)//查找雷的数量
{
	//由于雷是1,非雷是0,可以使周围数字相加之和就是雷的数量
	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 FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排查雷
{
	int x = 0, y = 0;
	int num = 0;
	while (num<row*col-EASY_COUNT)
	{
		printf("请输入要排查的坐标:>\n");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= ROW && y >= 1 && y <= ROW)
		{
			if (mine[x][y] == '1')
			{
				printf("游戏失败,此处是雷!\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int count = GetMineCount(mine, x, y);
				show[x][y]=count + '0';//数字加上字符'0'对应数字对应字符
				// 1 + '0' = '1'     2 + '0' = '2'
				DisplayBoard(show, ROW, COL);
				num++;
			}
		}
		else
		{
			printf("坐标错误重新输入:>\n");
		}
	}
	if (num == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功!\n");
		DisplayBoard(show, ROW, COL);
	}
}

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);//只打印一个9*9
	
	//布置雷
	SetMine(mine, ROW, COL);//只在中间9*9的格子里面放雷
	//DisplayBoard(mine, ROW, COL);
	
	//排查雷
	FindMine(mine, show, ROW, COL);
}

int main()
{
	int input;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("扫雷游戏开始:\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误重新选择\n");
			break;
		}

	} while (input);
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的基于Linux的扫雷游戏C语言代码。代码实现了一个简单扫雷游戏,玩家可以选择不同的难度级别并尝试找到所有地雷。 ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 10 #define COL 10 #define EASY 10 #define MEDIUM 20 #define HARD 30 int main() { int board[ROW][COL], num_mines, num_flags; int i, j, r, c, count, gameover = 0, win = 0, choice; char action; srand(time(NULL)); printf("Welcome to Minesweeper\n"); printf("----------------------\n"); printf("Choose a difficulty level:\n"); printf("1. Easy\n2. Medium\n3. Hard\n"); scanf("%d", &choice); switch (choice) { case 1: num_mines = EASY; break; case 2: num_mines = MEDIUM; break; case 3: num_mines = HARD; break; default: printf("Invalid choice. Defaulting to Easy difficulty.\n"); num_mines = EASY; break; } //initialize board with 0's for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { board[i][j] = 0; } } //place mines randomly for (i = 0; i < num_mines; i++) { r = rand() % ROW; c = rand() % COL; if (board[r][c] == -1) { //already a mine here i--; continue; } board[r][c] = -1; } //fill in numbers for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (board[i][j] == -1) { //skip mines continue; } count = 0; if (i-1 >= 0 && j-1 >= 0 && board[i-1][j-1] == -1) count++; if (i-1 >= 0 && board[i-1][j] == -1) count++; if (i-1 >= 0 && j+1 < COL && board[i-1][j+1] == -1) count++; if (j-1 >= 0 && board[i][j-1] == -1) count++; if (j+1 < COL && board[i][j+1] == -1) count++; if (i+1 < ROW && j-1 >= 0 && board[i+1][j-1] == -1) count++; if (i+1 < ROW && board[i+1][j] == -1) count++; if (i+1 < ROW && j+1 < COL && board[i+1][j+1] == -1) count++; board[i][j] = count; } } //game loop while (!gameover && !win) { num_flags = 0; printf("\n\n"); for (i = 0; i < ROW; i++) { printf("%d ", i); for (j = 0; j < COL; j++) { if (board[i][j] == -2) { //flag printf("F "); num_flags++; } else if (board[i][j] >= 0 && board[i][j] <= 8) { printf("%d ", board[i][j]); } else { printf("X "); } } printf("\n"); } printf(" "); for (i = 0; i < COL; i++) { printf("%d ", i); } printf("\n\n"); printf("Number of flags: %d\n", num_flags); printf("Enter coordinate and action (f = flag, u = unflag, r = reveal): "); scanf("%d %d %c", &r, &c, &action); if (r < 0 || r >= ROW || c < 0 || c >= COL) { printf("Invalid coordinate.\n"); continue; } if (action == 'f' || action == 'F') { //flag if (board[r][c] != -2) { board[r][c] = -2; } else { board[r][c] = 0; } } else if (action == 'r' || action == 'R') { //reveal if (board[r][c] == -1) { //mine gameover = 1; } else { board[r][c] += 10; //reveal if (board[r][c] == 9) { //win win = 1; } else if (board[r][c] == 10) { //empty square //reveal adjacent squares if (r-1 >= 0 && c-1 >= 0 && board[r-1][c-1] >= 0 && board[r-1][c-1] <= 8) board[r-1][c-1] += 10; if (r-1 >= 0 && board[r-1][c] >= 0 && board[r-1][c] <= 8) board[r-1][c] += 10; if (r-1 >= 0 && c+1 < COL && board[r-1][c+1] >= 0 && board[r-1][c+1] <= 8) board[r-1][c+1] += 10; if (c-1 >= 0 && board[r][c-1] >= 0 && board[r][c-1] <= 8) board[r][c-1] += 10; if (c+1 < COL && board[r][c+1] >= 0 && board[r][c+1] <= 8) board[r][c+1] += 10; if (r+1 < ROW && c-1 >= 0 && board[r+1][c-1] >= 0 && board[r+1][c-1] <= 8) board[r+1][c-1] += 10; if (r+1 < ROW && board[r+1][c] >= 0 && board[r+1][c] <= 8) board[r+1][c] += 10; if (r+1 < ROW && c+1 < COL && board[r+1][c+1] >= 0 && board[r+1][c+1] <= 8) board[r+1][c+1] += 10; } } } else if (action == 'u' || action == 'U') { //unflag if (board[r][c] == -2) { board[r][c] = 0; } } else { printf("Invalid action.\n"); } } //game over, reveal all squares printf("\n\n"); for (i = 0; i < ROW; i++) { printf("%d ", i); for (j = 0; j < COL; j++) { if (board[i][j] == -2) { //flag printf("F "); } else if (board[i][j] >= 0 && board[i][j] <= 8) { printf("%d ", board[i][j]); } else if (board[i][j] == -1) { //mine printf("M "); } else { printf("X "); } } printf("\n"); } printf(" "); for (i = 0; i < COL; i++) { printf("%d ", i); } printf("\n\n"); if (gameover) { printf("Game over! You hit a mine.\n"); } else { printf("Congratulations, you win!\n"); } return 0; } ``` 该代码包括以下功能: - 难度选择 - 地雷随机放置 - 数字填充 - 可以插旗 - 可以取消插旗 - 可以揭开方块 - 只有揭开所有非地雷方块才能获胜 这个代码还有可以改进的地方,比如增加计时器和玩家得分等等。但是,希望这个代码可以给你提供一个基础的思路和参考。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值