C语言实现简单扫雷游戏

本文详细介绍了扫雷游戏的规则、预期功能,包括初始化游戏界面、放置雷、排雷操作、游戏判定以及源代码实现。通过代码展示了如何设计和实现一个简单的扫雷游戏,包括关键函数如设置地雷、计算周围雷的数量和游戏流程控制。
摘要由CSDN通过智能技术生成

目录

扫雷游戏介绍及规则

预期功能

游戏设计与代码实现

游戏初始界面及多次游戏实现

初始化游戏界面

打印游戏界面

放置雷

排雷及游戏判定

计算周围雷的数量

完整的源代码及注释

头文件 game . h

源文件 test . c

源文件 game . c


扫雷游戏介绍及规则

扫雷游戏是一款经典的益智小游戏,玩家需要在由数字标记的方块矩阵中找出所有隐藏的地雷,同时避免踩到它们。游戏开始时,矩阵中大部分方块都是隐藏的,玩家需要逐个点击来翻开它们。每个方块上的数字表示其周围八个方向上的地雷数量,玩家需要利用这些数字来推理出地雷的位置。如果成功找出所有地雷而不踩到任何一个,那么游戏就胜利了。如果踩到地雷,游戏就会立即结束。

预期功能

  1. 初始化游戏界面:游戏开始时,应能生成一个预设大小的扫雷界面,该界面由一定数量的格子组成,每个格子初始状态为未翻开。

  2. 设置地雷:在界面上随机布置一定数量的地雷,同时计算每个非地雷格子周围的地雷数,并在界面上以数字形式显示。

  3. 扫雷游戏(排雷):玩家应能够通过键盘输入坐标来翻开格子,显示格子内容(数字或地雷)。如果翻开的是地雷格子,游戏结束;如果翻开的是数字格子,根据数字显示周围地雷数。

  4. 游戏胜利与失败判定:当玩家成功找出所有地雷并翻开所有非地雷格子时,游戏胜利;如果玩家翻开了地雷格子,则游戏失败。游戏应能正确判断并显示游戏结果。

  5. 重新开始或退出游戏:游戏结束后,程序应提供选项供用户选择重新开始新的一局或退出游戏。

游戏设计与代码实现

游戏初始界面及多次游戏实现

使用 printf 打印出简单的游戏初始界面 menu(),使用 do-while循环 和 switch 选择语句,当玩家输入的值 input  等于 1 时便开始游戏,游戏结束后,因为 input 值为 1,非零为真,循环会再次执行,便可以再次选则是否进行下一场游戏;input 等于 0 时,零为假,循环终止,退出游戏;其它值可以设置为,选择错误,请重新输入。

代码实现

//打印游戏初始界面
void menu()
{
	printf("************************\n");
	printf("******** 1.play ********\n");
	printf("******** 0.exit ********\n");
	printf("************************\n");
}

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:》");
        //玩家输入,1 开始游戏,0 退出游戏,其它重新输入
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();//选择1,调用游戏函数,开始游戏
			break;
		case 0:
			printf("退出游戏。\n");
			break;

		default:
			printf("选择错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

初始化游戏界面

定义两个数组,一个是玩家可以看到雷的信息的游戏矩阵;一个是玩家看不到,放置雷的后台矩阵。

游戏开始后,我们可以使用两个符号代表已经翻开的格子和未被翻开的格子,本文使用是 ‘ * ‘ 未翻开,放在玩家可以看到的游戏矩阵里;’ 0 ‘ 已经翻开,放在玩家看不到,放置雷的后台矩阵里。利用循环将游戏界面的那个矩阵依次赋值为 ’ * ' 或 ‘ 0 ‘ 即可。

代码实现

test.c


    char mine[ROWS][COLS];
	char show[ROWS][COLS];


	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

 game.c

//初始化游戏界面
void InitBoard(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 <=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");
	}
}

放置雷

利用随机函数产生的数作为雷的坐标,用循环将后台矩阵此处坐标的 ’ 0 ‘ 替换成雷的符号,

