命令行版扫雷,方向键控制

以前写的一个命令行版扫雷,今天翻出来整理了下拿出来,写的有点乱=  =

Codeblocks、VC6.0编译通过,只能在windows下运行,Linux不支持。不嫌蛋疼的可以用curses库来实现下Linux版本。。。

运行效果,比较简陋:

程序还是比较简单的,那这里就直接丢代码了:

  1 /**
  2  * 命令行版扫雷,方向键控制
  3  * 作者:evangwt
  4  */
  5 #include <stdio.h>
  6 #include <stdlib.h>
  7 #include <conio.h>
  8 #include <time.h>
  9 #include <windows.h>
 10 #define bool int
 11 #define true 1
 12 #define false 0
 13 #define ROW             9
 14 #define COLUMN          9
 15 #define TOTAL_MINE     10
 16 // ASCII码
 17 #define MINE            42
 18 #define ESC             27
 19 #define ENTER           13
 20 #define SPACE           32
 21 #define UP              72
 22 #define DOWN            80
 23 #define LEFT            75
 24 #define RIGHT           77
 25 typedef struct cursorPos_st
 26 {
 27     int x;
 28     int y;
 29 } cursorPos_t;
 30 
 31 typedef struct block_st
 32 {
 33     bool bCover;
 34     int nMine;
 35 } block_t;
 36 
 37 cursorPos_t cursorPos[ROW][COLUMN]; // 光标位置数组
 38 
 39 block_t mine[ROW][COLUMN];          // 扫雷地图数组
 40 
 41 int nLeftBlock = ROW * COLUMN;      // 剩余的格数
 42 
 43 int index_x = 0, index_y = 0;       // 光标在光标位置数组、地图数组中的下标
 44 
 45 void setColor(unsigned short Color);
 46 
 47 void welcome();
 48 
 49 void init();
 50 
 51 void count();                       // 计算附近雷数
 52 
 53 void get();                         // 获取键盘输入
 54 
 55 void gotoPos(int y, int x);
 56 
 57 void move(int y, int x);            // 移动当前光标位置
 58 
 59 bool check(int y, int x);           // 检测是否踩雷
 60 
 61 void print();                       // 输出扫雷界面
 62 
 63 void over(char *str);               // 游戏结束
 64 
 65 
 66 int main()
 67 {
 68     setColor(160);
 69     system("cls");
 70     welcome();
 71     init();
 72     count();
 73     print();
 74     /*颜色测试
 75     int i = 0;
 76     for(i = 0; i < 256; ++i){
 77         setColor(i);
 78         system("cls");
 79         print();
 80         gotoPos(0, 0);
 81         printf("%d", i);
 82         Sleep(100);
 83         getch();
 84     }
 85     */
 86     for (;;)
 87     {
 88         gotoPos(cursorPos[index_y][index_x].y, cursorPos[index_y][index_x].x);
 89         get();
 90     }
 91     return 0;
 92 }
 93 
 94 void setColor(unsigned short Color)
 95 {
 96     HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
 97     SetConsoleTextAttribute(hCon, Color);
 98 };
 99 
100 void init()
101 {
102     int i = 0, j = 0;
103     int nMine = TOTAL_MINE;             // 初始化地雷总数
104     srand((unsigned int)time(NULL));
105     // 初始化地雷地图数组
106     for (i = 0; i < ROW; ++i)
107     {
108         for (j = 0; j < COLUMN; ++j)
109         {
110             mine[i][j].bCover = true;
111             mine[i][j].nMine = 0;
112         }
113     }
114     // 放置地雷
115     while (nMine)
116     {
117         //printf("%d\n", nMine);
118         i = rand() % ROW;
119         j = rand() % COLUMN;
120         if (mine[i][j].nMine == 0)
121         {
122             mine[i][j].nMine = -1;    // -1为地雷
123             --nMine;
124         }
125     }
126 
127     // 初始化光标位置数组
128     for (i = 0; i < ROW; ++i)
129     {
130         for (j = 0; j < COLUMN; ++j)
131         {
132             cursorPos[i][j].x = j * 6 + 3;
133             cursorPos[i][j].y = i * 2 + 1;
134             //printf("%d,%d;", cursorPos[i][j].x, cursorPos[i][j].y);
135         }
136     }
137 }
138 
139 void count()
140 {
141     int i = 0, j = 0, m = 0, n = 0;
142     int nMine = 0;                                 // 每个格子周围的雷数
143     for (i = 0; i < ROW; ++i)
144     {
145         for (j = 0; j < COLUMN; ++j)
146         {
147             if (mine[i][j].nMine == -1)
148                 continue;
149             // 8方向
150             nMine = 0;
151             for (m = -1; m <= 1; ++m)
152             {
153                 if (i + m < 0 || i + m >= ROW)      // 行溢出
154                 {
155                     continue;
156                 }
157                 for (n = -1; n <= 1; ++n)
158                 {
159                     if (j + n < 0 || j + n >= COLUMN)// 列溢出
160                     {
161                         continue;
162                     }
163                     if (mine[i + m][j + n].nMine == -1)
164                     {
165                         ++nMine;
166                     }
167                 }
168             }
169             mine[i][j].nMine = nMine;
170         }
171     }
172 }
173 
174 void get() {
175     bool lose;
176     int key1 = getch();
177     if (key1 == 224)                    // 方向键两个字节,第一个字节ASCII 224
178     {
179         int key2 = getch();
180         switch (key2)
181         {
182         case UP:
183             move(index_y - 1, index_x);
184             break;
185         case DOWN:
186             move(index_y + 1, index_x);
187             break;
188         case LEFT:
189             move(index_y, index_x - 1);
190             break;
191         case RIGHT:
192             //printf("right\n");
193             move(index_y, index_x + 1);
194             break;
195         default:
196             break;
197         }
198     }
199     else
200     {
201         switch (key1)
202         {
203         case ENTER:
204         case SPACE:
205             lose = check(index_y, index_x);
206             system("cls");
207             print();
208             if (lose)
209             {
210                 printf("|              诶哟我去,踩到一坨热翔! =。。=        |\n");
211                 printf("|                 按\"r\"重玩,其他键继续。             |\n");
212                 printf("[%c]-------------------------------------------------[%c]\n", MINE, MINE);
213                 Sleep(1000);
214                 char key3 = getch();
215                 if (key3 == 'r' || key3 == 'R')
216                 {
217                     setColor(160);
218                     init();
219                     count();
220                     print();
221                 }
222             }
223             else if (nLeftBlock > TOTAL_MINE)
224             {
225                 printf("|                     哎哟,不错哦~ = v =             |\n");
226                 printf("[%c]-------------------------------------------------[%c]\n", MINE, MINE);
227             }
228             else
229             {
230                 printf("|                    哟,居然赢了! =。。=            |\n");
231                 printf("|                  按\"r\"重玩,其他键继续。            |\n");
232                 printf("[%c]-------------------------------------------------[%c]\n", MINE, MINE);
233                 Sleep(1000);
234                 char key3 = getch();
235                 if (key3 == 'r' || key3 == 'R')
236                 {
237                     setColor(160);
238                     init();
239                     count();
240                     print();
241                 }
242             }
243             break;
244         case ESC:
245             system("cls");
246             over("\t\t\t\t\t白白~\n\n\n\n\n\n\n\n");
247         default:
248             break;
249         }
250     }
251 }
252 
253 void gotoPos(int y, int x)
254 {
255     COORD c;
256     c.X = x;
257     c.Y = y;
258     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
259 }
260 
261 void move(int y, int x)
262 {
263     if ((x >= 0 && x < COLUMN) && (y >= 0 && y < ROW))
264     {
265         gotoPos(cursorPos[y][x].y, cursorPos[y][x].x);
266         index_x = x;
267         index_y = y;
268     }
269 }
270 
271 bool check(int y, int x)
272 {
273     int i = 0, j = 0;
274     // 下标溢出
275     if (x < 0 || x >= COLUMN || y < 0 || y >= ROW)
276     {
277         return false;
278     }
279     // 翻开选中的格子
280     mine[y][x].bCover = false;
281     // 踩中地雷
282     if (mine[y][x].nMine == -1)
283     {
284         mine[y][x].nMine = 9;
285         return true;
286     }
287 
288     // 展开连片空格
289     if (mine[y][x].nMine > 0 && mine[y][x].nMine < 9)
290     {
291         return false;
292     }
293     for (i = -1; i <= 1; ++i)
294     {
295         if (y + i < 0 || y + i >= ROW)               // 行溢出
296         {
297             continue;
298         }
299         for (j = -1; j <= 1; ++j)
300         {
301             if (x + j < 0 || x + j >= COLUMN)        // 列溢出
302             {
303                 continue;
304             }
305             if (mine[y + i][x + j].bCover)
306             {
307                 mine[y + i][x + j].bCover = false;
308                 check(y + i, x + j);
309             }
310         }
311     }
312     return false;
313 }
314 
315 void print()
316 {
317     system("cls");
318     char help0[] = "←↑↓→";
319     char help1[] = "移动光标";
320     char help2[] = "空格\\回车";
321     char help3[] = "  挖雷";
322     char help4[] = "Esc 退出";
323     gotoPos(4, 62);
324     printf("%s", help0);
325     gotoPos(6, 62);
326     printf("%s", help1);
327     gotoPos(9, 62);
328     printf("%s", help2);
329     gotoPos(11, 62);
330     printf("%s", help3);
331     gotoPos(14, 62);
332     printf("%s", help4);
333 
334     gotoPos(0, 0);
335     int i = 0, j = 0, k = 0;
336     nLeftBlock = 0;
337     printf("[M]---");
338     for (k = 1; k < COLUMN - 1; ++k)
339     {
340         printf("+-----");
341     }
342     printf("+---[I]\n");
343     for (i = 0; i < ROW; ++i)
344     {
345         for (j = 0; j < COLUMN; ++j)
346         {
347             if (mine[i][j].bCover)
348             {
349                 ++nLeftBlock;
350                 printf("|  %c  ", 1);
351             }
352             else if (mine[i][j].nMine == -1 || mine[i][j].nMine == 9)
353             {
354                 printf("|  %c  ", MINE);
355             }
356             else if (mine[i][j].nMine == 0)
357             {
358                 printf("|  %c  ", ' ');
359             }
360             else
361             {
362                 printf("|  %d  ", mine[i][j].nMine);
363             }
364         }
365         printf("|\n");
366         if (i < ROW - 1)
367         {
368             for (k = 0; k < COLUMN; ++k)
369             {
370                 printf("+-----");
371             }
372             printf("+\n");
373         }
374     }
375     printf("[N]---");
376     for (k = 1; k < COLUMN - 1; ++k)
377     {
378         printf("+-----");
379     }
380     printf("+---[E]\n");
381 }
382 
383 void welcome() {
384     int i = 0;
385     char words0[] = "《屌丝扫雷》";
386     char words1[] = "";
387     char words2[] = "命令行版本";
388     char words3[] = "版权所有 evangwt,谢谢 (=v = )";
389 
390     for (i = 0; i <= 5; ++i)
391     {
392         system("cls");
393         gotoPos(i, (80 - strlen(words0)) / 2);
394         printf("%s", words0);
395         Sleep(50);
396     }
397     for (i = 78; i >= 39; --i)
398     {
399         gotoPos(7, i);
400         printf("%s", words1);
401         gotoPos(7, 78 - i);
402         printf("%s", words1);
403         Sleep(40);
404     }
405     for (i = 0; i <= (80 - strlen(words2)) / 2; ++i)
406     {
407         gotoPos(9, i);
408         printf("%s", words2);
409         Sleep(50);
410     }
411     for (i = 24; i >= 14; --i)
412     {
413         system("cls");
414         gotoPos(5, (80 - strlen(words0)) / 2);
415         printf("%s", words0);
416         gotoPos(7, 39);
417         printf("%s", words1);
418         gotoPos(9, (80 - strlen(words2)) / 2);
419         printf("%s", words2);
420         gotoPos(i, (80 - strlen(words3)) / 2);
421         printf("%s", words3);
422         Sleep(50);
423     }
424     char help0[] = "{←↑↓→ 移动光标,空格\\回车 翻牌,Esc 退出}";
425     char help1[] = "{其他暂停界面按任意键继续}";
426     gotoPos(18, (80 - strlen(help0)) / 2);
427     printf("%s", help0);
428     gotoPos(19, (80 - strlen(help1)) / 2);
429     printf("%s", help1);
430 
431     getch();
432 }
433 
434 void over(char *str) {
435     setColor(110);
436     system("cls");
437     gotoPos(10, 0);
438     int i = 0;
439     do
440     {
441         printf("%c", str[i]);
442         Sleep(100);
443     } while(str[i++]);
444     system("pause");
445     exit(0);
446 }

 

转载于:https://www.cnblogs.com/evangwt/archive/2013/03/13/2956903.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值