赞
踩
目录
wasd控制指针移动,空格键翻开,f键标记,p键自爆(直接输)
- #include <bits/stdc++.h>
- #include <windows.h>
- #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)
-
- using namespace std;
-
- string mines0[81]; // 平铺的雷(用于随机埋雷)
- string status[9][9]; // 雷区状态(用于判断)
- string outstatus[9][9]; // 显示状态(用于显示)
- string out = ""; // 会在fan()函数前面注释解释
- int s; // 此区域周围雷数(用于标数字)
- int x = 1; // 指针坐标x
- int y = 1; // 指针坐标y
- int win = 0; // 0为正在游戏,1为胜利,-1为失败,-2为自爆
- int mine = 0; // 剩余雷数
-
- map<string, int> col = { // 颜色名称对应的颜色代码
- {"dblue", 1},
- {"dgreen", 2},
- {"dteal", 3},
- {"dred", 4},
- {"dpink", 5},
- {"yellow", 6},
- {"dwhite", 7},
- {"grey", 8},
- {"lblue", 9},
- {"lgreen", 10},
- {"lteal", 11},
- {"lred", 12},
- {"lpink", 13},
- {"lyellow", 14},
- {"lwhite", 15}
- };
-
-
- map<string, string> codesty = { // 状态代码对应的显示图标
- {"no", "□"},
- {"1", " 1"},
- {"2", " 2"},
- {"3", " 3"},
- {"4", " 4"},
- {"5", " 5"},
- {"6", " 6"},
- {"7", " 7"},
- {"8", " 8"},
- {"mine", "¤"},
- {"flag", " F"},
- {"nfan", "■"},
- {"point", "♂"}
- };
-
- map<string, string> codecol = { // 状态代码对应的颜色名称
- {"no", "grey"},
- {"1", "lblue"},
- {"2", "dgreen"},
- {"3", "lred"},
- {"4", "dblue"},
- {"5", "dpink"},
- {"6", "lteal"},
- {"7", "dteal"},
- {"8", "lgreen"},
- {"mine", "dred"},
- {"flag", "lyellow"},
- {"nfan", "lwhite"},
- {"point", "dwhite"}
- };
-
- void clearbuf() { // 清屏
- system("cls");
- }
-
- void color(string a) { // 设置文本颜色
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), col[a]);
- }
-
- void say(int a) { // 输出 a=1正常 a=0直接把所有内部都输出
- color("lwhite");
- cout << " 1 2 3 4 5 6 7 8 9" << endl;
- for (int i = 1; i <= 9; i++) {
- color("lwhite");
- cout << i << " ";
- for (int j = 1; j <= 9; j++) {
- if (i == y && j == x) {
- color(codecol["point"]);
- cout << codesty["point"];
- } else {
- if (a == 0) {
- color(codecol[status[i - 1][j - 1]]);
- cout << codesty[status[i - 1][j - 1]];
- } else {
- color(codecol[outstatus[i - 1][j - 1]]);
- cout << codesty[outstatus[i - 1][j - 1]];
- }
- }
- }
- cout << endl;
- }
- color("lwhite");
- cout << "剩余雷数: ";
- color("lred");
- cout << mine << endl;
- cout << endl;
- }
-
- bool w() { // 判断输赢
- for (int i = 0; i < 9; i++) {
- for (int j = 0; j < 9; j++) {
- if (outstatus[i][j] == "nfan" && status[i][j] != "mine") {
- return false;
- } else if (outstatus[i][j] == "flag" && status[i][j] != "mine") {
- return false;
- }
- }
- }
- return true;
- }
-
- /*
- 最重要的部分,连续翻开一大片 的函数(前提是点到了周围八个空均没有雷的方块)
- 思路如下:
- 首先假设是这个图案且点到了中心[2, 2](m是雷)
- 0 0 0 1 m
- 1 1 0 1 1
- m 1 0 0 0
- 1 1 1 1 1
- 0 0 1 m 1
- 看一下如果out里面有(a,b) 就 return
- 先把那一块3*3的区域划下来:
- 1 0 1
- 1 0 0
- 1 1 1
- 从左到右,从上到下判断是否为0,
- 如果是,重新以这个坐标为中心,把3*3的区域划下来(递归):
- 0 0 1
- 1 0 1
- 1 0 0
- 之后把判断的每一个位置都要outstatus[x][y] = status[x][y];然后把(x,y)添加到out,防止重复
- 角边要特殊处理!!!
- */
- void fan(int a, int b) {
- outstatus[a][b] = status[a][b];
- if (out.find("(" + to_string(a) + "," + to_string(b) + ")") != string::npos) {
- return;
- }
- out += ("(" + to_string(a) + "," + to_string(b) + ")");
- if (status[a][b] != "no") return;
- if (a == 0 && b == 0) { // 左上角
- fan(a, b + 1); // 递归
- fan(a + 1, b);
- fan(a + 1, b + 1);
- } else if (a == 0 && b == 8) { // 右上角
- fan(a, b - 1);
- fan(a + 1, b - 1);
- fan(a + 1, b);
- } else if (a == 8 && b == 0) { // 左下角
- fan(a - 1, b);
- fan(a - 1, b + 1);
- fan(a, b + 1);
- } else if (a == 8 && b == 8) { // 右下角
- fan(a - 1, b - 1);
- fan(a - 1, b);
- fan(a, b - 1);
- } else if (a == 0 || b == 0 || a == 8 || b == 8) { // 边上
- if (a == 0) { // 上边;
- fan(a, b - 1);
- fan(a, b + 1);
- fan(a + 1, b - 1);
- fan(a + 1, b);
- fan(a + 1, b + 1);
- } else if (b == 8) { // 右边
- fan(a - 1, b - 1);
- fan(a - 1, b);
- fan(a, b - 1);
- fan(a + 1, b - 1);
- fan(a + 1, b);
- } else if (a == 8) { // 下边
- fan(a - 1, b - 1);
- fan(a - 1, b);
- fan(a - 1, b + 1);
- fan(a, b - 1);
- fan(a, b + 1);
- } else if (b == 0) { // 左边
- fan(a - 1, b);
- fan(a - 1, b + 1);
- fan(a, b + 1);
- fan(a + 1, b);
- fan(a + 1, b + 1);
- }
- } else { // 中间
- fan(a - 1, b - 1);
- fan(a - 1, b);
- fan(a - 1, b + 1);
- fan(a, b - 1);
- fan(a, b + 1);
- fan(a + 1, b - 1);
- fan(a + 1, b);
- fan(a + 1, b + 1);
- }
- }
-
- int main() {
- // 随机埋雷
- for (int i = 0; i < 81; i++) {
- mines0[i] = "no";
- }
- for (int i = 0; i <= 10; i++) {
- mines0[i] = "mine";
- }
- srand(time(NULL));
- random_shuffle(mines0, mines0 + 81);
- for (int i = 1; i <= 9; i++) {
- for (int j = 1; j <= 9; j++) {
- status[i - 1][j - 1] = mines0[i* j - 1];
- outstatus[i - 1][j - 1] = "nfan";
- if (status[i-1][j-1] == "mine") mine++;
- }
- }
-
- // 标数字
- if (status[0][0] == "no") { // 左上角
- s = 0;
- if (status[0][1] == "mine") s++;
- if (status[1][0] == "mine") s++;
- if (status[1][1] == "mine") s++;
- if (s != 0) status[0][0] = to_string(s);
- }
- if (status[0][8] == "no") { // 右上角
- s = 0;
- if (status[0][7] == "mine") s++;
- if (status[1][7] == "mine") s++;
- if (status[1][8] == "mine") s++;
- if (s != 0) status[0][8] = to_string(s);
- }
- if (status[8][0] == "no") { // 左下角
- s = 0;
- if (status[7][0] == "mine") s++;
- if (status[7][1] == "mine") s++;
- if (status[8][1] == "mine") s++;
- if (s != 0) status[8][0] = to_string(s);
- }
- if (status[8][8] == "no") { // 右下角
- s = 0;
- if (status[7][7] == "mine") s++;
- if (status[7][8] == "mine") s++;
- if (status[8][7] == "mine") s++;
- if (s != 0) status[8][8] = to_string(s);
- }
- for (int i = 1; i <= 7; i++) { // 上边
- if (status[0][i] != "no") continue;
- s = 0;
- if (status[0][i - 1] == "mine") s++;
- if (status[0][i + 1] == "mine") s++;
- if (status[1][i - 1] == "mine") s++;
- if (status[1][i] == "mine") s++;
- if (status[1][i + 1] == "mine") s++;
- if (s != 0) status[0][i] = to_string(s);
- }
- for (int i = 1; i <= 7; i++) { // 右边
- if (status[i][8] != "no") continue;
- s = 0;
- if (status[i - 1][7] == "mine") s++;
- if (status[i - 1][8] == "mine") s++;
- if (status[i][7] == "mine") s++;
- if (status[i + 1][7] == "mine") s++;
- if (status[i + 1][8] == "mine") s++;
- if (s != 0) status[i][8] = to_string(s);
- }
- for (int i = 1; i <= 7; i++) { // 下边
- if (status[8][i] != "no") continue;
- s = 0;
- if (status[i - 1][8] == "mine") s++;
- if (status[i + 1][8] == "mine") s++;
- if (status[i - 1][7] == "mine") s++;
- if (status[i][7] == "mine") s++;
- if (status[i + 1][7] == "mine") s++;
- if (s != 0) status[8][i] = to_string(s);
- }
- for (int i = 1; i <= 7; i++) { // 左边
- if (status[i][0] != "no") continue;
- s = 0;
- if (status[i - 1][0] == "mine") s++;
- if (status[i - 1][1] == "mine") s++;
- if (status[i][1] == "mine") s++;
- if (status[i + 1][0] == "mine") s++;
- if (status[i + 1][1] == "mine") s++;
- if (s != 0) status[i][0] = to_string(s);
- }
- for (int i = 0; i < 8; i++) { // 中间
- for (int j = 0; j < 8; j++) {
- if (status[i][j] != "no") {
- continue;
- }
- s = 0;
- if (status[i - 1][j - 1] == "mine") s++;
- if (status[i - 1][j] == "mine") s++;
- if (status[i - 1][j + 1] == "mine") s++;
- if (status[i][j - 1] == "mine") s++;
- if (status[i][j + 1] == "mine") s++;
- if (status[i + 1][j - 1] == "mine") s++;
- if (status[i + 1][j] == "mine") s++;
- if (status[i + 1][j + 1] == "mine") s++;
- if (s != 0) status[i][j] = to_string(s);
- }
- }
-
- //开始运行(一直判断键盘是否按下并执行操作)
- while (win == 0) {
- say(1);
- if (KEY_DOWN('W') && y > 1) {
- y -= 1;
- } else if (KEY_DOWN('A') && x > 1) {
- x -= 1;
- } else if (KEY_DOWN('S') && y < 9) {
- y += 1;
- } else if (KEY_DOWN('D') && x < 9) {
- x += 1;
- } else if (KEY_DOWN('F')) { //插旗旗
- if (outstatus[y - 1][x - 1] == "nfan") {
- outstatus[y - 1][x - 1] = "flag";
- mine--;
- }
- } else if (KEY_DOWN(' ')) { // 翻方块
- if (status[y - 1][x - 1] == "mine") {
- win = -1;
- } else if (outstatus[y - 1][x - 1] == "flag") {
- mine++;
- fan(y - 1, x - 1);
- } else {
- fan(y - 1, x - 1);
- }
- } else if (KEY_DOWN('P')) { // 自爆
- win = -2;
- }
-
- // 判断输赢 - 没有空地(如果有检查空地是否mine)且所有flag都在mine上
- if (w()) {
- win = 1;
- }
-
- clearbuf(); // 清屏
- }
- say(0); // 输出内部
- cout << endl;
- if (win == -1 || win == -2) { // 判断输赢(输出)
- color("lred");
- if (win == -1) {
- cout << "你无了" << endl;
- } else {
- cout << "你自爆了" << endl;
- }
- color("dwhite");
- } else {
- color("lgreen");
- cout << "你排掉了所有的雷" << endl;
- color("dwhite");
- }
- system("pause");
- return 0;
- }
1-5行 预处理器和namespace std; 第三行定义判断键盘是否按下的函数(可以直接背)
7-15行 定义需要的变量
17-66行 定义map
68-70行 定义清屏函数
72-74行 定义颜色函数
76-103行 定义输出函数
105-116行 定义判断输赢函数
140-199行 定义翻开区域的函数(重点)
主程序:
203-217行 随机埋雷(Error:不知道为什么埋的雷数也是随机的)
220-304行 标区域周围雷的个数-标数字
while(正在游戏){
308行 输出当前状态
309-316行 用wasd控制指针移动
317-321行 f键插旗
322-330行 空格翻方块
331-333行 p键自爆
336-338行 判断输赢
340行 清屏(不断刷新)
}
342-343行 输出内部情况
344-356行 输赢的输出(也可以算做一个结束界面)
357-360行 请按任意键继续...
思路如下:
首先假设是这个图案且点到了中心[3, 3](m是雷)
0 0 0 1 m
1 1 0 1 1
m 1 0 0 0
1 1 1 1 1
0 0 1 m 1
检测out里是否有点到区域的坐标,如果是,直接return;
显示翻开的区域,把翻开区域坐标添加到字符串out用来防重复
框下周围八个方块(角边特殊处理):
1 0 1
1 0 0
1 1 1
依次重新翻开,如果翻开的区域是0:框下周围八个方块...(就是递归)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。