C++小遊戲-掃雷
阿新 • • 發佈:2020-12-12
前言
提示:本文是基於easyX圖形庫實現的,還有部分功能可以新增,僅適合新手參考。
提示:以下是本篇文章正文內容,下面案例可供參考
一、掃雷遊戲模式
在確定大小的矩形雷區中隨機佈置一定數量的地雷,玩家需要儘快找出雷區中的所有不是地雷的方塊,而不許踩到地雷。
遊戲的基本操作包括左鍵單擊和右鍵單擊。其中左鍵用於開啟安全的格子,推進遊戲進度;右鍵用於標記地雷,以輔助判斷。
左鍵單擊:在判斷出不是雷的方塊上按下左鍵,可以開啟該方塊。如果方塊上出現數字,則該數字表示其周圍3×3區域中的地雷數(一般為8個格子,對於邊塊為5個格子,對於角塊為3個格子。所以掃雷中最大的數字為8);如果方塊上為空(相當於0),則可以遞迴地開啟與空相鄰的方塊;如果不幸觸雷,則遊戲結束。
右鍵單擊:在判斷為地雷的方塊上按下右鍵,可以標記地雷(顯示為小紅旗)。重複一次或兩次操作可取消標記。
二、程式碼實現
1.繪製地圖場景
根據每一塊地區的資料進行圖形輸出。
程式碼如下(示例):
1 void drawmap(int map[][12],IMAGE *img) 2 { 3 int i, j; 4 for (i = 1; i <= 10; i++) 5 { 6 for (j = 0; j <= 10; j++) 7 { 8 int x = 50 * (i - 1);//得到位置 9 int y = 50 * (j - 1); 10 if (map[i][j]>25) 11 { 12 putimage(x, y, &img[9]);//標記flag 13 } 14 else 15 { 16 switch (map[i][j]) 17 { 18 case 9: 19 putimage(x, y, &img[11]);//輸出圖片雷 20 break;21 case 10: 22 putimage(x, y, &img[0]);//0 23 break; 24 case 11: 25 putimage(x, y, &img[1]);//1 26 break; 27 case 12: 28 putimage(x, y, &img[2]);//2 29 break; 30 case 13: 31 putimage(x, y, &img[3]);//3 32 break; 33 case 14: 34 putimage(x, y, &img[4]);//4 35 break; 36 case 15: 37 putimage(x, y, &img[5]);//5 38 break; 39 case 16: 40 putimage(x, y, &img[6]);//6 41 break; 42 case 17: 43 putimage(x, y, &img[7]);//7 44 break; 45 case 18: 46 putimage(x, y, &img[8]);//8 47 break; 48 default: 49 putimage(x, y, &img[10]);//地圖 50 break; 51 } 52 } 53 } 54 } 55 }
2.滑鼠點選
滑鼠左鍵點選翻開格子,右鍵點選標記flag,再次點選可以進行取消。
sum記錄翻開格子的數量,點選後對每個位置的資料進行加減操作。
程式碼如下(示例):
1 int mousedown(int map[][12]) 2 { 3 MOUSEMSG m; //定義滑鼠訊息變數 4 while (1) 5 { 6 //獲取滑鼠訊息 7 m = GetMouseMsg(); 8 int mi = m.x / 50 + 1; 9 int mj = m.y / 50 + 1; 10 11 //判斷滑鼠訊息 12 switch (m.uMsg) 13 { 14 case WM_LBUTTONDOWN: 15 if (map[mi][mj] > 9) //已翻開的情況 16 { 17 continue; 18 } 19 if (map[mi][mj] == 0) //如果點選為0,則翻開一片。 20 { 21 //使用遞迴函式 22 swap(map, mi, mj); 23 } 24 else 25 { 26 map[mi][mj] += 10; 27 sum += 1; 28 } 29 return map[mi][mj]; 30 break; 31 case WM_RBUTTONDOWN: 32 if (map[mi][mj] > 9&& map[mi][mj] < 25) //已翻開的情況 33 { 34 continue; 35 } 36 if (map[mi][mj] > 25) //再次點選取消flag 37 { 38 map[mi][mj] -= 30; 39 } 40 else 41 { 42 map[mi][mj] += 30; 43 } 44 return map[mi][mj]; 45 break; 46 } 47 } 48 }
3.遞迴
當我們點到為0的地區時,將會開啟周圍的部分地區,外圍為非0數或到達邊界,內部為0.
如圖:
程式碼如下(示例):
1 void swap(int map[][12],int mi,int mj) 2 { 3 map[mi][mj] = 10; 4 sum += 1; 5 for (int i = mi - 1; i <= mi + 1; i++) 6 { 7 for (int j = mj - 1; j <= mj + 1; j++) 8 { 9 //陣列下標不能越界 10 if (i >= 1 && i <= 10 && j >= 1 && j <= 10) 11 { 12 //翻開的只能是數字 13 if (map[i][j] < 9) 14 { 15 //如果為0,則進行遞迴。 16 if (map[i][j] == 0) 17 { 18 swap(map, i, j); 19 } 20 else 21 { 22 map[i][j] += 10; 23 sum += 1; 24 } 25 } 26 } 27 } 28 } 29 }
4.初始化遊戲
程式碼如下(示例):
1 void startgame() 2 { 3 initgraph(500, 500); //初始化地圖500x500 4 int map[12][12] = { 0 }; 5 int i,j,m,n; 6 //隨機函式種子 7 srand((unsigned int)time(NULL)); 8 //隨機生成10個雷 9 for (n = 0; n < 10;) 10 { 11 i = rand() % 10 + 1; //[1,10] 12 j = rand() % 10 + 1; 13 if (map[i][j] == 0) //排除本來就有雷的情況 14 { 15 map[i][j] = -1; //-1表示有雷 16 n++; 17 } 18 } 19 //產生數字 20 for (i = 1; i <= 10; i++) 21 { 22 for (j = 1; j <= 10; j++) 23 { 24 //排除是雷的情況 25 if (map[i][j] != -1) 26 { 27 for (m = i - 1; m <= i + 1; m++) //判斷周圍是否有雷 28 { 29 for (n = j - 1; n <= j + 1; n++) 30 { 31 if (map[m][n] == -1) 32 { 33 map[i][j]++; 34 } 35 } 36 } 37 } 38 } 39 } 40 IMAGE img[12]; //定義圖片變數 41 loadimage(&img[0], "E:\\C++ project\\minesweeping\\0.jpg", 50, 50); 42 loadimage(&img[1], "E:\\C++ project\\minesweeping\\1.gif", 50, 50);//載入圖片 43 loadimage(&img[2], "E:\\C++ project\\minesweeping\\2.gif", 50, 50); 44 loadimage(&img[3], "E:\\C++ project\\minesweeping\\3.gif", 50, 50); 45 loadimage(&img[4], "E:\\C++ project\\minesweeping\\4.gif", 50, 50); 46 loadimage(&img[5], "E:\\C++ project\\minesweeping\\5.gif", 50, 50); 47 loadimage(&img[6], "E:\\C++ project\\minesweeping\\6.gif", 50, 50); 48 loadimage(&img[7], "E:\\C++ project\\minesweeping\\7.gif", 50, 50); 49 loadimage(&img[8], "E:\\C++ project\\minesweeping\\8.gif", 50, 50); 50 loadimage(&img[9], "E:\\C++ project\\minesweeping\\flag.gif", 50, 50); 51 loadimage(&img[10], "E:\\C++ project\\minesweeping\\地圖.gif", 50, 50); 52 loadimage(&img[11], "E:\\C++ project\\minesweeping\\雷.gif", 50, 50); 53 while (1) 54 { 55 drawmap(map, img); 56 //點到地雷 57 if (mousedown(map)==9) 58 { 59 sum = 0; //重置判斷變數 60 drawmap(map, img); 61 MessageBox(hwnd,"你踩到雷了!","Game Over",MB_OK); 62 return; 63 } 64 //成功完成遊戲 65 if (sum == 90) 66 { 67 sum = 0; //重置判斷變數 68 drawmap(map, img); 69 MessageBox(hwnd, "你成功完成了遊戲!", "Game Over", MB_OK); 70 return; 71 } 72 } 73 }
5.main
程式碼如下(示例):
1 #include<iostream> 2 #include<time.h> 3 #include<graphics.h> //圖形庫標頭檔案 easyx 4 #include <conio.h> //呼叫_getch函式 5 using namespace std; 6 HWND hwnd; 7 int sum = 0;//用於表示目前已經點開的格子數 8 //宣告函式 9 void drawmap(int map[][12], IMAGE* img); 10 int mousedown(int map[][12]); 11 void swap(int map[][12], int mi, int mj); 12 //初始化遊戲 13 14 //繪製地圖 15 16 //滑鼠點選 17 18 //遞迴函式 19 20 int main() 21 { 22 while (1) 23 { 24 startgame(); 25 if (MessageBox(hwnd, "再來一次", "結束遊戲", MB_YESNO)==IDNO) 26 break; 27 } 28 //_getch(); //防止閃屏 29 closegraph(); 30 return 0; 31 }