C++ 掃雷遊戲實現
阿新 • • 發佈:2019-01-11
C++ 掃雷遊戲
這個星期在嘗試著自己寫一個掃雷遊戲。功能基本和windows下的功能差不多。左鍵單擊翻開一個格子,如果沒有雷則顯示其周圍格子中含有雷的個數,沒有周圍的沒有雷的話,那麼就擴充套件空白塊。
擴充套件空白塊的步驟為:1、翻開一個格子,如果檢測有雷,則退出遊戲;2、如果檢測沒有雷,那麼就檢測其周圍的八個格子,如果周圍有雷的話,顯示含有雷的個數,跳到第四步;3、沒有周圍都沒有雷的話,翻開這個格子,並且對周圍的八個格子重複第二步。4、進行下一次滑鼠點選檢測。
掃雷遊戲的難點在於如何擴充套件空白塊和捕捉到滑鼠的點選操作。
捕捉滑鼠的點選操作:注意在控制檯視窗中,直接執行這個程式是不能捕捉到滑鼠的點選操作的,需要在開啟的那個控制檯視窗上面那個白色邊框,右鍵滑鼠選擇屬性,然後關閉快速編輯選項,之後就可以正常的捕捉到滑鼠的點選操作了。
HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hin = GetStdHandle(STD_INPUT_HANDLE);
COORD coord, pos;
INPUT_RECORD mouseRec;
DWORD res;
ReadConsoleInput(hin, &mouseRec, 1, &res); //該函式用於讀取滑鼠和鍵盤事件
if (mouseRec.EventType == MOUSE_EVENT) //檢查是否有滑鼠的按鍵按下
{
cout << "滑鼠" << endl;
if (mouseRec.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) //最左邊的按鍵按下
{
cout << "左" << endl;
}
if (mouseRec.Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED) //最右邊的按鍵按下
{
cout << "右" << endl;
cout << "|>";
}
}
空白塊的擴充套件:一般有兩種方法遞迴和有一個標誌陣列。我採用的是遞迴實現的。
/*用於檢測各點座標點周圍的八個格子種地雷的個數*/
int detect_sweeper_eight(int a, int b, int init_p[], vector<vector<int>> map_sweeper)
{
int temp_sweeper_count = 0;
for (int i = a - 1; i < a + 2; ++i) //統計點開的格子周圍的地雷的個數
for (int j = b - 1; j < b + 2; ++j) //檢測雷區這一塊還需要進行相應的更改
{
if (i<0 || j<0 || i>init_p[0] - 1 || j>init_p[1] - 1)
{
temp_sweeper_count = temp_sweeper_count;
}
else
{
if (map_sweeper[i][j] == 1)
temp_sweeper_count++;
}
}
return temp_sweeper_count;
}
/* 這個遊戲中需要對已經翻開的格子進行做了標記,這個是重點,
第一次因為沒有對已經翻開的格子進行標記,導致程式進入了死迴圈;
第二次加入了標記,能夠正確的擴充套件空白塊,但是一直在空白塊之間迴圈,
後來發現是那個用來標識地雷的陣列沒有進行引用傳遞。用的是值傳遞的方式,這樣導致了無限迴圈,但是程式不會退出*/
void detect_sweeper(int a, int b, int init_p[], vector<vector<int>> map_sweeper, vector<vector<int>> &map_sweeper_flag)
{
int sweeper_count = 0;
int map_a = a + init_p[2];
int map_b = b + init_p[3];
sweeper_count = detect_sweeper_eight(a, b, init_p, map_sweeper);
if (!sweeper_count) //如果點開的格子周圍都沒有地雷的話,那麼就把這九個空格給消去
{
locate(map_b, map_a);
cout << " ";
map_sweeper_flag[a][b] = 0;
for (int i = a - 1; i < a + 2; ++i)
for (int j = b - 1; j < b + 2; ++j)
{
if ((i == a && j == b) || i<0 || j<0 || i>init_p[0] - 1 || j>init_p[1] - 1) //是中心點、到達邊界
{
}
else
{
if (map_sweeper_flag[i][j] == 0){} //已經翻開的格子進行做了標記,這個是重點,之前不會退出迴圈,後來發現是那個用來標識地雷的陣列沒有進行引用傳遞。
else //用的是值傳遞的方式,這樣導致了無限迴圈
{
detect_sweeper(i, j, init_p, map_sweeper, map_sweeper_flag);
}
}
}
}
else
{
locate(map_b, map_a);
cout << sweeper_count;
map_sweeper_flag[a][b] = 0;
}
}
掃雷遊戲最主要的就是這兩個部分了。下面是結果截圖: