C++實現(xiàn)掃雷、排雷小游戲
本文實例為大家分享了C++實現(xiàn)掃雷、排雷小游戲的具體代碼,供大家參考,具體內(nèi)容如下
界面:
游戲思想:
掃雷游戲:
1.隨機給定雷點坐標
2.判斷每個點的雷情況
3.由用戶根據(jù)上下左右鍵到達指定位置,點擊enter,翻開該點
如果該點是雷點,此時翻開所有雷點,告知游戲結(jié)束
非雷點,翻開該點坐標
代碼:
#include<iostream> #include<vector> #include<sstream> #include<algorithm> #include<graphics.h> #include<ctime> #include<conio.h> using namespace std; #define WIDTH 500 #define HEIGHT 500 #define SIDE 50 #define THUNDERNUM 10 #define TOTALSCORE 100 #define EVERY_OF_DESC 5 int score = TOTALSCORE; class Point { public: int x; int y; Point() {} Point(int _x, int _y) :x(_x), y(_y) {} void setPoint(int x, int y) { this->x = x; this->y = y; } Point(const Point& xy) :x(xy.x), y(xy.y) {} bool operator<(const Point& xy)const { if (x <= xy.x) return true; return y <= xy.y; } Point& operator=(const Point& xy) { if (this != &xy) { x = xy.x; y = xy.y; } return *this; } bool operator==(const Point& xy) { return ((x == xy.x) && (y = xy.y)); } bool operator!=(const Point& xy) { return !(*this == xy); } }; class ThunderPoint { private: vector<Point> storage; int num; public: ThunderPoint(int _num = THUNDERNUM) :num(_num) { //初始化雷點位置 int count = 0; while (count != num) { int x = (rand() % (WIDTH / SIDE)) * SIDE;//隨機生成數(shù)據(jù),使之在圖形界面之中 int y = (rand() % (HEIGHT / SIDE)) * SIDE; Point tem(x, y); int i = -1; bool flag = false; for (i = 0; i < storage.size(); i++) { if (tem == storage[i]) { flag = true; break; } } if (flag==false) { //說明沒有重復(fù) storage.push_back(tem); count++; } } } vector<Point>& getThunderPoint() { //獲得雷點位置 return storage; } void drawThunderPoint() { auto it = storage.begin(); while (it != storage.end()) { setfillcolor(RED); fillcircle((*it).x, (*it).y, SIDE / 2); ++it; } } }; class Grid { private: vector<vector<int>> nearbythunder; vector<vector<bool>> isopen; ThunderPoint thunder; Point currposition; Point preposition; vector<COLORREF> color; public: bool isOver; public: Grid() :thunder(10),currposition() { preposition.setPoint(0, 0); for (int i = 0; i < 10; ++i) { color.push_back(RGB(rand() % 256, rand() % 256, rand() % 256)); } isOver = false; isopen.resize(HEIGHT / SIDE, vector<bool>(WIDTH / SIDE, false)); nearbythunder.resize(HEIGHT/SIDE,vector<int>(WIDTH/SIDE,0)); currposition.setPoint(0, 0); //先將雷點的位置標出來,標為數(shù)字 9 // 任何一個點,他附近的雷點最多8個 auto it = thunder.getThunderPoint().begin(); while (it != thunder.getThunderPoint().end()) { int x = ((*it).x)/SIDE; int y = ((*it).y)/SIDE; nearbythunder[x][y] = 9; if (((y - SIDE/SIDE) >= 0) && (nearbythunder[x][y - SIDE/SIDE] != 9)) { nearbythunder[x][y - SIDE/SIDE]++; } if (((y - SIDE/SIDE) >= 0) && ((x - SIDE/SIDE) >= 0) && (nearbythunder[x - SIDE/SIDE][y - SIDE/SIDE] != 9)) { nearbythunder[x - SIDE/SIDE][y - SIDE/SIDE]++; } if (((y - SIDE/SIDE) >= 0) && ((x + SIDE/SIDE) < WIDTH/SIDE) && (nearbythunder[x + SIDE/SIDE][y - SIDE/SIDE] != 9)) { nearbythunder[x + SIDE/SIDE][y - SIDE/SIDE]++; } if (((x - SIDE/SIDE) >= 0) && (nearbythunder[x - SIDE/SIDE][y] != 9)) { nearbythunder[x - SIDE/SIDE][y]++; } if (((x + SIDE/SIDE) < WIDTH/SIDE) && (nearbythunder[x + SIDE/SIDE][y] != 9)) { nearbythunder[x + SIDE/SIDE][y]++; } if (((y + SIDE/SIDE) < HEIGHT/SIDE) && (nearbythunder[x][y + SIDE/SIDE] != 9)) { nearbythunder[x][y + SIDE/SIDE]++; } if (((y + SIDE/SIDE) < HEIGHT/SIDE) && ((x - SIDE/SIDE) >= 0) && (nearbythunder[x - SIDE/SIDE][y + SIDE/SIDE] != 9)) { nearbythunder[x - SIDE/SIDE][y + SIDE/SIDE]++; } if (((y + SIDE / SIDE) < HEIGHT / SIDE) && ((x + SIDE / SIDE) < WIDTH / SIDE) && (nearbythunder[x + SIDE / SIDE][y + SIDE / SIDE] != 9)) { nearbythunder[x + SIDE / SIDE][y + SIDE / SIDE]++; } ++it; } for (int i = 0; i < HEIGHT; i = i + SIDE) { setlinecolor(YELLOW); line(0, i, WIDTH, i); line(i, 0, i, HEIGHT); } } void keyDown() { char userKey = _getch(); if (userKey == -32) // 表明這是方向鍵 userKey = -_getch(); // 獲取具體方向,并避免與其他字母的 ASCII 沖突 setfillcolor(GREEN); preposition = currposition; switch (userKey) { case 'w': case 'W': case -72: //上 { if (currposition.y - SIDE >= 0) { currposition.y -= SIDE; } } break; case 's': case 'S': case -80://下 { if (currposition.y + SIDE < HEIGHT) currposition.y += SIDE; } break; case 'a': case 'A': case -75://左 { if (currposition.x - SIDE >= 0) currposition.x -= SIDE; } break; case 'd': case 'D': case -77://右 { if (currposition.x + SIDE < WIDTH) { currposition.x += SIDE; } } break; case '\r': { score -= EVERY_OF_DESC; settextstyle(10, 10, "楷體"); settextcolor(GREEN); RECT rect; rect.left = WIDTH-100; rect.top = 100; rect.right = WIDTH; rect.bottom = 200; string ll = to_string(score); const char* str = ll.c_str(); //drawtext(str, &rect, 1); //現(xiàn)在開始翻 openOne(currposition); } break; } setlinecolor(BLACK); setlinestyle(1, 0); line(preposition.x, preposition.y, preposition.x + SIDE, preposition.y); setfillcolor(GREEN); setlinecolor(WHITE); setlinestyle(1, 2); line(currposition.x, currposition.y, currposition.x + SIDE, currposition.y ); } private: bool pred(bool x) { return x == true; } void openOne(const Point& cur) { //說明此時翻一個 isopen[cur.x / SIDE][cur.y / SIDE] = true; //此時應(yīng)該著色 settextcolor(color[nearbythunder[cur.x/SIDE][cur.y/SIDE]]); RECT rect; settextstyle(SIDE, SIDE, "楷體"); rect.left = cur.x; rect.top = cur.y; rect.right = cur.x + SIDE; rect.bottom = cur.y + SIDE; drawtext((to_string(nearbythunder[cur.x / SIDE][cur.y / SIDE])).c_str(), &rect, 1); int count = 0; for (int i = 0; i < HEIGHT / SIDE; ++i) { for (int j = 0; j < WIDTH / SIDE; ++j) { if (isopen[i][j] == true) { count++; } } } cout << count << endl; if (nearbythunder[cur.x / SIDE][cur.y / SIDE] == 9 || count==((WIDTH/SIDE)*(HEIGHT/SIDE)- THUNDERNUM)) { //說明游戲結(jié)束 setfillcolor(RED); for (int i = 0; i < thunder.getThunderPoint().size(); i++) { fillcircle((thunder.getThunderPoint()[i]).x + SIDE / 2, (thunder.getThunderPoint()[i]).y + SIDE / 2, SIDE / 2); } settextcolor(WHITE); settextstyle(SIDE, SIDE, "楷體"); rect.left = 0; rect.top = 4*SIDE; rect.right = WIDTH; rect.bottom = HEIGHT; drawtext("GAMEOVER!", &rect, 2); isOver = true; return; } } }; int main() { initgraph(WIDTH, HEIGHT);//初始化界面 srand((unsigned)time(NULL));//設(shè)置隨機數(shù)據(jù)種子,以當前的時間戳為種子 setbkcolor(RED); srand((unsigned)time(NULL)); settextcolor(BLUE); setbkmode(TRANSPARENT); // 設(shè)置文字輸出模式為透明c setbkcolor(HSLtoRGB(100, 0.3, 7.5f)); Grid gr; while (gr.isOver==false) { gr.keyDown(); } system("pause"); clearcliprgn(); }
代碼解讀:
1.類之間的聯(lián)系
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++中priority_queue的使用與模擬實現(xiàn)
本文主要介紹了C++中priority_queue的使用與模擬實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02關(guān)于函數(shù)調(diào)用方式__stdcall和__cdecl詳解
下面小編就為大家?guī)硪黄P(guān)于函數(shù)調(diào)用方式__stdcall和__cdecl詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09詳解C語言中printf輸出的相關(guān)函數(shù)
這篇文章主要介紹了C語言中printf輸出的相關(guān)函數(shù)總結(jié),是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-08-08