雷的符号设置为 ’ 1 ‘。

代码实现

void SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

排雷及游戏判定

玩家输入要排查的坐标后,先用 if 检查数值是否合规,输入的坐标值需要可以在游戏界面矩阵上面可以找到;然后检查坐标位置是否是雷,当坐标符号和雷的符号 ’1 ‘一致时,则游戏结束。或者将所有不是雷的坐标排查完,剩下的未被排查到的坐标全是雷,游戏结束。

代码实现

//排雷,玩家开始游戏,输入需要排查的坐标
void FindMine(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");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int count = GetMineCount(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);
	}
}

计算周围雷的数量

如图,横坐标为 x ,纵坐标为 y ,当我们要计算出 q 坐标周围雷的数量的时候,可以发现它周围的格子的坐标是可以被算出来的,假如 q 的坐标是(x, y),那么它的左上角为((x-1),(y-1)),上方为(x,(y-1)),右上角为((x+1),(y-1)),以此类推可以算出它周围的所有坐标。

因为在前面设置了雷的符号为 ’ 1 ‘,所当我们找到 q 坐标处周围的所有坐标时,将周围所有坐标处的值 ’ 1 ‘ 相加,它们的和就是 q 坐标处雷的数量,在将和赋值给 q ,打印矩阵,我们就可以看到 q 处坐标周围雷的数量。

代码实现

//计算坐标周围的雷的数量
int GetMineCount(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] - '0' * 8);
}

(在定义游戏矩阵的行数和列数时,程序真正的创建的矩阵行数和列数要大于游戏矩阵,不然当坐标处于边界时,(x-1)、(y-1)的值便会越界。比如本文的游戏矩阵为 9X9,程序真实创建的矩阵为 11X11) 

//扫雷游戏界面的行数和列数
#define ROW 9
#define COL 9

//在我们计算坐标周围的雷的数量的时候防止越界,实际使用的数组
#define ROWS ROW+2
#define COLS COL+2

完整的源代码及注释

头文件 game . h

头文件提供函数和类的声明

#pragma once

#include <stdio.h>

//随机函数 srand 的头文件
#include <stdlib.h>

//时间函数 time 的头文件
#include <time.h>

//雷的数量
#define EASY_COUNT 10

//扫雷游戏界面的行数和列数
#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);

//打印游戏界面
void DisplayBoard(char board[ROWS][COLS], int row, int col);

//在游戏界面上放置雷
void SetMine(char board[ROWS][COLS], int row, int col);

//开始游戏,开始排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

源文件提供函数和类的实现

源文件 test . c

#define _CRT_SECURE_NO_WARNINGS

//引用头文件
#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];

	//初始化界面
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	//打印游戏界面
	
	//DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);

	//放置雷
	SetMine(mine, ROW, COL);

	//这里可以看到放置雷后的游戏界面,能看到雷在棋盘上的位置
	//DisplayBoard(mine, ROW, COL);

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

int main()
{
	int input = 0;
	//随机函数,使每次游戏雷的坐标不同
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:》");

        //玩家输入,1 开始游戏,0 退出游戏,其它重新输入
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏。\n");
			break;

		default:
			printf("选择错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

源文件 game . c

#define _CRT_SECURE_NO_WARNINGS

#include "game.h"

//初始化游戏界面
void InitBoard(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 <=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 SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}
//计算坐标周围的雷的数量
int GetMineCount(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] - '0' * 8);
}

//排雷,玩家开始游戏,输入需要排查的坐标
void FindMine(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");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int count = GetMineCount(mine, x, y);
				show[x][y] = count + '0';
				DisplayBoard(show, ROW, COL);
				win++;//当雷的数量为 10 ,矩阵为 9x9 时,win 值为 89 时,游戏获胜
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
	//把所有不是雷的位置找到,游戏获胜
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你!排雷成功!\n");
		DisplayBoard(mine, ROW, COL);
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值