前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >实现Windows经典游戏——扫雷

实现Windows经典游戏——扫雷

作者头像
Yui_
发布于 2024-10-16 00:08:43
发布于 2024-10-16 00:08:43
20000
代码可运行
举报
文章被收录于专栏:Yui编程知识Yui编程知识
运行总次数:0
代码可运行

扫雷游戏以前是windows的内置小游戏,相信不少人都玩过这么一款游戏。

1.扫雷游戏规则

以9*9的简单模式为例,游戏开始时系统会生成10颗雷随机分布在这9*9的格子当中。

当你点开其中的一格,将会显示该点周围8格的雷的数量

游戏的胜利条件就是排查所有的雷。

2.游戏实现

每次游戏都是要有菜单的,下面会写一次功能简单的菜单.仅支持游玩和退出。

2.1 简单的游戏菜单

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdio.h>
void menu()
{
	printf("***********************\n");
	printf("******** 1.play    ****\n");
	printf("******** 0.exit    ****\n");
	printf("***********************\n");
}
int main()
{
	int input = 0;
	do
	{
		menu();//打印菜单
		printf("请输入>");
		scanf("%d",&input);
		switch(input)
		{
			case 1:
				break;
			case 0:
				break;
			default:
				printf("请重新输入\n");
				break;
		}
	}while(input);
	return 0;
}

2.2游戏逻辑

当玩家通过菜单进入到游戏中,我们要创建一个棋盘来玩游戏啊,那么棋盘要怎么生成呢?利用字符数组来输出,以9*9的棋盘为例,我们将字符数组的长和宽定义为11*11.为什么要这么写呢,目的是为了方便后续对棋盘位置周围雷数的计算。我们先画一个棋盘。

统计图中标有红色圆圈周围有多少雷,难道我们还要去特别判断一下位置吗,这样会让游戏的实现变得繁琐且无意义,所以我们要改变思路,为这个棋盘加上两行两列。

加上的两行两列上不会布置雷,这样统计棋盘位置周围有多少颗雷就很方便了,所有的棋盘位置都是一样计算。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//test.c
void game()
{
	char mine[11][11];//利用字符型数组表示棋盘
	char show[11][11];
}

为什么要用到两个字符型数组呢?

我们要知道扫雷棋盘中的每个格子都是有两种信息的,在没点开前每个格子就已经存放了周围8格的雷的数量的信息,除此之外还有要隐藏信息的字符格覆盖信息。两种信息在不使用结构体的情况下是无法表示的,所以我使用了两格字符数组,一个存放地雷信息,一个存放覆盖信息的字符。

为了后续代码的可维护性我们要定义标识常量

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//game.h
#define Row 9
#define Col 9

#define Rows Row+2
#define Cols Col+2

//test.c
void game()
{
	char mine[Rows][Cols] = {0};//利用字符型数组表示棋盘
	char show[Rows][Cols] = {0};
}
//...

2.3 棋盘初始化

我们将棋盘分为两个,一个是展示棋盘(给玩家看的),一个是藏雷棋盘(不给玩家看的)。 展示棋盘的初始化我们全初始化为’*’ 藏雷棋盘全部初始化为‘0’.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//game.c
//初始化展示棋盘
void InitBoard(char board[Rows][Cols],int rows,int cols,char ch)
{
	for(int i = 0;i<rows;++i)
	{
		for(int j = 0;j<cols;++j)
		{
			board[i][j] = ch;//ch == '*'
		}
	}
}
//初始化藏雷棋盘
void InitBoard(char board[Rows][Cols],int rows,int cols,char ch)
{
	for(int i = 0;i<rows;++i)
	{
		for(int j = 0;j<cols;++j)
		{
			board[i][j] = ch;//ch == '0'
		}
	}
}
//test.c
void game()
{
	char mine[Rows][Cols] = {0};//利用字符型数组表示棋盘
	char show[Rows][Cols] = {0};
	//初始化棋盘
	InitBoard(mine,Rows,Cols,'0');
	InitBoard(show,Rows,Cols,'*');
}

2.4 打印棋盘

为方便玩家找到棋盘各个位置的坐标,我们会打印相应的数字对玩家进行提示,便于玩家找到坐标。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void PrintBoard(char board[Rows][Cols],int row,int col)
{
	printf("0 1 2 3 4 5 6 7 8 9\n");
	for(int i = 1;i<=row;++i)
	{
		printf("%d",i);
		for(int j = 1;j<=col;++j)
		{
			printf(" %c",board[i][j]);
		}
		printf("\n");
	}
}

2.5 随机布雷

