代码
先上代码(g++ 8.1.0 -Wall选项通过)
/*
* Minesweeper(扫雷) V2.3.0
*
* V2.3.0更新:
* - 命令 1 如果为已打开的格子,
* 若周围标记数量足够,
* 直接打开周围
* - 更改了部分Sleep事件时间参数
*
* V2.2.0更新:
* - 更新了亿堆对话
* - 增加了配色
*
* V2.1.0更新:
* - 当前所在的位置改用颜色突出显示
*
* V2.0.1更新:
* - 修复了再玩一次的Bug
*
* V2.0.0更新:
* - 去除了光标和闪屏
* - 使用上下左右或WASD控制"当前光标"位置
* - &表示当前所在的位置
* - 按下 1 打开, 按下 2 标记
* Enjoy =)
*/
#include <Windows.h>
#include <iostream>
#include <iomanip>
#include <random>
#include <conio.h>
#include <cmath>
#include <set>
using namespace std;
const int WAIT_TIME = 1000;
const int L = 10, W = 10;
const int X = L + 2, Y = W + 2;
const int back = 2;
int nowx = 1, nowy = 1;
struct Box {
Box() : youLei(false), leiLiang(0), zhuangTai(0) {};
bool youLei;
int leiLiang;
int zhuangTai;
void clear();
};
Box l[X][Y];
void click(int, int);
void flag(int, int);
void open(int,int);
void outNum(int);
void outAll();
void load();
void aGame();
int main() {
HWND hwnd = GetForegroundWindow();
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
LONG l_WinStyle = GetWindowLong(hwnd,GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, (l_WinStyle | WS_POPUP | WS_MAXIMIZE) & ~WS_CAPTION & ~WS_THICKFRAME & ~WS_BORDER);
SetWindowPos(hwnd, HWND_TOP, 0, 0, cx, cy, 0);
CONSOLE_CURSOR_INFO cursor;
cursor.bVisible = false;
cursor.dwSize = sizeof(cursor);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorInfo(handle,&cursor);
cout <<
R"(
__ ____
/ |/ (_)___ ___ ______ _____ ___ ____ ___ _____
/ /|_/ / / __ \/ _ \/ ___/ | /| / / _ \/ _ \/ __ \/ _ \/ ___/
/ / / / / / / / __(__ )| |/ |/ / __/ __/ /_/ / __/ /
/_/ /_/_/_/ /_/\___/____/ |__/|__/\___/\___/ .___/\___/_/
/_/
by c2021ldw
)";
Sleep(500);
system("cls");
try {
while (true) {
aGame();
cout << "你想再玩一次扫雷吗? 按Y确认, 其他键退出";
int tmp = getch();
if (tmp == 'Y' || tmp == 'y')
continue;
return 0;
}
}
catch (...) {
cerr << "发生了一个错误...";
Sleep(WAIT_TIME);
cout << "请联系c2021ldw!!!" << endl;
Sleep(WAIT_TIME);
return 0;
}
return 0;
}
void Box::clear() {
youLei = false;
leiLiang = 0;
zhuangTai = 0;
}
ostream& operator<<(ostream& os, Box b) {
if (b.zhuangTai == 0)
os << ' ';
if (b.zhuangTai == 1) {
if (b.youLei) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 240);
os << '*';
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
}
else {
switch (b.leiLiang) {
case 1:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 3);
break;
case 2:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 10);
break;
case 3:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
break;
case 4:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 9);
break;
case 5:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
break;
case 6:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 6);
break;
case 7:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 13);
break;
case 8:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
break;
}
os << b.leiLiang;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
}
}
if (b.zhuangTai == 2) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 8);
os << '#';
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
}
return os;
}
void click(int x, int y) {
if (l[x][y].zhuangTai == 0) {
l[x][y].zhuangTai = 1;
if (!l[x][y].youLei && l[x][y].leiLiang == 0)
open(x, y);
return;
}
if (l[x][y].zhuangTai == 1)
open(x, y);
}
void flag(int x, int y) {
if (l[x][y].zhuangTai == 0)
l[x][y].zhuangTai = 2;
else if (l[x][y].zhuangTai == 2)
l[x][y].zhuangTai = 0;
}
void open(int x, int y) {
if (X < 1 || y < 1 || x > L || y > W)
return;
int tmp = 0;
for (int i = x - 1; i <= x + 1; ++i) {
for (int j = y - 1; j <= y + 1; ++j) {
if (i == x && j == y)
continue;
if(i < 1 || j < 1 || i > L || y > W)
continue;
if(l[i][j].zhuangTai != 2)
continue;
++tmp;
}
}
if (tmp == l[x][y].leiLiang) {
for (int i = x - 1; i <= x + 1; ++i) {
for (int j = y - 1; j <= y + 1; ++j) {
if (i == x && j == y)
continue;
if(i < 1 || j < 1 || i > L || y > W)
continue;
if(l[i][j].zhuangTai != 0)
continue;
click(i, j);
}
}
}
}
void outNum(int a) {
int k = a, s = 0;
while (k != 0) {
++s;
k /= 10;
}
cout << a;
for (int i = 1; i <= back - s + 1; ++i)
cout << ' ';
}
void outAll() {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
cout << ' ';
for (int i = 1; i <= back; ++i)
cout << ' ';
for (int i = 1; i <= W; ++i)
outNum(i);
for (int i = 1; i <= L; ++i) {
cout << "\n\n";
outNum(i);
for (int j = 1; j <= W; ++j) {
if (i == nowx && j == nowy) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 143);
if (l[i][j].zhuangTai == 0)
cout << ' ';
if (l[i][j].zhuangTai == 1) {
if (l[i][j].youLei)
cout << '*';
else
cout << l[i][j].leiLiang;
}
if (l[i][j].zhuangTai == 2)
cout << '#';
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
}
else
cout << l[i][j];
for (int i = 1; i <= back; ++i)
cout << ' ';
}
}
cout << endl;
}
void load() {
system("cls");
for (int i = 0; i < X; ++i) {
for (int j = 0; j < Y; ++j)
l[i][j].clear();
}
nowx = 1;
nowy = 1;
static default_random_engine e(time(NULL));
static uniform_int_distribution<int> u1{4,L};
static uniform_int_distribution<int> u2{4,W};
set<pair<int, int>> lei;
unsigned set_lei = sqrt(L * W);
while (lei.size() != set_lei)
lei.insert(pair<int, int>(u1(e),u2(e)));
for (set<pair<int, int>>::iterator it = lei.begin(); it != lei.end(); ++it)
l[it->first][it->second].youLei = true;
for (int i = 1; i <= L; ++i) {
for (int j = 1; j <= W; ++j) {
if (l[i][j].youLei)
continue;
int s = 0;
for (int m = i - 1; m <= i + 1; ++m) {
for (int n = j - 1; n <= j + 1; ++n) {
if (l[m][n].youLei)
++s;
}
}
l[i][j].leiLiang = s;
}
}
}
bool win() {
for (int i = 1; i <= L; ++i) {
for (int j = 1; j <= W; ++j) {
if (l[i][j].zhuangTai == 1 && l[i][j].youLei)
return false;
if (l[i][j].zhuangTai == 0 && !l[i][j].youLei)
return false;
if (l[i][j].zhuangTai == 2 && !l[i][j].youLei)
return false;
}
}
return true;
}
bool lose() {
for (int i = 1; i <= L; ++i) {
for (int j = 1; j <= W; ++j) {
if (l[i][j].youLei && l[i][j].zhuangTai == 1)
return true;
}
}
return false;
}
void aGame() {
load();
while (win() == false && lose() == false) {
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = 0;
pos.Y = 0;
SetConsoleCursorPosition(handle,pos);
outAll();
int tmp = getch();
if (tmp == 224) {
tmp = getch();
if (tmp == 72)
--nowx;
else if (tmp == 75)
--nowy;
else if (tmp == 80)
++nowx;
else if (tmp == 77)
++nowy;
if (nowx < 1)
while (++nowx < 1);
if (nowx > L)
while (--nowx > L);
if (nowy < 1)
while (++nowy < 1);
if (nowy > W)
while (--nowy > W);
}
else if (tmp == 'W' || tmp == 'w') {
--nowx;
if (nowx < 1)
while (++nowx < 1);
}
else if (tmp == 'A' || tmp == 'a') {
--nowy;
if (nowy < 1)
while (++nowy < 1);
}
else if (tmp == 'S' || tmp == 's') {
++nowx;
if (nowx > L)
while (--nowx > L);
}
else if (tmp == 'D' || tmp == 'd') {
++nowy;
if (nowy > W)
while (--nowy > W);
}
else if (tmp == '1')
click(nowx, nowy);
else if (tmp == '2')
flag(nowx, nowy);
else if (tmp == 3)
exit(0);
}
system("cls");
if (win())
cout << "恭喜, 你赢了!!!" << endl;
else
cout << "抱歉, 你输了..." << endl;
Sleep(1000);
nowx = -1;
nowy = -1;
for (int i = 1; i <= L; ++i) {
for (int j = 1; j <= W; ++j)
l[i][j].zhuangTai = 1;
}
outAll();
}
玩法
上下左右(WASD)移动当前格
按1点击,2标记
后续更新
参见泉州一中信息学题库的c2021ldw在1000题的提交记录