C++學習(二十二)(C語言部分)之 項目掃雷實例


一、新建項目

 

 

 

 二、新建源文件

main.cpp和mining,cpp

 

 

 

 

 

 三、新建頭文件

mining.h

 

 

 

 四、圖片資源添加

 

 

 

 

 

 添加完成后會在頭文件里面生成一個.h頭文件,用來調用資源

 打開之后可以看到,對每一個資源文件進行了定義

這里面的順序和你添加文件時的順序是一樣的,是根據你添加資源的先后順序進行排列定義的

 

 在資源文件夾下回顯示添加的資源

 

 

 五、VS安裝圖形庫

 

 

 安裝完成后重啟VS之后就可以在項目中調用圖形庫的頭文件----->  #include<graphics.h>  //圖形庫的頭文件

 接下來是相關代碼:

 

頭文件部分:

mining.h文件

 1 #include<time.h> //該種方式引用的頭文件是c自帶的頭文件
 2 #include<stdlib.h>
 3 #include<graphics.h>  //圖形庫的頭文件
 4 
 5 #define MAP_WIDTH 500 //定義地圖寬度 宏定義方式 即MAP_WIDTH就等於550
 6 
 7 #define MAP_HEIGHT 550 //定義地圖的高度
 8 
 9 #define EACH_SIZE 50 //每一個格子的大小
10 
11 #define MAX_X (MAP_WIDTH/EACH_SIZE) //計算每一行有多少個
12 
13 #define MAX_Y (MAP_HEIGHT/EACH_SIZE) //計算每一列有多少個
14 
15 #define MINE_COUNT 20 //雷的個數
16 
17 //1.初始化地圖 
18 void InitMap(); //定義一個函數 是一個模塊 只做屬於自己的事情 19 
20 //2.實現雷的周圍加一
21 void ChangeState(int x,int y); 22 
23 //3.判斷是否越界
24 int IsPosOk(int x, int y); 25 
26 //4.貼圖
27 void DrawMap(); 28 
29 //5.顯示信息
30 void ShowInfo(); 31 
32 //6.實現鼠標點擊 ** 還未實現
33 int IsOpenMine(); 34 
35 //7.進行遞歸翻開格子 ** 還未實現
36 void OpenZeroRecursively(int x,int y); 37 
38 //8.翻開所有格子
39 void OpenAll(); 40 
41 //9.判斷輸贏 點擊到地雷就輸了 ** 還未實現
42 void RenGame();

 

源文件部分:

main.cpp

 1 #include"mining.h"
 2 #include<stdio.h>
 3 
 4 int main()  5 {  6     initgraph(MAP_WIDTH, MAP_HEIGHT);//畫出地圖窗口
 7 
 8     InitMap();//初始換函數
 9 
10     DrawMap();//貼圖函數
11  getchar(); 12 
13     OpenAll();//翻開所有格子
14     DrawMap();//貼圖
15 
16  getchar(); 17     return 0; 18     getchar();//防止結果閃退
19 }

 