初始化完棋盘后我们要往藏雷棋盘里面开始布置地雷了,为了达到随机布置的效果,我们要利用到rand函数。因为这了我们用了rand函数,所以我必须在前面写上srand来给rand函数提供随机种子,为此我们还需要用到time为srand提供数字来帮助它输出随机种子.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//为rand提供随机种子
	do
	{
		menu();//打印菜单
		printf("请输入>");
		scanf("%d",&input);
		switch(input)
		{
			case 1:
				break;
			case 0:
				break;
			default:
				printf("请重新输入\n");
				break;
		}
	}while(input);
	return 0;
}

开始布置雷

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//game.h
#define Row 9
#define Col 9

#define Rows Row+2
#define Cols Col+2

#define MineNum 10//藏雷个数

//game.c
void SetMine(char mine[Rows][Cols],int row,int col)
{
	int count = MineNum;//布置10颗雷
	int x = 0;
	int y = 0;
	while(count)
	{
		x = rand()%row+1;//产生的x范围为1~9
		y = rand()%col+1;
		if(mine[x][y]=='0')
		{
			mine[x][y] = '1';
			count-=1;
		}
	}
}

2.6 玩家操作

布置完了雷后玩家就可以开始操作了,玩家扫雷利用的棋盘的坐标来排雷。 玩家操作的逻辑是,给个坐标供玩家选择,不能超过棋盘的范围,如果没超过,就判断是否说已经选取过的坐标。因为玩家会存在胜利和失败两种结果,为了达成胜利结局,我们就必须的排除所有的雷,也就是把所有非雷的位置找到,为此我们可以设置一个数字来表示当前棋盘内还有多少非雷位置未被找到。所以我们可以定义一个变量来表示剩余的非雷元素。当这个变量减为0时就代表玩家胜利了。失败的条件当然就是触雷了,当玩家触雷时,我们打印一下藏雷表给玩家看。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void Demining(char mine[Rows][Cols], char show[Rows][Cols], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = row * col - MineNum;//正常格子的数目
	while (count)
	{
		printf("利用坐标进行排雷>");
		scanf("%d %d", &x, &y);
		if (x<1 || y<1 || x>row || y>col)
		{
			printf("坐标非法!\n");
		}
		else if (show[x][y] != '*')
		{
			printf("该坐标已被选择\n");
		}
		else
		{
			//判断所选坐标是不是雷,如果是雷则游戏失败
			if (mine[x][y] == '1')
			{
				printf("你被炸死了!\n");
				PrintBoard(mine, row, col);
				break;
			}
			else
			{
				//不是雷就开始计算周围雷的数目
				count -= 1;
				int ret = MineCount(mine, x, y);
				show[x][y] = '0' + ret;
				//打印棋盘展示
				PrintBoard(show, row, col);
			}
		}
	}
	if (count == 0)
	{
		printf("扫雷成功!\n");
	}
	else
	{
		printf("扫雷失败!\n");
	}
}

//计算周围雷的数目
int MineCount(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][y + 1]
		+ mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - '0' * 8;
}

3.代码整合

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define Row 9
#define Col 9

#define Rows Row+2
#define Cols Col+2

#define MineNum 10

void InitBoard(char board[Rows][Cols], int rows, int cols, char ch);

void PrintBoard(char board[Rows][Cols], int row, int col);

void SetMine(char mine[Rows][Cols], int row, int col);

void Demining(char mine[Rows][Cols], char show[Rows][Cols], int row, int col);

int MineCount(char mine[Rows][Cols], int x, int y);


//game.c
#include "game.h"

void InitBoard(char board[Rows][Cols], int rows, int cols, char ch)
{
	for (int i = 0; i < rows; ++i)
	{
		for (int j = 0; j < cols; ++j)
		{
			board[i][j] = ch;//ch == '*'
		}
	}
}

void PrintBoard(char board[Rows][Cols], int row, int col)
{
	printf("0 1 2 3 4 5 6 7 8 9\n");
	for (int i = 1; i <= row; ++i)
	{
		printf("%d", i);
		for (int j = 1; j <= col; ++j)
		{
			printf(" %c", board[i][j]);
		}
		printf("\n");
	}
}

void SetMine(char mine[Rows][Cols], int row, int col)
{
	int count = MineNum;//布置10颗雷
	int x = 0;
	int y = 0;
	while (count)
	{
		x = rand() % row + 1;//产生的x范围为1~9
		y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count -= 1;
		}
	}
}

void Demining(char mine[Rows][Cols], char show[Rows][Cols], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = row * col - MineNum;//正常格子的数目
	while (count)
	{
		printf("利用坐标进行排雷>");
		scanf("%d %d", &x, &y);
		if (x<1 || y<1 || x>row || y>col)
		{
			printf("坐标非法!\n");
		}
		else if (show[x][y] != '*')
		{
			printf("该坐标已被选择\n");
		}
		else
		{
			//判断所选坐标是不是雷,如果是雷则游戏失败
			if (mine[x][y] == '1')
			{
				printf("你被炸死了!\n");
				PrintBoard(mine, row, col);
				break;
			}
			else
			{
				//不是雷就开始计算周围雷的数目
				count -= 1;
				int ret = MineCount(mine, x, y);
				show[x][y] = '0' + ret;
				//打印棋盘展示
				PrintBoard(show, row, col);
			}
		}
	}
	if (count == 0)
	{
		printf("扫雷成功!\n");
	}
	else
	{
		printf("扫雷失败!\n");
	}
}

int MineCount(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][y + 1]
		+ mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - '0' * 8;
}

//test.c
void game()
{
	char mine[Rows][Cols] = { 0 };//利用字符型数组表示棋盘
	char show[Rows][Cols] = { 0 };
	//初始化
	InitBoard(mine, Rows, Cols, '0');
	InitBoard(show, Rows, Cols, '*');
	//打印棋盘
	PrintBoard(show, Row, Col);
	//布置地雷
	SetMine(mine, Row, Col);
	//PrintBoard(mine, Row, Col);
	Demining(mine, show, Row, Col);
}
void menu()
{
	printf("***********************\n");
	printf("******** 1.play    ****\n");
	printf("******** 0.exit    ****\n");
	printf("***********************\n");
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//为rand提供随机种子
	do
	{
		menu();//打印菜单
		printf("请输入>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("请重新输入\n");
			break;
		}
	} while (input);
		return 0;
}

效果

关于为什么没有展开 对于让周围没有雷的个格子展开,你们可以来实现,展开格子的特点就是:

  1. 该坐标不是雷,周围没有雷 该坐标也没有被展开过(用递归展开)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
