C++实现扫雷游戏示例讲解
作者:叁三山雨 发布时间:2022-05-03 18:49:05
标签:C++,游戏,扫雷
C/C++实现扫雷小游戏
源代码:
github:https://github.com/KamSss/C-Practice/tree/master/Minesweeper扫雷小游戏/Minesweeper扫雷
总体构造:
a.简易的游戏菜单逻辑
b.初始化棋盘
c.布置雷的位置
d.排雷、棋盘打印、判断输赢(难点)
a.简易的游戏菜单逻辑
简单的通过一个输入0和1实现判断是玩游戏还是退出游戏的逻辑
输入1则进入游戏
输入0则break退出游戏,且退出do…while循环,程序结束。
void test(){
int input = 0;
do{
menu();
cout << "请输入:>--";
cin >> input;
switch (input)
{
case 1:
game();
break;
case 0:
cout << "退出游戏" << endl;
break;
default:
cout << " 选择错误!请重新输入" << endl;
break;
}
} while (input);
}
b.初始化棋盘
一、越界情况的考虑
为了减少边界情况可能出现越界访问的情况,把棋盘扩大一圈,但是在显示的时候只显示没扩大之前的棋盘。
二、棋盘打印的考虑
如果只使用一个二维数组,同时要记录雷的位置和每一个位置附近的雷数以及点击和未点击的位置显示显然不合适。
所以: 初始化两个棋盘,一个专门用来存放雷的位置,一个专门用于打印当前棋盘给玩家看。
//初始化格子
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
memset(&board[0][0], set, rows*cols*sizeof(board[0][0]));
}
初始化完,得到一个全0的雷盘,和一个全*的显示盘。
c.布置雷的位置
这里用随机数布置雷的位置,会不会对同一个点多次放雷呢?这里的解决办法是,如果当前随机到的位置已经有雷就再随机一个位置防雷。
void SetMine(char board[ROWS][COLS], int row, int col)
{
srand((unsigned int)time(NULL));
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--;
}
}
}
d.排雷、棋盘打印、判断输赢(难点)d
排雷的逻辑判断:
如果没有雷如何打印棋盘呢?
扫雷应该做到,“点击”棋盘之后,一路“打开”到最近的出现雷的边界上。
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int offset_x = 0;
int offset_y = 0;
int count = 0;
//坐标合法
if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
{
//遍历周围坐标
for (offset_x = -1; offset_x <= 1; offset_x++)
{
for (offset_y = -1; offset_y <= 1; offset_y++)
{
//如果这个坐标不是雷
if (mine[x + offset_x][y + offset_y] == '0')
{
//统计周围雷的个数
count = GetMineCount(mine, x + offset_x, y + offset_y);
if (count == 0)
{
if (show[x + offset_x][y + offset_y] == '*')
{
show[x + offset_x][y + offset_y] = ' ';
Spread(mine, show, x + offset_x, y + offset_y);
}
}
else
{
show[x + offset_x][y + offset_y] = count + '0';
}
}
}
}
}
}
如何判断输赢:
很简单,踩到雷 board[i][j] == 1
所有的雷都出现了 * == MineCount 就赢了
//判断是否排雷成功
int IsWin(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (show[i][j] == '*')
{
count++;
}
}
}
return count == EASY_COUNT;
}
来源:https://blog.csdn.net/qq_42685588/article/details/98476029


猜你喜欢
- 目录1、概念相关1.1、概念1.2、解决了什么:1.3、场景:2、简单实现2.1 代码3. netty中的责任链模式4、思考本文先介绍了责任
- 本文实例讲述了C#实现xml文件反序列化读入数据到object的方法。分享给大家供大家参考。具体实现方法如下:public static o
- Java中避免NullPointerException的方法总结在字符串常量上调用equals// good"string lit
- 前言这里用swing ,awt写的。我们大概要做成一个电脑的记事本那样的一个编辑器。可以调整字体,字号,颜色。能够打开、保存文件,新建窗口,
- 1.Object类里面常用的方法:protected Object clone()创建并返回此对象的一个副本。boolean equals(
- 前言系统很多地方都会抛出异常, 而Java的异常体系目标就是与逻辑解耦,Spring提供了统一的异常处理注解,用户只需要在错误的时候提示信息
- 一、IDEA下载idea、jdk、tomcat、maven下载地址请参考上一篇博客:https://blog.csdn.net/DwZ735
- 本文实例讲述了java使用Hashtable过滤数组中重复值的方法。分享给大家供大家参考,具体如下:package org.eline.co
- 详解Java虚拟机管理的内存运行时数据区域概述 Java虚拟机在执行Java程序的过程中会把它所管理的内
- 本文实例讲述了Java编程中文件读写的方法。分享给大家供大家参考,具体如下:Java中文件读写操作的作用是什么?回答这个问题时应该先想到的是
- 什么是线程同步? 当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机
- 这是个很简单的问题,但每次隔一段时间后使用起来总是会出点乱子。这里记录下Logcat的步骤:1,在Activity里申明tag变量(名字其实
- 在使用Java集合的时候,都需要使用Iterator。但是java集合中还有一个迭代器ListIterator,在使用List、ArrayL
- Android 中倒计时验证两种常用方式实例详解短信验证码功能,这里总结了两种常用的方式,可以直接拿来使用。看图:说明:这里的及时从10开始
- 题目一(有关传值调用与非法访问)请问运行Test 函数会有什么样的结果?答 :程序运行会崩溃 ! 且存在内存泄漏 ;原因:1.str传给p的
- 发现问题:之前用springAOP做了个操作日志记录,这次在往其他类上使用的时候,service一直注入失败,找了网上好多内容,发现大家都有
- /** * 实现 * @author dujinyang * */顺序是: OneAcitivity
- 综述在Android系统中,出于对性能优化的考虑,对于Android的UI操作并不是线程安全的。也就是说若是有多个线程来操作UI组件,就会有
- 本文实例讲述了Java实现多个wav文件合成一个的方法。分享给大家供大家参考,具体如下:前面一篇介绍了java切割wav音频文件的方法,这里
- 前言本次示例代码的文件结构如下图所示。1. 导入依赖坐标在 order-service 的 pom.xml 文件中导入 Feign 的依赖坐