前言
最近学会了扫雷,今天我用C++给他敲了出来。(新的问题是,他就很差劲 )
效果图
来来来,上效果图。
源码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iomanip>
using namespace std;
int board[15][15]; // 雷图: 9 表示 地雷; 0~8 表示周边八格雷数
int show[15][15]; // 展示状态图: 0 表示 未知; 1 表示 已知; 2 表示 旗子🚩
// 游戏规则展示
void intro()
{
cout << "===============================================" << endl;
cout << " ***欢迎运行扫雷游戏!***" << endl;
cout << " 【游戏规则如下:】" << endl;
cout << " 在这个游戏里会有一个 9*9 的网格,网格中埋着 10颗雷" << endl;
cout << " 游戏目标是找出所有的雷,如果触雷,则游戏失败" << endl;
cout << " 每次输入要操作的格子 行、列,1表示翻开,2表示标记/取消旗子🚩" << endl;
cout << " 格子中的数字表示它周围八个格中有几个雷" << endl;
cout << " *第一次翻格子不会是雷" << endl;
cout << " 按下 回车键 开始游戏" << endl;
cout << "================================================" << endl << endl;
getchar();
}
// 打印当前棋盘
void drawBoard()
{
cout << "\033c" << flush;
// 输出行号
cout << " ";
for (int i = 1; i <= 9; i++) cout << " " << i;
cout << " \n";
// 输出上边框
cout << " ╔";
for (int i = 1; i <= 8; i++) cout << "═══╤";
cout << "═══╗\n";
// 输出中间部分
for (int i = 1; i <= 9; i++) // 行
{
cout << " " << i << " ║";
for (int j = 1; j <= 9; j++) // 列
{
if (show[i][j] == 0) // 未知
cout << "\033[47m \033[0m";
if (show[i][j] == 1) // 已知
{
if (board[i][j] == 9) // 雷
cout << "\033[31m ※ \033[0m";
if (board[i][j] == 0) // 空白
cout << " ";
if (board[i][j] > 0 && board[i][j] < 9) // 数字
cout << " " << board[i][j] << " ";
}
if (show[i][j] == 2) // 旗子
{
cout << "\033[47m 🚩 \033[0m";
}
if (j != 9)
cout << "│";
else
cout << "║";
cout << "";
}
cout << " \n";
cout << " ";
// 输出下边框
if (i != 9)
{
cout << " ╟";
for (int i = 1; i <= 8; i++) cout << "───┼";
cout << "───╢\n";
}
else
{
cout << " ╚";
for (int i = 1; i <= 8; i++) cout << "═══╧";
cout << "═══╝\n";
}
}
}
// 标记/取消旗子🚩
void mark(int x, int y)
{
if (show[x][y] == 1) return;
if (show[x][y] == 2) show[x][y] = 0;
else show[x][y] = 2;
}
// 判断是否与已翻开的空白格相邻
bool near(int x, int y)
{
for (int i = x-1; i <= x+1; i++)
{
for (int j = y-1; j <= y+1; j++)
{
if (board[i][j] == 0 && show[i][j] == 1)
{
return true;
}
}
}
return false;
}
// 翻开格子
void open(int x, int y)
{
show[x][y] = 1;
// 重复 8 次,扫描翻开区域
for (int t = 1; t <= 8; t++)
{
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
if (board[i][j] != 9 && show[i][j] == 0 && near(i, j))
{
show[i][j] = 1;
}
}
}
}
}
// 初始化雷图
void init(int x, int y)
{
// 生成 10 个雷
srand(time(0));
for (int i = 1; i <= 10; i++)
{
int hang, lie;
while (true)
{
hang = rand() % 9 + 1;
lie = rand() % 9 + 1;
// 避开初次翻开的格子和雷
if (board[hang][lie] != 9 && (abs(hang - x) > 1 || abs(lie - y) > 1))
{
board[hang][lie] = 9;
break;
}
}
}
// 生成雷图
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
if (board[i][j] == 9) continue;
for (int xx = i-1; xx <= i+1; xx++)
{
for (int yy = j-1; yy <= j+1; yy++)
{
if (board[xx][yy] == 9) board[i][j]++;
}
}
}
}
}
// 扫雷失败,显示所有雷
void gameOver()
{
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
if (board[i][j] == 9)
{
show[i][j] = 1;
}
}
}
drawBoard();
cout << "游戏失败!" << endl;
}
// 判断是否获胜
bool gameWin()
{
int cnt = 0; // 未知 + 旗子 数量
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
if (show[i][j] == 0 || show[i][j] == 2)
{
cnt++;
}
}
}
return cnt == 10;
}
// 开始游戏
void game()
{
bool fst = true; // 初次
int start = time(0); // 开始时间
while (true)
{
drawBoard();
int x, y, op;
cout << "请输入行、列(1 ~ 9),操作(1 表示翻开,2 表示标记/取消旗子🚩) 例: 5 5 1" << endl;
cin >> x >> y >> op;
if (x < 1 || x > 9 || y < 1 || y > 9) continue;
if (op != 1 && op != 2) continue;
if (op == 1) // 翻开
{
if (fst) // 初次翻开
{
init(x, y);
fst = false;
}
if (board[x][y] == 9) // 游戏结束
{
gameOver();
return;
}
open(x, y);
}
if (op == 2) // 标记/取消旗子
{
mark(x, y);
}
if (gameWin()) // 判断是否获胜
{
drawBoard();
cout << "游戏胜利!" << endl;
cout << "总用时 " << time(0) - start << " s" << endl;
return;
}
}
}
int main()
{
intro(); // 游戏介绍
game(); // 开始游戏
return 0;
}
不知不觉,代码就敲出来啦。
BUG
如果您使用的是窗户系统,或者某破烂字体,或者某破烂编译器,将会出下下面的效果。
结束
本期文章就结束啦,代码不难,没看懂的就别看啊。
885+1