python剪切文件
心血来潮,手机上导出的图片全部按日期放在不同文件夹,很是麻烦,想放在一起方便浏览,手动操作费时费力,想到bat令,不是很熟,看到python欣喜不已,很是方便
狼啸风云
2020/07/30
1.2K0
Python教程:os 与 sys 模块详细用法
总结 os 模块功能很多很杂,不可能全都记住,但是下面的这些功能我们日后会经常用到,一定要尽量学会使用:
闻说社
2025/04/28
1470
Python教程:os 与 sys 模块详细用法
Python Python的os包
Python的os包 os的文件与目录函数介绍 import os 函数名 参数 介绍 举例 返回值 getcwd 无 返回当前的路径 os.getcwd() 字符串 listdir path 返回制定路径下所有的文件或文件夹 os.listdir(‘c//Windows’) 返回一个列表 makedirs Path mode 创建多级文件夹 os.makedir(‘d//imooc/py’) 无 removedirs path 删除多级文件夹 os.removedirs(‘d://imooc/py’)
Zkeq
2022/05/18
9150
python第二十七课——os模块
演示os模块中常用的属性和函数: 1.os模块: 作用:管理文件和目录 属性: os.name:返回系统类型 常用的windows系统 --> nt os.environ:返回当前系统所有的环境变量 os.environ.get(ver):返回ver环境变量的内容
hankleo
2020/09/16
3400
Python入门(五):常用标准库sys和os
我们可以编写自己的模块,也可以使用大量的Python标准库模块和开源模块,站在巨人的肩上行动,正因为如此,使得当今python如此热门,今天就让我们来一起领略python开源库的魅力。
披头
2019/12/26
1.9K0
Python基础语法-内置函数和模块-os模块
os 模块提供了一些函数来与操作系统进行交互,比如获取当前工作目录、创建目录、删除目录、重命名文件等等。在本文中,我们将详细介绍 os 模块的常用函数。
玖叁叁
2023/04/18
3130
Python 目录操作
os.path.isdir(name):判断name是不是一个目录,name不是目录就返回false
py3study
2020/01/13
6960
python 文件操作总结
file:路径+文件 mode:打开模式;r只读,w写入,a追加, encoding:编码方式
火星娃统计
2020/12/22
3390
(汇总)os模块以及shutil模块对文件的操作
''' # os 模块 os.sep 可以取代操作系统特定的路径分隔符。windows下为 '\\' os.name 字符串指示你正在使用的平台。比如对于Windows,它是'nt',而对于Linux/Unix用户,它是 'posix' os.getcwd() 函数得到当前工作目录,即当前Python脚本工作的目录路径 os.getenv() 获取一个环境变量,如果没有返回none os.putenv(key, value) 设置一个环境变量值 os.listdir(path) 返回指定目录下的所有文件和目
汪凡
2018/05/29
9000
python之OS模块(对文件or目录操
  os,语义为操作系统,包含普遍的操作系统功能,与具体的平台无关。python编程时,处理文件和目录这些操作,就比如说:显示当前目录下所有文件/删除某个文件/获取文件大小……
py3study
2020/01/09
6640
python 文件 目录操作
python中对文件、文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块。 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 返回指定目录下的所有文件和目录名:os.listdir() 函数用来删除一个文件:os.remove() 删除多个目录:os.removedirs(r“c:\python”) 检验给出的路径是否是一个文件:os.path.isfile() 检验给出的路径是否是一个目录:os.path.isdir() 判断是否是绝对路径:os.path.isabs() 检验给出的路径是否真地存:os.path.exists() 返回一个路径的目录名和文件名:os.path.split() eg os.path.split('/home/swaroop/byte/code/poem.txt') 结果:('/home/swaroop/byte/code', 'poem.txt') 分离扩展名:os.path.splitext() 获取路径名:os.path.dirname() 获取文件名:os.path.basename() 运行shell命令: os.system() 重命名:os.rename(old, new) 创建多级目录:os.makedirs(r“c:\python\test”) 创建单个目录:os.mkdir(“test”) 获取文件属性:os.stat(file) 修改文件权限与时间戳:os.chmod(file) 终止当前进程:os.exit() 获取文件大小:os.path.getsize(filename) getsize os.path.join(路径,文件) #################################### '/var/log/message' \>>> y=os.path.dirname(a) \>>> y '/var/log' \>>> b='message' \>>> aa=os.path.join(y,b) \>>> print aa /var/log/message ####################################
py3study
2020/01/09
9640
Python基础教程(十四):OS 文件/目录方法
💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 💝💝💝如有需要请大家订阅我的专栏【Python系列】哟!我会定期更新相关系列的文章 💝💝💝关注!关注!!请关注!!!请大家关注下博主,您的支持是我不断创作的最大动力!!!
用户11147438
2024/06/14
1530
python os模块学习笔记
import os os.mkdir(name) #创建目录 os.path.exists(name) #判断文件或者目录是否存在 os.path.isdir(name) #判断指定对象是否为目录。是True,否则False。 os.mknod(name) #创建一个文件 os.path.isfile(name) #判断文件是否存在,存在返回True,否则返回False
py3study
2020/01/14
8290
python文件和目录操作方法大全
一、python中对文件、文件夹操作时经常用到的os模块和shutil模块常用方法。 1.得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 2.返回指定目录下的所有文件和目录名:os.listdir() 3.函数用来删除一个文件:os.remove() 4.删除多个目录:os.removedirs(r“c:\python”) 5.检验给出的路径是否是一个文件:os.path.isfile() 6.检验给出的路径是否是一个目录:os.path.isdir() 7.判断是否是绝对
用户1214487
2018/01/24
1.3K0
图解python | 文件与目录操作
教程地址:http://www.showmeai.tech/tutorials/56
ShowMeAI
2022/02/23
1K0
图解python | 文件与目录操作
Python: os模块实例详解
import os 操作文件 # I use jupyter notebook to create some file !touch foo.txt !echo Hello > foo.txt !cat foo.txt Hello # rename file os.rename('foo.txt','bar.txt') !cat bar.txt Hello # remove file os.remove('bar.txt') 改变目录 # current dir print os.getcwd() # cu
用户2183996
2018/06/28
8660
python3基础:目录操作
os模块提供了统一的操作系统接口函数,python中对文件和文件夹的操作都要涉及到os和shutil模块,在使用前需要使用import引入,例如;
py3study
2020/01/09
1.3K0
python os模块
删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
py3study
2018/08/02
8300
(十) 初遇python甚是喜爱之OS Module模块
各位读者大大们大家好,今天学习python的OS Module模块,并记录学习过程欢迎大家一起交流分享。
XXXX-user
2019/07/23
4650
(十) 初遇python甚是喜爱之OS Module模块
python 的路径操作
os.sep 表示默认的文件路径分隔符,windows为\, linux为/ os.walk(spath): 用来遍历目录下的文件和子目录 os.listdir(dirname):列出dirname下的目录和文件 os.mkdir() : 创建目录 os.makedirs(): 创建目录,包含中间级目录 os.remove():删除文件,不能是目录 os.rmdir():删除空目录 os.removedirs(path):删除目录及其子目录 os.rename(src, dst) :修改文件名 os.renames(old, new) :修改文件或目录名,包含中间级
py3study
2020/01/10
1.8K0
相关推荐
python剪切文件
更多 >
目录
  • 1.扫雷游戏规则
  • 2.游戏实现
    • 2.1 简单的游戏菜单
    • 2.2游戏逻辑
    • 2.3 棋盘初始化
    • 2.4 打印棋盘
    • 2.5 随机布雷
    • 2.6 玩家操作
  • 3.代码整合
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档