C++實(shí)現(xiàn)控制臺(tái)版掃雷程序
本文實(shí)例為大家分享了C++實(shí)現(xiàn)控制臺(tái)版掃雷程序的具體代碼,供大家參考,具體內(nèi)容如下
測(cè)試平臺(tái): WIN7
工具: VC6.0 , VS2008都能編譯得過(guò)。
花了兩天時(shí)間寫的,里面涉及的算法大都是自己想的,所以可能有些BUG。
#include <iostream> #include <time.h> #include <windows.h> using namespace std; ? #pragma comment (linker,"/subsystem:console") ? #define BLACK 0?? ??? ?//空白 #define MINE 100?? ?//地雷 #define NOSWEEP 0?? ?//未掃過(guò) #define SWEEP 1?? ??? ?//掃雷 #define FLAG 2?? ??? ?//標(biāo)記 ? class WinMine { public: ? ?? ?WinMine(int iRow, int iColumn); ?? ?~WinMine(); public: ?? ?void InitMine(int iMineMax); ?? ?void SetColor(); ?? ?void StatisticsMine(); ?? ?void Map(); ?? ?bool OpenWhites(int x, int y, int status); ?? ?void GameStart(int iMineMax); ?? ?void GameOver(); ?? ?bool GoodOver(); private: ?? ?int **m_ppMine; ?? ?int **m_ppSweep; ?? ?bool m_bMineflag; ?? ?bool m_bSweepflag; ?? ?int m_row; ?? ?int m_column; ?? ?int m_minenum; }; ? int main(void) { ?? ?system("color 0d"); ?? ?while (true) ?? ?{ ?? ??? ?int level; ?? ??? ?WinMine *Mine; ?? ??? ?cout << "請(qǐng)輸入游戲等級(jí):" <<endl; ?? ??? ?cout << "1.初級(jí)" <<endl; ?? ??? ?cout << "2.中級(jí)" <<endl; ?? ??? ?cout << "3.高級(jí)" <<endl; ?? ??? ?cout << "4.退出" <<endl; ?? ??? ?cin >> level; ?? ??? ?if (level == 1) ?? ??? ?{ ?? ??? ??? ?Mine = new WinMine(9,9); ?? ??? ??? ?Mine->GameStart(10); ?? ??? ?} ?? ??? ?else if (level == 2) ?? ??? ?{ ?? ??? ??? ?Mine = new WinMine(16,16); ?? ??? ??? ?Mine->GameStart(40); ?? ??? ?} ?? ??? ?else if (level == 3) ?? ??? ?{ ?? ??? ??? ?Mine = new WinMine(16,30); ?? ??? ??? ?Mine->GameStart(70); ?? ??? ?} ?? ??? ?else if (level == 4) ?? ??? ?{ ?? ??? ??? ?return 0; ?? ??? ?} ?? ??? ?else? ?? ??? ?{ ?? ??? ??? ?cout << "輸入錯(cuò)誤!" <<endl; ?? ??? ??? ?continue; ?? ??? ?} ?? ??? ?delete Mine; ?? ?} ? ?? ?return 0; } ? WinMine::WinMine(int iRow, int iColumn) { ?? ?int i; ?? ? ?? ?//儲(chǔ)雷狀態(tài) ?? ?m_ppMine = (int **) new int[iRow]; if (!m_ppMine) return; ?? ?m_ppMine[0] = new int[iRow * iColumn]; if (!*m_ppMine) { delete[] m_ppMine; m_ppMine = NULL; return;} ?? ?m_bMineflag = true; ? ?? ?//掃雷狀態(tài) ?? ?m_ppSweep = (int **) new int[iRow]; if (!m_ppSweep) return; ?? ?m_ppSweep[0] = new int[iRow * iColumn]; if (!*m_ppSweep) { delete[] m_ppSweep; m_ppSweep = NULL; return;} ?? ?m_bSweepflag = true; ? ?? ?m_row = iRow; m_column = iColumn; ?? ? ?? ?for (i = 1; i < iRow; i++) ?? ?{ ?? ??? ?m_ppMine[i] = m_ppMine[0] + i * iRow; ?? ?} ? ?? ?for (i = 1; i < iRow; i++) ?? ?{ ?? ??? ?m_ppSweep[i] = m_ppSweep[0] + i * iRow; ?? ?} ? ?? ?memset(m_ppSweep[0], 0, iRow * iColumn * sizeof(int)); ?? ?memset(m_ppMine[0], 0, iRow * iColumn * sizeof(int)); ?? ? } ? WinMine::~WinMine() { ?? ?if (m_bMineflag) ?? ?{ ?? ??? ?if (m_ppMine[0]) delete[] m_ppMine[0]; ?? ??? ?if (m_ppMine) delete[] m_ppMine; ?? ?} ?? ?if (m_bSweepflag) ?? ?{ ?? ??? ?if (m_ppSweep[0]) delete[] m_ppSweep[0]; ?? ??? ?if (m_ppSweep) delete[] m_ppSweep; ?? ?} } ? //設(shè)置顏色 void WinMine::SetColor() { ?? ?system("color 0a"); } ? //初始化雷數(shù) void WinMine::InitMine(int iMineMax)?? ? { ?? ?int x, y,num = 0; ?? ?srand( (unsigned)time(NULL) ); ?? ?for (int i = 0; num != iMineMax; i++) ?? ?{ ?? ??? ?x = rand()%m_row; ?? ??? ?y = rand()%m_column; ?? ??? ?if (MINE != m_ppMine[x][y]) ?? ??? ?{ ?? ??? ??? ?m_ppMine[x][y] = MINE; ?? ??? ??? ?num++; ?? ??? ?} ?? ?} ?? ?m_minenum = num; ? } ? //統(tǒng)計(jì)雷數(shù) void WinMine::StatisticsMine() { ?? ?int i, j; ?? ?int n, m; ?? ?int num = 0; //保存雷數(shù) ? ?? ?//中間 ?? ?for ( i = 1; i < m_row - 1; i++) ?? ?{ ?? ??? ?for ( j = 1; j < m_column - 1; j++) ?? ??? ?{ ?? ??? ??? ?if ( m_ppMine[i][j] == BLACK) ?? ??? ??? ?{ ?? ??? ??? ??? ?for (n = i - 1; n <= i + 1; n++) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?for (m = j - 1; m <= j + 1; m++) ?? ??? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ??? ?if ( m_ppMine[n][m] == MINE ) ?? ??? ??? ??? ??? ??? ??? ?num++; ? ?? ??? ??? ??? ??? ?} ?? ??? ??? ??? ?} ?? ??? ??? ??? ?m_ppMine[i][j] = num; ?? ??? ??? ??? ?num = 0; ?? ??? ??? ?} ? ?? ??? ?} ?? ?} ? ?? ?//頂邊 ?? ?for ( i = 1; i < m_column - 1; i++) ?? ?{ ?? ??? ?if (m_ppMine[0][i] == BLACK) ?? ??? ?{ ?? ??? ??? ?for (n = 0; n < 2; n++) ?? ??? ??? ?{ ?? ??? ??? ??? ?for (m = i - 1; m <= i + 1; m++) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?if (m_ppMine[n][m] == MINE) ?? ??? ??? ??? ??? ??? ?num++; ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ??? ?m_ppMine[0][i] = num; ?? ??? ??? ?num = 0; ?? ??? ?} ?? ?} ? ?? ?//下邊 ?? ?for ( i = 1; i < m_column - 1; i++) ?? ?{ ?? ??? ?if (m_ppMine[m_row - 1][i] == BLACK) ?? ??? ?{ ?? ??? ??? ?for (n = m_row - 2; n < m_row; n++) ?? ??? ??? ?{ ?? ??? ??? ??? ?for (m = i - 1; m <= i + 1; m++) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?if (m_ppMine[n][m] == MINE) ?? ??? ??? ??? ??? ??? ?num++; ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ??? ?m_ppMine[m_row - 1][i] = num; ?? ??? ??? ?num = 0; ?? ??? ?} ?? ?} ? ?? ?//左邊 ? ?? ?for ( i = 1; i < m_row - 1; i++ ) ?? ?{ ?? ??? ?if (m_ppMine[i][0] == BLACK) ?? ??? ?{ ?? ??? ??? ?for (n = i - 1; n <= i + 1; n++) ?? ??? ??? ?{ ?? ??? ??? ??? ?for (m = 0; m < 2; m++) ?? ??? ??? ??? ??? ?if (m_ppMine[n][m] == MINE) ?? ??? ??? ??? ??? ??? ?num++;?? ? ?? ??? ??? ?} ? ?? ??? ??? ?m_ppMine[i][0] = num; ?? ??? ??? ?num = 0; ?? ??? ?} ?? ?} ? ?? ?//右邊 ?? ?for ( i = 1; i < m_row - 1; i++ ) ?? ?{ ?? ??? ?if (m_ppMine[i][m_column - 1] == BLACK) ?? ??? ?{ ?? ??? ??? ?for (n = i - 1; n <= i + 1; n++) ?? ??? ??? ?{ ?? ??? ??? ??? ?for (m = m_column - 2; m < m_column; m++) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?if (m_ppMine[n][m] == MINE) ?? ??? ??? ??? ??? ??? ?num++; ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ??? ?m_ppMine[i][m_column - 1] = num; ?? ??? ??? ?num = 0; ?? ??? ?} ?? ?} ? ?? ?//左上角 ?? ?if (m_ppMine[0][0] != MINE) ?? ?{ ?? ??? ?if (m_ppMine[0][1] == MINE) ?? ??? ??? ?num++; ?? ??? ?if (m_ppMine[1][1] == MINE) ?? ??? ??? ?num++; ?? ??? ?if (m_ppMine[1][0] == MINE) ?? ??? ??? ?num++; ?? ??? ?m_ppMine[0][0] = num; ?? ??? ?num = 0; ?? ?} ? ? ?? ?//左下角 ? ?? ?if (m_ppMine[m_row - 1][0] != MINE) ?? ?{ ?? ??? ?if (m_ppMine[m_row - 2][0] == MINE) ?? ??? ??? ?num++; ?? ??? ?if (m_ppMine[m_row - 2][1] == MINE) ?? ??? ??? ?num++; ?? ??? ?if (m_ppMine[m_row - 1][1] == MINE) ?? ??? ??? ?num++; ?? ??? ?m_ppMine[m_row - 1][0] = num; ?? ??? ?num = 0; ?? ?} ? ?? ?//右上角 ?? ?if (m_ppMine[0][m_column - 1] != MINE) ?? ?{ ?? ??? ?if (m_ppMine[1][m_column - 1] == MINE) ?? ??? ??? ?num++; ?? ??? ?if (m_ppMine[1][m_column - 2] == MINE) ?? ??? ??? ?num++; ?? ??? ?if (m_ppMine[0][m_column - 2] == MINE) ?? ??? ??? ?num++; ?? ??? ?m_ppMine[0][m_column - 1] = num; ?? ??? ?num = 0; ?? ?} ? ?? ?//右下角 ?? ?if (m_ppMine[m_row - 1][m_column - 1] != MINE) ?? ?{ ?? ??? ?if (m_ppMine[m_row - 2][m_column - 1] == MINE) ?? ??? ??? ?num++; ?? ??? ?if (m_ppMine[m_row - 2][m_column - 2] == MINE) ?? ??? ??? ?num++; ?? ??? ?if (m_ppMine[m_row - 1][m_column - 2] == MINE) ?? ??? ??? ?num++; ?? ??? ?m_ppMine[m_row - 1][m_column - 1] = num; ?? ??? ?num = 0; ?? ?} } ? //展開(kāi)空白 bool WinMine::OpenWhites(int row, int column, int status) { ?? ?if (row < 0 || row > (m_row - 1) || column < 0 || column > (m_column - 1)) ?? ??? ?return true; ?? ?if (status == SWEEP && ?m_ppMine[row][column] == MINE) ?? ?{ ?? ??? ?return false; ?? ?} ? ?? ?if (status == FLAG) ?? ?{ ?? ??? ?m_ppSweep[row][column] = FLAG; ?? ??? ?return true; ?? ?} ? ?? ?if (m_ppSweep[row][column] == NOSWEEP && m_ppMine[row][column] != MINE) ?? ?{ ? ?? ??? ?if (m_ppMine[row][column] > 0) ?? ??? ?{ ?? ??? ??? ?m_ppSweep[row][column] = SWEEP;? ?? ??? ??? ?return true; ?? ??? ?} ?? ??? ?else ?? ??? ?{ ?? ??? ??? ?m_ppSweep[row][column] = SWEEP; ?? ??? ??? ?OpenWhites(row-1, column, status); ?? ??? ??? ?OpenWhites(row-1, column-1, status); ?? ??? ??? ?OpenWhites(row-1, column+1, status); ?? ??? ??? ?OpenWhites(row, column-1, status); ?? ??? ??? ?OpenWhites(row, column+1, status); ?? ??? ??? ?OpenWhites(row+1, column, status); ?? ??? ??? ?OpenWhites(row+1, column-1, status); ?? ??? ??? ?OpenWhites(row+1, column+1, status); ?? ??? ?} ?? ?} ?? ?return true; } ? //地圖 void WinMine::Map() { ?? ?SetColor(); ?? ?int i, j; ?? ?for ( i = 0; i < m_row; i++) ?? ?{ ?? ??? ?for (j = 0; j < m_column; j++) ?? ??? ?{ ?? ??? ??? ?if (m_ppSweep[i][j] == SWEEP) ?? ??? ??? ?{ ?? ??? ??? ??? ?if (m_ppMine[i][j] == 0) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cout << "□"; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?else if (m_ppMine[i][j] == 1) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cout << "①"; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?else if (m_ppMine[i][j] == 2) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cout << "②"; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?else if (m_ppMine[i][j] == 3) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cout << "③"; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?else if (m_ppMine[i][j] == 4) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cout << "④"; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?else if (m_ppMine[i][j] == 5) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cout << "⑤"; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?else if (m_ppMine[i][j] == 6) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cout << "⑥"; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?else if (m_ppMine[i][j] == 7) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cout << "⑦"; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?else if (m_ppMine[i][j] == 8) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cout << "⑧"; ?? ??? ??? ??? ?}?? ? ? ?? ??? ??? ?} ?? ??? ??? ?else if (m_ppSweep[i][j] == FLAG) ?? ??? ??? ?{ ?? ??? ??? ??? ?cout << "⊙"; ?? ??? ??? ?} ?? ??? ??? ?else ?? ??? ??? ??? ?cout << "▇"; ?? ??? ?} ?? ??? ?cout << endl; ?? ?} } ? //游戲結(jié)束 void WinMine::GameOver() { ? ?? ?int i, j; ?? ?for ( i = 0; i < m_row; i++) ?? ?{ ?? ??? ?for (j = 0; j < m_column; j++) ?? ??? ?{ ?? ??? ??? ?if (m_ppMine[i][j] == MINE) ?? ??? ??? ??? ?cout << "★"; ?? ??? ??? ?else? ?? ??? ??? ??? ?cout << "□"; ?? ??? ??? ? ?? ??? ?} ?? ??? ?cout << endl; ?? ?} } //檢查是否雷標(biāo)記正確。 bool WinMine::GoodOver() { ?? ?int i, j; ?? ?int num = 0; ?? ?for (i = 0; i < m_row; i++) ?? ?{ ?? ??? ?for (j = 0; j < m_column; j++) ?? ??? ?{ ?? ??? ??? ?if (m_ppSweep[i][j] == FLAG && m_ppMine[i][j] == MINE) ?? ??? ??? ??? ?num++; ? ?? ??? ?} ?? ?} ?? ?if (num == m_minenum) ?? ??? ?return true; ?? ?else ?? ??? ?return false; } ? //開(kāi)始游戲 void WinMine::GameStart(int iMineMax) { ?? ?int x, y; ?? ?int flag; begin: ?? ?memset(m_ppSweep[0], 0, m_row * m_column * sizeof(int)); ?? ?memset(m_ppMine[0], 0, m_row * m_column * sizeof(int)); ?? ?InitMine(iMineMax); ?? ?StatisticsMine(); ? ?? ?while (true) ?? ?{ ?? ??? ?system("cls"); ? ?? ??? ?Map(); ?? ??? ?cout << "請(qǐng)輸入要掃的區(qū)域的坐標(biāo):" <<endl; ?? ??? ?cout << "請(qǐng)輸入縱坐標(biāo):";cin>>x; ?? ??? ?cout << "請(qǐng)輸入橫坐標(biāo):";cin>>y; ?? ??? ?if (x <= 0 || x > m_row || y <= 0 || y > m_column) ?? ??? ?{ ?? ??? ??? ?cout <<"輸入錯(cuò)誤請(qǐng)重新輸入" <<endl; ?? ??? ??? ?Sleep(1000); ?? ??? ??? ?continue; ?? ??? ?} ? ?? ??? ?cout << "請(qǐng)輸入是要做標(biāo)記還是掃雷,掃雷請(qǐng)按1,標(biāo)記請(qǐng)按2:" <<endl; ?? ??? ?cin >> flag; ?? ??? ?if ( false == OpenWhites(x-1, y-1, flag) ) ?? ??? ?{ ?? ??? ??? ?int i; ?? ??? ??? ?system("cls"); ?? ??? ??? ?GameOver(); ?? ??? ??? ?cout << "游戲結(jié)束!" <<endl; ?? ??? ??? ?cout << "繼續(xù)游戲請(qǐng)按1,退出游戲請(qǐng)按0:"<<endl; ?? ??? ??? ?cin >> i; ?? ??? ??? ?if (i == 1) ?? ??? ??? ??? ?goto begin; ?? ??? ??? ?else? ?? ??? ??? ??? ?goto end; ?? ??? ?} ?? ??? ?else ?? ??? ?{ ?? ??? ??? ?if (GoodOver() == true) ?? ??? ??? ?{ ?? ??? ??? ??? ?int i; ?? ??? ??? ??? ?cout << "掃雷成功!" <<endl; ?? ??? ??? ??? ?cout << "繼續(xù)游戲請(qǐng)按1,退出游戲請(qǐng)按0:"<<endl; ?? ??? ??? ??? ?cin >> i; ?? ??? ??? ??? ?if (i == 1) ?? ??? ??? ??? ??? ?goto begin; ?? ??? ??? ??? ?else? ?? ??? ??? ??? ??? ?goto end; ?? ??? ??? ?} ?? ??? ?} ?? ?} end: ?? ?return; }
再為大家分享一位作者的文章:控制臺(tái)版掃雷(支持鼠標(biāo)操作)
//說(shuō)明: 左鍵雙擊對(duì)應(yīng)windows自帶掃雷中的雙鍵點(diǎn)擊 ? #include <windows.h> #include <cstdlib> #include <ctime> #include <list> ? using namespace std; //數(shù)組索引轉(zhuǎn)成坐標(biāo) #define X(v) (v) % WIDTH #define Y(v) (v) / WIDTH //坐標(biāo)系統(tǒng)轉(zhuǎn)換 #define BOARDX(x) ((x) - OFFSETX) / 2 #define BOARDY(y) (y) - OFFSETY #define SCREENX(x) 2 * (x) + OFFSETX #define SCREENY(y) (y) + OFFSETY #define BACKGROUND_WHITE (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED) #define FOREGROUND_WHITE (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED) ? typedef enum { ?? ?UNKNOWN, ?? ?DISPLAY, ?? ?MARKED } State; ? typedef enum { ?? ?NUMBER, ?? ?EMPTY, ?? ?MINE } MType; ? typedef struct { ?? ?State state; ?? ?MType mtype; ?? ?int val; } Cell; ? typedef bool (* CmpProc)(Cell& cell, void* pData); ? int HEIGHT ? = 16; int WIDTH ? ?= 16; int MINE_CNT = 40;?? ?//地雷數(shù) int CELL_CNT; //第一個(gè)格子的x, y偏移 int OFFSETX = 3; int OFFSETY = 3; int flagCnt;?? ??? ?//標(biāo)記數(shù) int mineLeft;?? ??? ?//地雷剩余 int unkwLeft;?? ??? ?//未知剩余 int liveLeft;?? ??? ?//生命剩余 COORD tmPos;?? ??? ?//計(jì)時(shí)坐標(biāo) COORD mnPos;?? ??? ?//地雷(剩余)坐標(biāo) COORD lvPos;?? ??? ?//生命坐標(biāo) bool bGameStart, bGameStop;?? ??? ?//游戲開(kāi)始.結(jié)束標(biāo)記 DWORD dwStart; HANDLE hOut, hIn; Cell cells[16][30]; ? void writeChar(LPCSTR pChar, COORD wrtCrd) { ?? ?DWORD wtn; ?? ?WriteConsoleOutputCharacter(hOut, pChar, strlen(pChar), wrtCrd, &wtn); } ? void fillChar(TCHAR cChar, DWORD len, COORD wrtCrd) { ?? ?DWORD wtn; ?? ?FillConsoleOutputCharacter(hOut, cChar, len, wrtCrd, &wtn); } ? void fillAttr(WORD attr, DWORD len, COORD wrtCrd) { ?? ?DWORD wtn; ?? ?FillConsoleOutputAttribute(hOut, attr, len, wrtCrd, &wtn); } ? bool isCell(int x, int y) { ?? ?return x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT; } ? bool isMine(int x, int y) { ?? ?return isCell(x, y) && cells[y][x].mtype == MINE; } ? bool cmpState(Cell& cell, void* pData) { ?? ?return cell.state == *(State*)pData; } ? bool cmpMtype(Cell& cell, void* pData) { ?? ?return cell.mtype == *(MType*)pData; } //四周格子作比較 int aroundCmp(int x, int y, CmpProc cmp, void* pData) { ?? ?int nRet = 0; ?? ?for (int y0=y-1; y0<=y+1; y0++) ?? ?{ ?? ??? ?for (int x0=x-1; x0<=x+1; x0++) ?? ??? ?{ ?? ??? ??? ?if (isCell(x0, y0)? ?? ??? ??? ??? ?&& !(x0 == x && y0 == y))?? ??? ?//not self ?? ??? ??? ?{ ?? ??? ??? ??? ?nRet += cmp(cells[y0][x0], pData); ?? ??? ??? ?} ?? ??? ?} ?? ?} ?? ?return nRet; } ? int aroundMines(int x, int y) { ?? ?int val = MINE; ?? ?return aroundCmp(x, y, cmpMtype, &val); } ? int aroundMarks(int x, int y) { ?? ?int val = MARKED; ?? ?return aroundCmp(x, y, cmpState, &val); } //擾亂數(shù)組的前n個(gè)元素 void ruffle(int* arr, int len, int n) { ?? ?for (int i=0; i<n; i++) ?? ?{ ?? ??? ?int j = rand() % len; ?? ??? ?int tmp = arr[i]; ?? ??? ?arr[i] = arr[j]; ?? ??? ?arr[j] = tmp; ?? ?} } //計(jì)時(shí) void setElapsedTime() { ?? ?if (bGameStart && !bGameStop) ?? ?{ ?? ??? ?DWORD dwDelt = (GetTickCount() - dwStart) / 1000; ?? ??? ?if (dwDelt < 1000) ?? ??? ?{ ?? ??? ??? ?char buf[5] = {0}; ?? ??? ??? ?sprintf(buf, "%.3d\0", dwDelt); ?? ??? ??? ?writeChar(buf, tmPos); ?? ??? ?}?? ? ?? ?} } //剩余雷數(shù)(僅顯示, 非實(shí)際) void setMinesLeft() { ?? ?char buf[5] = {0}; ?? ?sprintf(buf, "%2d\0", MINE_CNT - flagCnt); ?? ?writeChar(buf, mnPos); } //剩余生命 void setLivesLeft(int delt = 0) { ?? ?char buf[5] = {0}; ?? ?liveLeft += delt; ?? ?sprintf(buf, "%2d\0", liveLeft); ?? ?writeChar(buf, lvPos); } ? void drawCell(int x, int y) { ?? ?Cell* pCell = &cells[y][x]; ?? ?COORD cellCrd = {SCREENX(x), SCREENY(y)}; ?? ?char buf[3] = {0}; ?? ?switch (pCell->state) ?? ?{ ?? ?case UNKNOWN: ?? ??? ?sprintf(buf, "□\0"); ?? ??? ?break; ?? ?case MARKED: ?? ??? ?sprintf(buf, " P\0");?? ? ?? ??? ?break; ?? ?case DISPLAY: ?? ??? ?switch (pCell->mtype) ?? ??? ?{ ?? ??? ?case MINE: ?? ??? ??? ?sprintf(buf, " *\0"); ?? ??? ??? ?break; ?? ??? ?case EMPTY: ?? ??? ??? ?sprintf(buf, " ?\0"); ?? ??? ??? ?break; ?? ??? ?case NUMBER: ?? ??? ??? ?sprintf(buf, " %d\0", pCell->val); ?? ??? ??? ?fillAttr((WORD)pCell->val, 2, cellCrd);?? ?//數(shù)字著色 ?? ??? ??? ?break; ?? ??? ?} ?? ??? ?break; ?? ?} ?? ?writeChar(buf, cellCrd); } //初始化信息欄 void initInfoBar() { ?? ?char buf[50] = {0}; ?? ?sprintf(buf, "生命: %2d ? 地雷: %2d ? 用時(shí): 000\0", liveLeft, MINE_CNT); ?? ?COORD crd = {(80 - strlen(buf)) / 2, SCREENY(HEIGHT) + 1};?? ??? ?//水平居中 ?? ?writeChar(buf, crd); ?? ?crd.X += 6;?? ? ? ?lvPos = crd; ?? ?crd.X += 11;?? ?mnPos = crd; ?? ?crd.X += 11;?? ?tmPos = crd; } ? void clearScreen() { ?? ?COORD crd = {0, 0}; ?? ?CONSOLE_SCREEN_BUFFER_INFO csbi; ?? ?GetConsoleScreenBufferInfo(hOut, &csbi); ?? ?fillChar(' ', csbi.dwSize.X * csbi.dwSize.Y, crd); ?? ?fillAttr(FOREGROUND_WHITE, csbi.dwSize.X * csbi.dwSize.Y, crd); } ? void initGame() { ?? ?srand((unsigned)time(NULL)); ?? ?SetConsoleTitle("掃雷控制臺(tái)版 ? F2: 初級(jí); F3: 中級(jí); F4: 高級(jí)"); ?? ?clearScreen(); ?? ?CELL_CNT = HEIGHT * WIDTH; ?? ?OFFSETX = (80 - WIDTH * 2) / 2;?? ?//水平居中 ?? ?int* idxs = new int[CELL_CNT];?? ?//地雷索引 ?? ?int i, x, y; ?? ?//init cells and indexs ?? ?for (i=0; i<CELL_CNT; i++) ?? ?{ ?? ??? ?cells[Y(i)][X(i)].mtype = EMPTY; ?? ??? ?cells[Y(i)][X(i)].state = UNKNOWN; ?? ??? ?idxs[i] = i; ?? ?} ?? ?ruffle(idxs, CELL_CNT, MINE_CNT); ?? ?//fill mines ?? ?for (i=0; i<MINE_CNT; i++) ?? ?{ ?? ??? ?cells[Y(idxs[i])][X(idxs[i])].mtype = MINE; ?? ?} ?? ?//fill nums && print the game ?? ?for (y=0; y<HEIGHT; y++) ?? ?{ ?? ??? ?for (x=0; x<WIDTH; x++) ?? ??? ?{ ?? ??? ??? ?if (!isMine(x, y)) ?? ??? ??? ?{ ?? ??? ??? ??? ?cells[y][x].val = aroundMines(x, y); ?? ??? ??? ??? ?cells[y][x].mtype = cells[y][x].val > 0 ? NUMBER : EMPTY; ?? ??? ??? ?} ?? ??? ??? ?drawCell(x, y); ?? ??? ?} ?? ?} ?? ?delete[] idxs; ? ?? ?bGameStart = false; ?? ?bGameStop ?= false; ?? ?mineLeft = MINE_CNT; ?? ?unkwLeft = CELL_CNT; ?? ?liveLeft = MINE_CNT / 20 + 1;?? ?//每二十個(gè)雷加一條命 ?? ?flagCnt ?= 0; ?? ?initInfoBar(); } ? void showAll() { ?? ?for (int i=0; i<CELL_CNT; i++) ?? ?{ ?? ??? ?cells[Y(i)][X(i)].state = DISPLAY; ?? ??? ?drawCell(X(i), Y(i)); ?? ?} } ? void showTip(const char* tipMsg, WORD attr = FOREGROUND_WHITE) { ?? ?COORD tipCrd = {(80 - strlen(tipMsg)) / 2, 1}; ?? ?writeChar(tipMsg, tipCrd); ?? ?fillAttr(attr, strlen(tipMsg), tipCrd); } ? void gameWin() { ?? ?if (!bGameStop) ?? ?{ ?? ??? ?showTip("恭喜你, 你贏了! ", FOREGROUND_GREEN | FOREGROUND_INTENSITY); ?? ??? ?bGameStop = true; ?? ?} } ? void gameOver(int x, int y) { ?? ?setLivesLeft(-1); ?? ?if (liveLeft == 0) ?? ?{ ?? ??? ?showAll(); ?? ??? ?showTip("游戲結(jié)束, 請(qǐng)重新來(lái)過(guò)!", FOREGROUND_RED | FOREGROUND_INTENSITY); ?? ??? ?bGameStop = true; ?? ?} ?? ?else ?? ?{ ?? ??? ?COORD crd = {SCREENX(x), SCREENY(y)}; ?? ??? ?WORD attr = FOREGROUND_WHITE; ?? ??? ?for (int i=0; i<6; i++)?? ??? ?//觸雷閃爍 ?? ??? ?{ ?? ??? ??? ?attr = FOREGROUND_WHITE ^ FOREGROUND_RED ^ attr; ?? ??? ??? ?fillAttr(attr, 2, crd); ?? ??? ??? ?Sleep(100); ?? ??? ?} ?? ?} } ? void showAround(int x, int y) {?? ? ?? ?list<COORD> lst; ?? ?COORD crd = {x, y}; ?? ?lst.push_back(crd); ?? ?while (!lst.empty()) ?? ?{ ?? ??? ?crd = lst.front(); ?? ??? ?lst.pop_front(); ?? ??? ?x = crd.X; ?? ??? ?y = crd.Y; ?? ??? ?for (int x0=x-1; x0<=x+1; x0++) ?? ??? ?{ ?? ??? ??? ?for (int y0=y-1; y0<=y+1; y0++) ?? ??? ??? ?{ ?? ??? ??? ??? ?if (!isCell(x0, y0)?? ?|| (x0 == x && y0 == y)) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?continue; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?Cell* pCell = &cells[y0][x0]; ?? ??? ??? ??? ?if (pCell->state == UNKNOWN) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?if (pCell->mtype == MINE) ?? ??? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ??? ?gameOver(x0, y0); ?? ??? ??? ??? ??? ??? ?break; ?? ??? ??? ??? ??? ?} ?? ??? ??? ??? ??? ?else if (pCell->mtype == EMPTY) ?? ??? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ??? ?crd.X = x0; ?? ??? ??? ??? ??? ??? ?crd.Y = y0; ?? ??? ??? ??? ??? ??? ?lst.push_back(crd); ?? ??? ??? ??? ??? ?} ?? ??? ??? ??? ??? ?unkwLeft--; ?? ??? ??? ??? ??? ?pCell->state = DISPLAY; ?? ??? ??? ??? ??? ?drawCell(x0, y0); ?? ??? ??? ??? ?} ?? ??? ??? ?}?? ?//end for ?? ??? ?}?? ?//end for ?? ?} } ? void onCellLDBLClick(int x, int y) { ?? ?Cell* pCell = &cells[y][x]; ?? ?//左雙擊對(duì)顯示的數(shù)字格子起作用, 且該格子周圍的標(biāo)記數(shù)等于該數(shù)字 ?? ?if (pCell->mtype == NUMBER && pCell->state == DISPLAY? ?? ??? ?&& aroundMarks(x, y) == pCell->val) ?? ?{ ?? ??? ?showAround(x, y); ?? ?} } ? void onCellLClick(int x, int y) { ?? ?Cell* pCell = &cells[y][x]; ?? ?//左擊只對(duì)未知格子起作用 ?? ?if (pCell->state == UNKNOWN) ?? ?{ ?? ??? ?if (pCell->mtype == MINE) ?? ??? ?{ ?? ??? ??? ?gameOver(x, y); ?? ??? ?} ?? ??? ?else ?? ??? ?{ ?? ??? ??? ?pCell->state = DISPLAY; ?? ??? ??? ?unkwLeft--; ?? ??? ??? ?drawCell(x, y); ?? ??? ??? ?if (pCell->mtype == EMPTY) ?? ??? ??? ?{ ?? ??? ??? ??? ?showAround(x, y); ?? ??? ??? ?} ?? ??? ?} ?? ?}?? ? } ? void onCellRClick(int x, int y) { ?? ?Cell* pCell = &cells[y][x]; ?? ?//右擊對(duì)未知, 標(biāo)記格子起作用 ?? ?if (pCell->state != DISPLAY) ?? ?{ ?? ??? ?if (pCell->state == UNKNOWN) ?? ??? ?{ ?? ??? ??? ?pCell->state = MARKED; ?? ??? ??? ?mineLeft -= pCell->mtype == MINE ? 1 : 0; ?? ??? ??? ?unkwLeft--; ?? ??? ??? ?flagCnt++; ?? ??? ?} ?? ??? ?else ?? ??? ?{ ?? ??? ??? ?pCell->state = UNKNOWN; ?? ??? ??? ?mineLeft += pCell->mtype == MINE ? 1 : 0; ?? ??? ??? ?unkwLeft++; ?? ??? ??? ?flagCnt--; ?? ??? ?} ?? ??? ?drawCell(x, y); ?? ??? ?setMinesLeft(); ?? ?} } ? void onKeyDown(WORD keyCode) { ?? ?switch (keyCode) ?? ?{ ?? ?case VK_F2:?? ??? ?//初級(jí) ?? ??? ?HEIGHT ? = 9; ?? ??? ?WIDTH ? ?= 9; ?? ??? ?MINE_CNT = 10; ?? ??? ?initGame(); ?? ??? ?break; ?? ?case VK_F3:?? ??? ?//中級(jí) ?? ??? ?HEIGHT ? = 16; ?? ??? ?WIDTH ? ?= 16; ?? ??? ?MINE_CNT = 40; ?? ??? ?initGame(); ?? ??? ?break; ?? ?case VK_F4:?? ??? ?//高級(jí) ?? ??? ?HEIGHT ? = 16; ?? ??? ?WIDTH ? ?= 30; ?? ??? ?MINE_CNT = 99; ?? ??? ?initGame(); ?? ??? ?break; ?? ?case VK_F12: ?? ??? ?if (liveLeft < 99) ?? ??? ?{ ?? ??? ??? ?setLivesLeft(1); ?? ??? ?} ?? ??? ?break; ?? ?default: ?? ??? ?break; ?? ?} } ? void afterMouseEvent() { ?? ?if (!bGameStart) ?? ?{ ?? ??? ?bGameStart = true; ?? ??? ?dwStart = GetTickCount(); ?? ?} ?? ?if (mineLeft == 0 && unkwLeft == 0) ?? ?{ ?? ??? ?gameWin(); ?? ?} } ? int main(int argc, char* argv[]) { ?? ?hIn ?= GetStdHandle(STD_INPUT_HANDLE); ?? ?hOut = CreateConsoleScreenBuffer( ?? ??? ??? ?GENERIC_WRITE, ?? ??? ??? ?0, ?? ??? ??? ?NULL, ?? ??? ??? ?CONSOLE_TEXTMODE_BUFFER, ?? ??? ??? ?NULL ?? ??? ??? ?); ?? ?CONSOLE_CURSOR_INFO cci; ?? ?cci.dwSize = 1; ?? ?cci.bVisible = FALSE; ?? ?SetConsoleCursorInfo(hOut, &cci);?? ?//隱藏光標(biāo) ?? ?SetConsoleActiveScreenBuffer(hOut); ?? ?initGame(); ?? ?//監(jiān)聽(tīng)事件 ?? ?for (;;) ?? ?{ ?? ??? ?DWORD nEvts; ?? ??? ?GetNumberOfConsoleInputEvents(hIn, &nEvts); ?? ??? ?if (nEvts > 0) ?? ??? ?{ ?? ??? ??? ?INPUT_RECORD inpRec; ?? ??? ??? ?ReadConsoleInput(hIn, &inpRec, 1, &nEvts); ?? ??? ??? ?bool bClked = false;?? ?//是否有合法鼠標(biāo)事件發(fā)生 ?? ??? ??? ?if (!bGameStop && inpRec.EventType == MOUSE_EVENT) ?? ??? ??? ?{ ?? ??? ??? ??? ?int x = BOARDX(inpRec.Event.MouseEvent.dwMousePosition.X); ?? ??? ??? ??? ?int y = BOARDY(inpRec.Event.MouseEvent.dwMousePosition.Y); ?? ??? ??? ??? ?if (!isCell(x, y)) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?continue; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?bClked = true; ?? ??? ??? ??? ?switch (inpRec.Event.MouseEvent.dwButtonState) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ?case FROM_LEFT_1ST_BUTTON_PRESSED: ?? ??? ??? ??? ??? ?if (inpRec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) ?? ??? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ??? ?onCellLDBLClick(x, y); ?? ??? ??? ??? ??? ??? ?break;?? ?//處理過(guò)雙擊不再處理單擊 ?? ??? ??? ??? ??? ?} ?? ??? ??? ??? ??? ?onCellLClick(x, y); ?? ??? ??? ??? ??? ?break; ?? ??? ??? ??? ?case RIGHTMOST_BUTTON_PRESSED: ?? ??? ??? ??? ??? ?onCellRClick(x, y); ?? ??? ??? ??? ??? ?break; ?? ??? ??? ??? ?default: ?? ??? ??? ??? ??? ?bClked = false; ?? ??? ??? ??? ??? ?break; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?if (bClked) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?afterMouseEvent(); ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ??? ?if (inpRec.EventType == KEY_EVENT)?? ?//按鍵事件 ?? ??? ??? ?{ ?? ??? ??? ??? ?onKeyDown(inpRec.Event.KeyEvent.wVirtualKeyCode); ?? ??? ??? ??? ?Sleep(100); ?? ??? ??? ?} ?? ??? ??? ?FlushConsoleInputBuffer(hIn); ?? ??? ?} ?? ??? ?setElapsedTime(); ?? ??? ?Sleep(50); ?? ?} ?? ?return 0; }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++文件IO流及stringstream流讀寫文件和字符串操作詳解
本文詳細(xì)介紹C++中的文件IO流和stringstream流的使用方法,包括文件的打開(kāi)、讀寫操作,以及字符串的輸入輸出、轉(zhuǎn)換等操作。同時(shí)提供實(shí)用的示例代碼和技巧,幫助讀者更好地掌握這兩種流的使用2023-04-04vs2022?qt環(huán)境搭建調(diào)試的方法步驟
最近net6和vs2022發(fā)布,本文就詳細(xì)的介紹一下vs2022?qt環(huán)境搭建調(diào)試的方法步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12C語(yǔ)言簡(jiǎn)明講解操作符++和--的使用方法
++和--運(yùn)算符分別是+=1和-=1的簡(jiǎn)寫。設(shè)計(jì)這樣兩個(gè)運(yùn)算符的本意是?便程序員,但i++和++i使?不恰當(dāng)有時(shí)候會(huì)造成混淆,反倒令剛?cè)腴T的C程序員有點(diǎn)混亂2022-04-04C++對(duì)cin輸入字符的判斷及分段函數(shù)處理方法示例
這篇文章主要介紹了C++對(duì)cin輸入字符的判斷及分段函數(shù)處理方法,結(jié)合實(shí)例形式分析了C++輸入判斷及處理相關(guān)操作技巧,需要的朋友可以參考下2017-09-09C++ 如何判斷四個(gè)點(diǎn)是否構(gòu)成正方形
這篇文章主要介紹了C++ 如何判斷四個(gè)點(diǎn)是否構(gòu)成正方形的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03