mining.cpp

 1 #include"mining.h"  //這種方式引用的頭文件是我們自己定義的
 2 #include"resource.h"
 3 
 4 int Map[MAX_X][MAX_Y]; //定義一個二維數組 制作地圖
 5 
 6 int nCountOpen;  //打開格子的個數
 7 
 8 int nCountFlag;  //標記的個數
 9 
 10 void InitMap()  //第一個函數 初始化函數
 11 {  12     //1.初始化數組
 13     for (int i = 0; i < MAX_X; i++)  14  {  15         for (int j = 0; j < MAX_Y; j++)  16  {  17             Map[i][j] = 0;  18  }  19  }  20 
 21     nCountOpen = 0;  //初始化
 22 
 23     nCountFlag = 0;  //初始化  24 
 25     //2.埋地雷---> 地雷是隨機的
 26 
 27     srand((unsigned int)time(0));  // 種下隨機數種子
 28 
 29     int x, y;  30 
 31     int nCount=0;  //統計埋雷的個數  32 
 33     //開始埋雷
 34     while (nCount<MINE_COUNT)  //當前埋雷的個數 小於埋雷的最大個數 就一直循環
 35  {  36         x = rand() % MAX_X;  // ? %10==0~9 rand 獲取隨機數
 37 
 38         y = rand() % (MAX_Y - 1) + 1;  // 
 39 
 40         if (-1 == Map[x][y])  //-1 表示地雷
 41         {//隨機下標是一個地雷
 42             continue;  //跳過本次循環 不是結束循環(break)
 43  }  44         Map[x][y] = -1;  // 埋雷
 45 
 46         nCount++;  //埋雷的個數加一
 47  }  48 
 49     //實現地雷九宮格周圍加一
 50     for (int i = 0; i < MAX_X; i++)  51  {  52         for (int j = 1; j < MAX_Y; j++)  //因為第一行沒有雷 我們是用來顯示信息的 所以不能從0開始
 53  {  54             if (-1 == Map[i][j])  //判斷是不是一顆地雷 -1寫在左邊的原因-->左值 Map[i][j]=-1這種形式是錯誤的
 55  {  56                 ChangeState(i, j);  //下標
 57  }  58  }  59  }  60 }  61 
 62 void ChangeState(int x, int y)  //第二個函數 實現雷的周圍加一 九宮格范圍
 63 {  64     for (int i = x - 1; i <= x + 1; i++)  65  {  66         for (int j = y - 1; j <= y + 1; j++)  67  {  68             if (-1 == Map[i][j]||IsPosOk(i,j)==0 ) //這個位置是一顆地雷並且判斷是否越界
 69  {  70                 continue;   //跳出本次循環
 71  }  72             Map[i][j]+=1;  //和Map[i][j]++;是一樣的
 73  }  74  }  75 }  76 
 77 int IsPosOk(int x, int y)  //第三個函數 判斷當前的下標是不是越界了
 78 {  79     //邏輯表達式的值 0和1
 80     return (x >= 0 && x <= MAX_X&&y <= 1 && y < MAX_Y);  //越界返回0 沒越界返回1
 81 }  82 
 83 void DrawMap()  //第四個函數 對地圖貼圖貼圖
 84 {  85  IMAGE img;  86 
 87     for (int i = 0; i < MAX_X; i++)  88  {  89         for (int j = 1; j < MAX_Y; j++)  90  {  91             if (Map[i][j] < 9)  //雷的周圍1最大是8個不會超過九 小於9 說明格子沒有被翻開
 92  {  93                 loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG13), EACH_SIZE, EACH_SIZE);  //L寬字節 jpg13是沒有翻開的情況的圖片
 94  }  95             else  //已經被翻開
 96             {   //翻開一個格子 讓這個格子+10 表示已經被翻開
 97                 if (Map[i][j] >= 11 && Map[i][j] <= 18)  //11~18表示1~8
 98  {  99                     loadimage(&img, L"JPG", MAKEINTRESOURCE(IDR_JPG1 + Map[i][j] - 11, EACH_SIZE, EACH_SIZE));  //通過這個算法 判斷貼哪一張圖片
100  } 101                 else if (Map[i][j] == 9)  //9-10==-1 -1是地雷
102  { 103                     loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG10), EACH_SIZE, EACH_SIZE);  //貼地雷圖片
104  } 105                 else if (Map[i][j] == 10)  //10-10==0 0表示空白
106  { 107                     loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG11), EACH_SIZE, EACH_SIZE);  //貼空地圖片
108  } 109                 else
110  { 111                     loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG9), EACH_SIZE, EACH_SIZE);  //貼標記圖片
112  } 113  } 114             putimage(i*EACH_SIZE, j*EACH_SIZE, &img); 115  } 116  } 117  ShowInfo(); 118 } 119 
120 void ShowInfo()  //第五個函數 顯示信息
121 { 122     //埋雷的個數 打開的個數 標記的個數 123     //設置字體的樣式
124     settextstyle(20, 20, L"wingding.ttf");  //字體樣式標號 125     
126     //背景顏色
127  setbkmode(TRANSPARENT); 128 
129     //字體顏色
130  settextcolor(YELLOW); 131     
132     //設置字體的位置
133     WCHAR szOpen[32]; 134     WCHAR szFlag[32]; 135     WCHAR szAllMine[32]; 136 
137       //字符串格式化 138       //與printf scanf類似 
139     wsprintf(szAllMine, L"埋雷:%d", MINE_COUNT);//埋雷:20 把“埋雷”這個字符串放到szAllMine里面 格式化成字符串類型
140     wsprintf(szOpen, L"打開:%d", nCountOpen); 141     wsprintf(szFlag, L"標記:%d", nCountFlag); 142     
143       //調整坐標
144     outtextxy(20, 20, szAllMine); 145     outtextxy(190, 20, szOpen); 146     outtextxy(350, 20, szFlag); 147 
148 } 149 
150 
151 
152 
153 
154 
155 void OpenZeroRecursively(int x, int y)  //第七個函數 進行遞歸翻開格子
156 { 157 
158 } 159 
160 void OpenAll()  //第八個函數 翻開所有格子
161 { 162     for (int i = 0; i < MAX_X; i++) 163  { 164         for (int j=1;j<MAX_Y;j++) 165  { 166             if (Map[i][j] < 9) 167  { 168                 Map[i][j] += 10; 169  } 170  } 171  } 172 } 173 
174 void RenGame()  //第九個函數 判斷輸贏
175 { 176 
177 }

 

