C++控制臺(tái)實(shí)現(xiàn)掃雷游戲
本文實(shí)例為大家分享了C++控制臺(tái)實(shí)現(xiàn)掃雷游戲的具體代碼,供大家參考,具體內(nèi)容如下
花了一下午寫(xiě)出來(lái)的控制臺(tái)掃雷,主要通過(guò)修改和打印數(shù)組來(lái)實(shí)現(xiàn)。
主要的問(wèn)題點(diǎn):
1.在顯示地圖的過(guò)程中,既要顯示數(shù)字,又要顯示雷和符號(hào),所以的用string類型的二維向量,vector<vector<string.>>;中間要利用ASCII碼將int型的數(shù)字轉(zhuǎn)化為字符串。
2.生成地圖的時(shí)候,雷是隨機(jī)的,我這里采用的做法是取余生成雷,舉個(gè)例子,如果雷數(shù)是格子數(shù)的十分之一,那我遍歷整個(gè)二維數(shù)組,在rand()%8 == 0時(shí)放置一顆雷,當(dāng)放置10顆之后停止,這樣可能會(huì)導(dǎo)致我的雷都偏前面一點(diǎn),哈哈。
3.對(duì)于沒(méi)有雷的格子,需要做一個(gè)遍歷,統(tǒng)計(jì)周邊的雷數(shù),為了方便,實(shí)際地圖要大一圈,實(shí)際的邊長(zhǎng)+2,邊不作為地圖,只為統(tǒng)計(jì)雷數(shù)時(shí)方便存在。
4.當(dāng)點(diǎn)開(kāi)一顆雷之后,如果數(shù)字是0,那么四周為0的數(shù)字也要被點(diǎn)亮,因此在這里使用遞歸實(shí)現(xiàn)dfs。
5.在每次進(jìn)行一個(gè)格子操作之后,使用一個(gè)count計(jì)數(shù),所有格子操作完后,游戲結(jié)束統(tǒng)計(jì)游戲結(jié)果,在此之前,踩到雷也會(huì)導(dǎo)致游戲結(jié)束。
附上游戲截圖和代碼
主函數(shù)
#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();//玩家的難度選擇參數(shù) ?? ??? ? ?? ??? ?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,沒(méi)踩到返回0 ?? ??? ??? ??? ?if (game->stepOnMine(m)) break; ?? ??? ??? ?} ?? ??? ??? ?else if (swicth == 2) { ?? ??? ??? ??? ?//插旗子 ?? ??? ??? ??? ?game->flagMine(m); ?? ??? ??? ?} ?? ??? ??? ?else if (swicth == 3) { ?? ??? ??? ??? ?//取消插旗子 ?? ??? ??? ??? ?game->cancelFalgMine(m); ?? ??? ??? ?} ?? ??? ??? ?else { ?? ??? ??? ??? ?cout << "您的輸入有誤!" << endl; ?? ??? ??? ?} ?? ??? ??? ?//判斷格子是否被開(kāi)完,開(kāi)完了則取勝 ?? ??? ??? ?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);//根據(jù)難度構(gòu)造地圖 ?? ?void initMap();//根據(jù)難度初始化地圖 ?? ?string aroudMineNum ?? ?(const vector<vector<string>>&, const int&, const int&) const;//判斷某個(gè)坐標(biāo)桌邊的雷數(shù) ?? ?void showMap();//打印showMapArray數(shù)組?? ? ?? ?int dateUpMap(const int&, const int&);//如果返回值為1,繼續(xù),返回值為0表示結(jié)束,如果返回值為-1表示非法輸入 ?? ?int flag(const int&, const int&);//插旗子修改顯示數(shù)組 ?? ?int cancelFlag(const int&, const int&);//取消旗子時(shí)修改顯示數(shù)組 ?? ?bool gameOver(); private: ?? ?int mapCount;//格子用完的計(jì)數(shù) ?? ?int difficult;//難度 ?? ?vector<vector<string>> map;//隱藏的雷表 ?? ?vector<vector<string>> showMapArray;//公開(kāi)的顯示數(shù)組 };
源文件
#include"map.h" Map::Map(int difficult) : ?? ?difficult(difficult), ?? ?mapCount(difficult* difficult) { } //初始化地圖數(shù)組 void Map::initMap() { ?? ?//根據(jù)難度設(shè)置二維數(shù)組的大小以及雷的數(shù)量 ?? ?int mineNumber = difficult * difficult * 10;//雷的數(shù)量 ?? ?int size = 10 * difficult;//此處尺寸加2,四邊都為零,這樣方便統(tǒng)計(jì)沒(méi)有雷的格子上的數(shù)據(jù) ?? ?srand(time(0)); ?? ?//使用隨機(jī)數(shù)設(shè)置雷的數(shù)量 ?? ?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); ?? ?} ?? ?//此外還需要根據(jù)雷的位置和數(shù)量在其他位置上提示! ?? ?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); ?? ??? ??? ?} ?? ??? ?} ?? ?} ?? ?//初始化顯示顯示數(shù)組,注意!此數(shù)組要顯示行列數(shù),所以比上述數(shù)組多一行一列 ?? ?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); ?? ?} } //判斷自身格子上的數(shù)字為多少 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; } //按照地圖數(shù)組顯示畫(huà)面 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; ?? ?//判斷坐標(biāo)是否已經(jīng)被翻開(kāi),若被翻開(kāi),則輸入非法,返回-1 ?? ?if (showMapArray[x][y] != " #") return -1; ?? ?//如果該點(diǎn)有雷,則把該點(diǎn)的雷翻出來(lái),顯示游戲失敗 ?? ?if (map[x][y] == "*") { ?? ??? ?showMapArray[x][y] = " *"; ?? ??? ?return 0; ?? ?} ?? ?//如果該點(diǎn)的數(shù)字大于0,則只把單一數(shù)字翻出來(lái) ?? ?else if (map[x][y] != "00") { ?? ??? ?string temp; ?? ??? ?temp.append(map[x][y]); ?? ??? ?showMapArray[x][y] = temp; ?? ??? ?--mapCount;//格子數(shù)減少統(tǒng)計(jì),當(dāng)格子數(shù)為0時(shí)判斷游戲勝利! ?? ?} ?? ?//如果該點(diǎn)的數(shù)字為0,則把附近為0的點(diǎn)全部翻出來(lái),直到翻出數(shù)字為止 ?? ?else { ?? ??? ?if (showMapArray[x][y] != " Q") { ?? ??? ??? ?--mapCount;//格子數(shù)減少統(tǒng)計(jì),當(dāng)格子數(shù)為0時(shí)判斷游戲勝利! ?? ??? ??? ?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;//格子數(shù)減少統(tǒng)計(jì),當(dāng)格子數(shù)為0時(shí)判斷游戲勝利! ?? ??? ?showMapArray[x][y] = " Q"; ?? ?} ?? ?return 0; } int Map::cancelFlag(const int& x, const int& y) { ?? ?if (showMapArray[x][y] != " Q") return -1; ?? ?else { ?? ??? ?++mapCount;//格子數(shù)增加統(tǒng)計(jì),當(dāng)格子數(shù)為0時(shí)判斷游戲勝利! ?? ??? ?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.簡(jiǎn)單模式**************" << endl; ?? ?cout << "************2.中等模式**************" << endl; ?? ?cout << "************3.困難模式**************" << endl; ?? ?cout << "**********請(qǐng)輸入你的選擇************" << 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 << "請(qǐng)輸入你想排雷的坐標(biāo):" << endl; ?? ?cout << "x:" << endl; ?? ?cin >> x; ?? ?cout << "y:" << endl; ?? ?cin >> y; ?? ?int result = m->dateUpMap(x, y); ?? ?system("cls"); ?? ?if (result == -1) { ?? ??? ?cout << "您的輸入有誤,請(qǐng)重新輸入!" << endl; ?? ?} ?? ?else if (result == 0) { ?? ??? ?cout << "你踩到雷啦!" << endl; ?? ??? ?Sleep(300); ?? ??? ?cout << "游戲即將結(jié)束!" << 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 << "請(qǐng)輸入你想插旗子的坐標(biāo):" << 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 << "請(qǐng)輸入你想取消旗子的坐標(biāo):" << endl; ?? ?cout << "x:" << endl; ?? ?cin >> x; ?? ?cout << "y:" << endl; ?? ?cin >> y; ?? ?int result = m->cancelFlag(x, y); ?? ?system("cls"); ?? ?if (result == -1) { ?? ??? ?cout << "此處沒(méi)有旗子可以取消!" << endl; ?? ?} ?? ?else { ?? ??? ?cout << "取消旗子成功!" << endl; ?? ?} ?? ??? ? ?? ?return 0; }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++實(shí)現(xiàn)讀取圖片長(zhǎng)度和寬度
這篇文章主要介紹了C++實(shí)現(xiàn)讀取圖片長(zhǎng)度和寬度,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-04-04C語(yǔ)言中g(shù)etchar函數(shù)詳解看這一篇就夠了(函數(shù)功能、使用、返回值)
getchar讀取字符的函數(shù),今天通過(guò)本文給大家介紹C語(yǔ)言中g(shù)etchar函數(shù)簡(jiǎn)介用法示例詳解,感興趣的朋友跟隨小編一起看看吧2023-02-02C++編寫(xiě)實(shí)現(xiàn)飛機(jī)大戰(zhàn)
這篇文章主要為大家詳細(xì)介紹了C++編寫(xiě)實(shí)現(xiàn)飛機(jī)大戰(zhàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06C++實(shí)現(xiàn) 單例模式實(shí)例詳解
這篇文章主要介紹了C++實(shí)現(xiàn) 單例模式實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05C語(yǔ)言中的fscanf()函數(shù)與vfscanf()函數(shù)使用
這篇文章主要介紹了C語(yǔ)言中的fscanf()函數(shù)與vfscanf()函數(shù)使用,是C語(yǔ)言入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-08-08基于OpenGL實(shí)現(xiàn)多段Bezier曲線拼接
這篇文章主要為大家詳細(xì)介紹了基于OpenGL實(shí)現(xiàn)多段Bezier曲線拼接,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04