C++控制台实现扫雷游戏

Kitty ·
更新时间:2024-11-13
· 1071 次阅读

本文实例为大家分享了C++控制台实现扫雷游戏的具体代码,供大家参考,具体内容如下

花了一下午写出来的控制台扫雷,主要通过修改和打印数组来实现。

主要的问题点:

1.在显示地图的过程中,既要显示数字,又要显示雷和符号,所以的用string类型的二维向量,vector<vector<string.>>;中间要利用ASCII码将int型的数字转化为字符串。
2.生成地图的时候,雷是随机的,我这里采用的做法是取余生成雷,举个例子,如果雷数是格子数的十分之一,那我遍历整个二维数组,在rand()%8 == 0时放置一颗雷,当放置10颗之后停止,这样可能会导致我的雷都偏前面一点,哈哈。
3.对于没有雷的格子,需要做一个遍历,统计周边的雷数,为了方便,实际地图要大一圈,实际的边长+2,边不作为地图,只为统计雷数时方便存在。
4.当点开一颗雷之后,如果数字是0,那么四周为0的数字也要被点亮,因此在这里使用递归实现dfs。
5.在每次进行一个格子操作之后,使用一个count计数,所有格子操作完后,游戏结束统计游戏结果,在此之前,踩到雷也会导致游戏结束。

附上游戏截图和代码

主函数

#include<vector> #include<algorithm> #include<functional> #include<iostream> #include<windows.h> #include"gameManager.h" #include"map.h" using namespace std; int main() {     GameManager* game = new GameManager();     while (true) {         int diff = game->difficultNumber();//玩家的难度选择参数         Map* m = new Map(diff);         m->initMap();         while (true) {             m->showMap();             int swicth;             cout << "1.踩雷" << endl;             cout << "2.插旗子" << endl;             cout << "3.取消插旗子" << endl;             cin >> swicth;             if (swicth == 1) {                 //踩雷;如果踩到雷了返回1,没踩到返回0                 if (game->stepOnMine(m)) break;             }             else if (swicth == 2) {                 //插旗子                 game->flagMine(m);             }             else if (swicth == 3) {                 //取消插旗子                 game->cancelFalgMine(m);             }             else {                 cout << "您的输入有误!" << endl;             }             //判断格子是否被开完,开完了则取胜             if (m->gameOver()) {                 cout << "恭喜你获得胜利!" << endl;                 m->showMap();                 break;             }         }         int over = 0;         cout << "1.回到主菜单" << endl;         cout << "other.退出游戏" << endl;         cin >> over;         if (over == 1) {             system("cls");             continue;         }         else break;     }     system("pause");     return 0; }

map类

头文件

```cpp #pragma once #include<ctime> #include <vector> #include<string> #include <iostream> using namespace std; class Map { public:     Map(int);//根据难度构造地图     void initMap();//根据难度初始化地图     string aroudMineNum     (const vector<vector<string>>&, const int&, const int&) const;//判断某个坐标桌边的雷数     void showMap();//打印showMapArray数组         int dateUpMap(const int&, const int&);//如果返回值为1,继续,返回值为0表示结束,如果返回值为-1表示非法输入     int flag(const int&, const int&);//插旗子修改显示数组     int cancelFlag(const int&, const int&);//取消旗子时修改显示数组     bool gameOver(); private:     int mapCount;//格子用完的计数     int difficult;//难度     vector<vector<string>> map;//隐藏的雷表     vector<vector<string>> showMapArray;//公开的显示数组 };

源文件

#include"map.h" Map::Map(int difficult) :     difficult(difficult),     mapCount(difficult* difficult) { } //初始化地图数组 void Map::initMap() {     //根据难度设置二维数组的大小以及雷的数量     int mineNumber = difficult * difficult * 10;//雷的数量     int size = 10 * difficult;//此处尺寸加2,四边都为零,这样方便统计没有雷的格子上的数据     srand(time(0));     //使用随机数设置雷的数量     for (int i = 0; i < size + 2; ++i) {         vector<string> temp;         for (int j = 0; j < size + 2; ++j) {             if (rand() % 8 == 0 && mineNumber != 0 && i != 0 && j != 0 && i != size - 1 && j != size - 1) {                 temp.push_back("*");                 --mineNumber;             }             else {                 temp.push_back("0");             }         }         map.push_back(temp);     }     //此外还需要根据雷的位置和数量在其他位置上提示!     for (int i = 1; i < size - 1; ++i) {         for (int j = 1; j < size - 1; ++j) {             if (map[i][j] != "*") {                 map[i][j] = aroudMineNum(map, i, j);             }         }     }     //初始化显示显示数组,注意!此数组要显示行列数,所以比上述数组多一行一列     for (int i = 0; i < size + 1; ++i) {         vector<string> temp;         for (int j = 0; j < size + 1; ++j) {             if (i == 0) {                 string t;                 if (j < 10) {                     t.push_back(48);                     t.push_back(j + 48);                 }                 else if (j < 20) {                     t.push_back(49);                     t.push_back(j + 38);                 }                 else if (j < 30) {                     t.push_back(50);                     t.push_back(j + 28);                 }                 else {                     t.push_back('3');                     t.push_back('0');                 }                 temp.push_back(t);             }             else if (j == 0) {                 string t;                 if (i < 10) {                     t.push_back(48);                     t.push_back(i + 48);                 }                 else if (i < 20) {                     t.push_back(49);                     t.push_back(i + 38);                 }                 else if (i < 30) {                     t.push_back(50);                     t.push_back(i + 28);                 }                 else {                     t.push_back('3');                     t.push_back('0');                 }                 temp.push_back(t);             }             else temp.push_back(" #");         }         showMapArray.push_back(temp);     } } //判断自身格子上的数字为多少 string Map::aroudMineNum(const vector<vector<string>>& map, const int& i, const int& j) const {     int count = 0;     string ans;     for (int x = i - 1; x <= i + 1; ++x) {         for (int y = j - 1; y <= j + 1; ++y) {             if (map[x][y] == "*") {                 ++count;             }         }     }     ans.push_back(48);     ans.push_back(count + 48);     return ans; } //按照地图数组显示画面 void Map::showMap() {     int sideLength = showMapArray.size();     for (int i = 0; i < sideLength; ++i) {         for (int j = 0; j < sideLength; ++j) {             cout << showMapArray[i][j] << " ";         }         cout << endl;     } } int Map::dateUpMap(const int& x, const int& y) {     //判断xy的值只能在0-30之间difficult*10     if (x < 1 || x >= (difficult * 10) || y < 0 || y >= (difficult * 10)) return -1;     //判断坐标是否已经被翻开,若被翻开,则输入非法,返回-1     if (showMapArray[x][y] != " #") return -1;     //如果该点有雷,则把该点的雷翻出来,显示游戏失败     if (map[x][y] == "*") {         showMapArray[x][y] = " *";         return 0;     }     //如果该点的数字大于0,则只把单一数字翻出来     else if (map[x][y] != "00") {         string temp;         temp.append(map[x][y]);         showMapArray[x][y] = temp;         --mapCount;//格子数减少统计,当格子数为0时判断游戏胜利!     }     //如果该点的数字为0,则把附近为0的点全部翻出来,直到翻出数字为止     else {         if (showMapArray[x][y] != " Q") {             --mapCount;//格子数减少统计,当格子数为0时判断游戏胜利!             showMapArray[x][y] = "00";         }         if (showMapArray[x][y] == " Q" && map[x][y] == "*") {             showMapArray[x][y] = " *";             return -1;         }         for (int i = x - 1; i <= x + 1; ++i) {             for (int j = y - 1; j <= y + 1; ++j) {                 if (!(i == x && j == y) && i > 0 && i < (difficult * 10) && j > 0 && j < (difficult * 10)) {                     dateUpMap(i, j);                 }             }         }         return 1;     } } int Map::flag(const int& x, const int& y) {     if (showMapArray[x][y] != " #") return -1;     else {         --mapCount;//格子数减少统计,当格子数为0时判断游戏胜利!         showMapArray[x][y] = " Q";     }     return 0; } int Map::cancelFlag(const int& x, const int& y) {     if (showMapArray[x][y] != " Q") return -1;     else {         ++mapCount;//格子数增加统计,当格子数为0时判断游戏胜利!         showMapArray[x][y] = " #";     }     return 0; } bool Map::gameOver() {     if (mapCount == 0) return true;     return false; }

gameManager类

头文件

#pragma once #include<iostream> #include<windows.h> #include"map.h" using namespace std; class GameManager { public:     void showMenu();//显示主菜单     int difficultNumber();//选择难度     int stepOnMine(Map * m);//踩雷     int flagMine(Map* m);//插旗子     int cancelFalgMine(Map * m);//取消旗子 };

源文件

#include"gameManager.h" #include"map.h" void GameManager::showMenu() {     cout << "***************主菜单***************" << endl;     cout << "************1.简单模式**************" << endl;     cout << "************2.中等模式**************" << endl;     cout << "************3.困难模式**************" << endl;     cout << "**********请输入你的选择************" << endl; } int GameManager::difficultNumber() {     int diff = 0;     while (diff != 1 && diff != 2 && diff != 3) {         this->showMenu();         cin >> diff;     }     return diff; } int GameManager::stepOnMine(Map* m) {     int x, y;     cout << "请输入你想排雷的坐标:" << endl;     cout << "x:" << endl;     cin >> x;     cout << "y:" << endl;     cin >> y;     int result = m->dateUpMap(x, y);     system("cls");     if (result == -1) {         cout << "您的输入有误,请重新输入!" << endl;     }     else if (result == 0) {         cout << "你踩到雷啦!" << endl;         Sleep(300);         cout << "游戏即将结束!" << endl;         Sleep(300);         cout << "5!" << endl;         Sleep(300);         cout << "4!" << endl;         Sleep(300);         cout << "3!" << endl;         Sleep(300);         cout << "2!" << endl;         Sleep(300);         cout << "1!" << endl;         m->showMap();         system("pause");         return 1;     }     return 0; } int GameManager::flagMine(Map* m) {     //插旗子     int x, y;     cout << "请输入你想插旗子的坐标:" << endl;     cout << "x:" << endl;     cin >> x;     cout << "y:" << endl;     cin >> y;     int result = m->flag(x, y);     system("cls");     if (result == -1) {         cout << "此处不能插旗子!" << endl;     }     else         cout << "插旗子成功!" << endl;     return 0; } int GameManager::cancelFalgMine(Map* m) {     int x, y;     cout << "请输入你想取消旗子的坐标:" << endl;     cout << "x:" << endl;     cin >> x;     cout << "y:" << endl;     cin >> y;     int result = m->cancelFlag(x, y);     system("cls");     if (result == -1) {         cout << "此处没有旗子可以取消!" << endl;     }     else {         cout << "取消旗子成功!" << endl;     }     return 0; }



c+ C++ 控制台

需要 登录 后方可回复, 如果你还没有账号请 注册新账号