赞
踩
这篇文章是用C++来简单讲解扫雷代码怎么实现。首先我们就得先理清代码思路,先看这张图片。
可以看到,游戏中的棋盘(我没实际看到的),没有被排除的地方就是灰白色方块,被掩盖,排查之后出现的数字,是代表这个地方周围一圈(八个位置)总共有多少个雷(随机位置),而旗帜是用来标记雷的(暂时不做实现)。那么在代码实现过程中,我们就需要做到扫雷棋盘的创建,随机放置雷,排查雷以及棋盘的打印。仅用C++,我们肯定暂时做不到正常游戏那样,所以我们就需要两个棋盘,一个棋盘给玩家看假设刚开始全是字符 * ,每当我们选择排查的坐标时,就会进入到另一个隐藏的棋盘,同坐标下排查,与游戏的棋盘同呼应,这样说肯定会有点抽象,先看图
至于为什么行列都加二,后面会说。当玩家输入坐标时,假如2 3,反应的其实是隐藏的棋盘,假如隐藏的棋盘2 3坐标布置了雷,游戏就结束了,假如没有雷,那么就会根据隐藏的棋盘的坐标2 3计算周围一圈有几个雷,再返回一个数据,输出到玩家看到的棋盘上。
#include<iostream>
using namespace std;
void menu() //打印菜单
{
cout << "***************************" << endl;
cout << "***********1.play**********" << endl;
cout << "***********0.exit**********" << endl;
cout << "***************************" << endl;
}
int main()
{
int n = 0;
do
{
menu();
cout << "请输入:";
cin >> n;
switch (n)
{
case 1: break;
case 0:cout << "游戏结束" << endl; break;
default:cout << "输入错误,请重新输入" << endl; break;
}
} while (n);
return 0;
}
这里我们使用do while循环和switch来控制游戏的开始和结束,while循环的条件是n,1表示游戏开始并且循环继续,0表示结束,循环也会结束,执行效果如下,menu()函数随便写写就是了。
框架完成那就该写这个游戏需要的函数了,首先需要在源文件添加两个新项,鼠标右击源文件添加新建项,一个项名字写 头文件名称.h , 另一个项名字写为 头文件名称.cpp
game.h项用来存放需要函数的声明以及一些定义的常量,game.cpp就是用来实现game.h声明后的函数。
我们现在game.h里声明函数,在此之前,先定义一些常变量,表示棋盘矩阵的行和列,可以看到,这里的EasyNumber可以理解为简单模式(实际上就是雷的个数),我还定义了ROWS和COLS总是比ROW和COL多2,还是待会儿解释。再来看game()函数,是定义在 扫雷实现 的项里,它会调用已经实现的game.h里的函数。接下来就请看棋盘创建的代码
void Create(char chessboard[ROWS][COLS], int rows, int cols, char ch) //创建棋盘
{
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
chessboard[i][j] = ch;
}
}
}
在geme()函数中,我们已经事先定义了两个二维矩阵,我们可以看到Create()函数有四个变量,分别是数组,行,列,数组元素,而我们这里数组元素都用的char类型字符,这样可以做到创建几个数据类型相同的棋盘,用字符’0‘来表示隐藏棋盘没有雷的情况,所以等下我们布置雷就要用到字符’1‘。
void MinePlace(char chessboard[ROWS][COLS])
{
int num = EasyNumber;
int x, y;
srand(time(NULL));
while (num)
{
x = rand() % 10 + 1;
y = rand() % 10 + 1;
if (chessboard[x][y] == '0')
{
chessboard[x][y] = '1';
num--;
}
}
}
这个函数的实现还是很简单,但是这里用到了srand(),time()和rand()【资料来源于百度百科】,srand和rand的头文件都是<cstdlib>(C语言是<stdlib.h>),time()的头文件是<ctime>,然后rand()产生的随机数模上10+1就将产生的数字控制在1-10之间,分别赋值给x和y
再根据坐标将字符’0‘改成字符’1‘,只能原来是’0‘才会成功修改,并且使应该布置的雷个数减一,避免重复。
void Print(char chessboard[ROWS][COLS], int rows, int cols)
{
for (int i = 0; i <= rows; i++) {
cout << i << " ";
}
cout << endl;
for (int i = 1; i <= rows; i++) {
cout << i << " ";
for (int j = 1; j <= cols; j++) {
cout << chessboard[i][j] << " ";
}
cout << endl;
}
}
三个变量,依次是数组,行,列,第一个for循环打印的第一行数字是让棋盘打印更加直观且美观,第二个for循环从1行1列开始打印,看打印效果就知道了。这个函数对所以棋盘都有效。
int MarkerMine(char chessboard[ROWS][COLS], int x, int y)
{
return chessboard[x - 1][y - 1]
+ chessboard[x - 1][y]
+ chessboard[x - 1][y + 1]
+ chessboard[x][y - 1]
+ chessboard[x][y + 1]
+ chessboard[x + 1][y - 1]
+ chessboard[x + 1][y]
+ chessboard[x + 1][y + 1] - 8 * '0';
}
void FindMine(char gamemode[ROWS][COLS], char actualmode[ROWS][COLS], int row, int col)
{
int x, y;
int count = 0;
int win = 0;
while (win < row * col - EasyNumber)
{
cout << "请输入你要排查的坐标:";
cin >> x >> y;
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (actualmode[x][y] == '1')
{
cout << "你被炸死了,游戏结束" << endl;
Print(actualmode, ROW, COL); break;
}
else
{
count = MarkerMine(actualmode, x, y);
gamemode[x][y] = count + '0';
Print(gamemode, ROW, COL);
win++;
}
}
else
{
cout << "坐标非法,请重新输入" << endl;
}
if (win == row * col - EasyNumber)
cout << "恭喜你,排查成功!" << endl;
}
}
这排查雷会讲到之前的疑惑,先看第二个函数,四个变量,依次是游戏棋盘,隐藏棋盘,行和列,变量count是用来存输入一个坐标后,如果该坐标不是雷,周围有多少个雷。变量win用来存储我们排查了多个次,如果等于 棋盘数-雷的个数(win == row * col - EasyNumber),那我们就排查成功。while循环我们没输入一个坐标,就会往隐藏棋盘反应,踩雷游戏就结束,没踩雷,就计算周围雷的个数,接下来就看第一个函数int MarkerMine(char chessboard[ROWS][COLS], int x, int y),进入到函数,我们发现就一个return函数还要一堆加法。
假如我输入 4 5 (实际输入是 3 4) 坐标,看周围就两个1,此时我们知道ASCII码表知道字符’0‘是48,’1‘是49,’2‘是50,我们将周围每个坐标减去一个’0‘,就能得到一个整型数据,再相加,就能得到周围雷的个数,但这是整型,之后我们再将count加上一个’0‘,这样就变成ASCII值的雷的个数,然后在将这个值赋值给玩家看到的游戏棋盘再打印出来,再看坐标 7 3(实际输入是 6 2 ),此坐标周围多出来一行,实际上我们创建棋盘的时候都赋值为'0',所以依旧适用我们写的int MarkerMine(char chessboard[ROWS][COLS], int x, int y)函数
这实际上是我们使用的棋盘,最外层是有字符'0'的,这里我写的数字代表行列,也是打印出来我们看见的,这也就是为什么我们要把行列都加二的原因
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。