注:

設置字體樣式:

 

 

 

 

 

目前實現的結果如下:

 

之后的以后有機會寫好之后再補充

 

2019-03-20   13:09:47

 

之前寫的代碼並不完整,而且還有一些錯誤,在經過一番學習添加修改后,

最終添加修改完善后的代碼如下所示:

 

  1 mining.h文件
  2 #include<time.h> //該種方式引用的頭文件是c自帶的頭文件
  3 #include<stdlib.h>
  4 #include<graphics.h>  //圖形庫的頭文件
  5 
  6 #define MAP_WIDTH 500 //定義地圖寬度  宏定義方式  即MAP_WIDTH就等於550
  7 
  8 #define MAP_HEIGHT 550 //定義地圖的高度
  9 
 10 #define EACH_SIZE 50   //每一個格子的大小
 11 
 12 #define MAX_X (MAP_WIDTH/EACH_SIZE) //計算每一行有多少個
 13 
 14 #define MAX_Y (MAP_HEIGHT/EACH_SIZE) //計算每一列有多少個
 15 
 16 #define MINE_COUNT 5//雷的個數
 17 
 18 //1.初始化地圖  
 19 void InitMap(); //定義一個函數 是一個模塊 只做屬於自己的事情
 20 
 21 //2.實現雷的周圍加一
 22 void ChangeState(int x,int y);
 23 
 24 //3.判斷是否越界
 25 int IsPosOk(int x, int y);
 26 
 27 //4.貼圖
 28 void DrawMap();
 29 
 30 //5.顯示信息
 31 void ShowInfo();
 32 
 33 //6.實現鼠標點擊  
 34 int IsOpenMine();
 35 
 36 //7.進行遞歸翻開格子 
 37 void OpenZeroRecursively(int x,int y);  
 38 
 39 //8.翻開所有格子
 40 void OpenAll();
 41 
 42 //9.判斷輸贏 點擊到地雷就輸了 
 43 void RenGame();
 44 
 45 //以上是對使用函數的一個聲明
 46 
 47 
 48 mining.cpp文件
 49 #include"mining.h"  //這種方式引用的頭文件是我們自己定義的
 50 #include"resource.h"
 51 
 52 int Map[MAX_X][MAX_Y]; //定義一個二維數組 制作地圖
 53 
 54 int nCountOpen;  //打開格子的個數
 55 
 56 int nCountFlag;  //標記的個數
 57 
 58 void InitMap()  //第一個函數 初始化函數
 59 {
 60     //1.初始化數組
 61     for (int i = 0; i < MAX_X; i++)
 62     {
 63         for (int j = 0; j < MAX_Y; j++)
 64         {
 65             Map[i][j] = 0;
 66         }
 67     }
 68 
 69     nCountOpen = 0;  //初始化
 70 
 71     nCountFlag = 0;  //初始化
 72 
 73     //2.埋地雷--->  地雷是隨機的
 74 
 75     srand((unsigned int)time(0));  // 種下隨機數種子
 76 
 77     int x, y;
 78 
 79     int nCount=0;  //統計埋雷的個數
 80 
 81     //開始埋雷
 82     while (nCount<MINE_COUNT)  //當前埋雷的個數 小於埋雷的最大個數 就一直循環
 83     {
 84         x = rand() % MAX_X;  // ? %10==0~9  rand 獲取隨機數
 85 
 86         y = rand() % (MAX_Y - 1) + 1;  // 
 87 
 88         if (-1 == Map[x][y])  //-1 表示地雷
 89         {//隨機下標是一個地雷
 90             continue;  //跳過本次循環 不是結束循環(break)
 91         }
 92         Map[x][y] = -1;  // 埋雷
 93 
 94         nCount++;  //埋雷的個數加一
 95     }
 96 
 97     //實現地雷九宮格周圍加一
 98     for (int i = 0; i < MAX_X; i++)  
 99     {
100         for (int j = 1; j < MAX_Y; j++)  //因為第一行沒有雷 我們是用來顯示信息的 所以不能從0開始
101         {
102             if (-1 == Map[i][j])  //判斷是不是一顆地雷  -1寫在左邊的原因-->左值  Map[i][j]=-1這種形式是錯誤的
103             {
104                 ChangeState(i, j);  //下標
105             }
106         }
107     }    
108 }
109 
110 void ChangeState(int x, int y)  //第二個函數 實現雷的周圍加一 九宮格范圍
111 {
112     for (int i = x - 1; i <= x + 1; i++)
113     {
114         for (int j = y - 1; j <= y + 1; j++)
115         {
116             if (-1 == Map[i][j]||IsPosOk(i,j)==0 ) //這個位置是一顆地雷並且判斷是否越界
117             {
118                 continue;   //跳出本次循環
119             }
120             Map[i][j]+=1;  //和Map[i][j]++;是一樣的
121         }
122     }
123 }
124 
125 int IsPosOk(int x, int y)  //第三個函數 判斷當前的下標是不是越界了
126 {
127     //邏輯表達式的值 0和1
128     return (x >= 0 && x < MAX_X &&y >= 1 && y < MAX_Y);  //越界返回0 沒越界返回1
129 }
130 
131 void DrawMap()  //第四個函數 對地圖貼圖貼圖
132 {
133     IMAGE img;
134     BeginBatchDraw();  //批量繪圖  解決閃屏問題
135 
136     cleardevice();
137     
138 
139     for (int i = 0; i < MAX_X; i++)
140     {
141         for (int j = 1; j < MAX_Y; j++)
142         {
143             if (Map[i][j] < 9)  //雷的周圍1最大是8個不會超過九  小於9 說明格子沒有被翻開
144             {
145                 loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG13), EACH_SIZE, EACH_SIZE);  //L寬字節 jpg13是沒有翻開的情況的圖片
146             }
147             else  //已經被翻開
148             {   //翻開一個格子 讓這個格子+10 表示已經被翻開
149                 if (Map[i][j] >= 11 && Map[i][j] <= 18)  //11~18表示1~8
150                 {
151                     loadimage(&img, L"JPG", MAKEINTRESOURCE(IDR_JPG1 + Map[i][j] - 11), EACH_SIZE, EACH_SIZE);  //通過這個算法 判斷貼哪一張圖片
152                 }
153                 else if (Map[i][j] == 9)  //9-10==-1  -1是地雷
154                 {
155                     loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG10), EACH_SIZE, EACH_SIZE);  //貼地雷圖片
156                 }
157                 else if (Map[i][j] == 10)  //10-10==0  0表示空白
158                 {
159                     loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG12), EACH_SIZE, EACH_SIZE);  //貼空地圖片
160                 }
161                 else
162                 {
163                     loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG9), EACH_SIZE, EACH_SIZE);  //貼標記圖片
164                 }
165             }
166             putimage(i*EACH_SIZE, j*EACH_SIZE, &img);
167         }
168     }
169     ShowInfo();
170     EndBatchDraw();
171 }
172 
173 void ShowInfo()  //第五個函數  顯示信息
174 {
175     //埋雷的個數  打開的個數  標記的個數
176     //設置字體的樣式
177     settextstyle(20, 20, L"wingding.ttf");  //字體樣式標號
178     
179     //背景顏色
180     setbkmode(TRANSPARENT);
181 
182     //字體顏色
183     settextcolor(YELLOW);
184     
185     //設置字體的位置
186     WCHAR szOpen[32];
187     WCHAR szFlag[32];
188     WCHAR szAllMine[32];
189 
190       //字符串格式化
191       //與printf  scanf類似 
192     wsprintf(szAllMine, L"埋雷:%d", MINE_COUNT);//埋雷:20  把“埋雷”這個字符串放到szAllMine里面 格式化成字符串類型
193     wsprintf(szOpen, L"打開:%d", nCountOpen);
194     wsprintf(szFlag, L"標記:%d", nCountFlag);
195     
196       //調整坐標
197     outtextxy(20, 20, szAllMine);
198     outtextxy(190, 20, szOpen);
199     outtextxy(350, 20, szFlag);
200 
201 }
202 
203 int IsOpenMine()
204 {
205     MOUSEMSG m = { 0 };//保存鼠標消息
206 
207     while (1)  //死循環
208     {
209         m = GetMouseMsg();//獲取鼠標消息
210         switch (m.uMsg)
211         {
212         case WM_LBUTTONDOWN:  //鼠標左鍵按下
213             if (Map[m.x / EACH_SIZE][m.y / EACH_SIZE] == -1)  //點擊到了地雷
214             {
215                 Map[m.x / EACH_SIZE][m.y / EACH_SIZE] += 10;  //int a=5; a+=10  a=a+10 翻開格子+10 表示已經翻開
216                 return 0;  //返回0說明點擊的是一顆雷
217             }
218             else if (Map[m.x / EACH_SIZE][m.y / EACH_SIZE] == 0)  //點擊到的是一個空地
219             {
220                 OpenZeroRecursively(m.x / EACH_SIZE, m.y / EACH_SIZE);
221                 return 1;
222             }
223             else if (Map[m.x / EACH_SIZE][m.y / EACH_SIZE] > 0 && Map[m.x / EACH_SIZE][m.y / EACH_SIZE] < 9)  //表示 點擊的位置的值是1~8  9表示的是已經被翻開的
224             {
225                 Map[m.x / EACH_SIZE][m.y / EACH_SIZE] += 10;
226                 nCountOpen++;
227                 return 1;
228             }
229             
230             break;
231         case WM_RBUTTONDOWN:
232             if (Map[m.x / EACH_SIZE][m.y / EACH_SIZE] < 9)
233             {
234                 Map[m.x / EACH_SIZE][m.y / EACH_SIZE ]+= 100;  //加多少都可以 只是一個標記
235                 nCountFlag++;
236             }
237             else if (Map[m.x / EACH_SIZE][m.y / EACH_SIZE]>19)
238             {
239                 Map[m.x / EACH_SIZE][m.y / EACH_SIZE] -= 100;
240                 nCountFlag--;
241             }
242             return 1;
243         }
244     }
245 }
246 
247 void OpenZeroRecursively(int x, int y)  //第七個函數 進行遞歸翻開格子
248 {
249     Map[x][y] += 10;
250     nCountOpen++;
251     for (int i = x - 1; i <= x + 1; i++)
252     {
253         for (int j = y - 1; j <= y + 1; j++)
254         {
255             if (IsPosOk(i, j)==0)
256             {
257                 continue;
258             }
259             if (0==Map[i][j])
260             {
261                 OpenZeroRecursively(i, j);
262             }
263             if (Map[i][j] < 9)
264             {
265                 Map[i][j] += 10;
266                 nCountOpen++;
267             }
268         }
269     }
270 }
271 
272 void OpenAll()  //第八個函數 翻開所有格子  游戲結束
273 {
274     for (int i = 0; i < MAX_X; i++)
275     {
276         for (int j=1;j<MAX_Y;j++)
277         {
278             if (Map[i][j] < 9)
279             {
280                 Map[i][j] += 10;
281             }
282         }
283     }
284 }
285 
286 void RenGame()  //第九個函數 判斷輸贏
287 {
288     while (nCountOpen<((MAX_X*(MAX_Y-1))-MINE_COUNT))  //100個格子 有20個地雷  10*111=110   10*10
289     {
290         if (IsOpenMine()==0)
291         {
292             OpenAll();
293             DrawMap();
294             MessageBox(GetHWnd(), L"你太菜了!再去修煉吧!", L"提示",MB_OK);
295             return ;  //結束函數
296         }
297         DrawMap();
298     }
299     DrawMap();
300     MessageBox(GetHWnd(), L"恭喜你,你贏了", L"提示", MB_OK);
301 }
302 
303 
304 
305 main.cpp文件
306 #include"mining.h"
307 #include<stdio.h>
308 
309 int main()
310 {
311     initgraph(MAP_WIDTH, MAP_HEIGHT);//畫出地圖窗口
312 
313     InitMap();//初始換函數
314     DrawMap();//貼圖
315 
316     while (true)  //循環游戲
317     {
318         RenGame();
319         InitMap();
320         DrawMap();
321     }
322     getchar();
323     return 0;
324 }

 

 

 

2019-03-20  23:57:46

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM