鱼C论坛

 找回密码
 立即注册
查看: 1315|回复: 6

[技术交流] 扫雷游戏

[复制链接]
发表于 2020-5-21 16:12:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 就是要努力呀 于 2020-5-21 16:13 编辑
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <time.h>

  5. void menu(int *map_x, int *map_y);        //主菜单
  6. char **make_map(int map_x, int map_y);        //生成地图
  7. char **make_mine_map(int mine_x, int mine_y, int mine_num);        //生成地雷地图
  8. void print_all_map(char **map, int map_x, int map_y, char **mine_map, int mine_x, int mine_y);        //打印地图
  9. int begin_game(char **map, int map_x, int map_y, char **mine_map, int mine_x, int mine_y, int mine_num);        //开始游戏
  10. int open_place(char **map, int map_x, int map_y, char **mine_map, int mine_x, int mine_y, int x, int y);        //打开玩家选择的位置
  11. void expand(char **map, int map_x, int map_y, char **mine_map, int mine_x, int mine_y, int x, int y);        //通过递归方式实现扫雷的扩展功能,游戏最重要的部分
  12. int check_mine(char **mine_map, int mine_x, int mine_y, int x, int y);        //检测一个位置周围8格以内的地雷数
  13. int check_win(char **map, int mine_x, int mine_y, int mine_num);        //检测是否赢得游戏
  14. void win(char **map, int map_x, int map_y);        //赢得游戏,打印所有地雷所在位置

  15. void win(char **map, int map_x, int map_y)
  16. {
  17.         int i, j;

  18.         for(i = 0; i < map_x; i++)
  19.         {
  20.                 for(j = 0; j < map_y; j++)
  21.                 {
  22.                         if(map[i][j] == '+')
  23.                         {
  24.                                 map[i][j] = '@';
  25.                         }

  26.                         printf("%c ", map[i][j]);
  27.                 }

  28.                 putchar('\n');
  29.         }
  30. }

  31. int check_win(char **map, int mine_x, int mine_y, int mine_num)
  32. {
  33.         int i, j;
  34.         int num = 0;

  35.         for(i = 1; i < mine_x; i++)
  36.         {
  37.                 for(j = 1; j < mine_y; j++)
  38.                 {
  39.                         if(map[i][j] == '+')
  40.                         {
  41.                                 num++;
  42.                         }
  43.                 }
  44.         }

  45.         if(num == mine_num)
  46.         {
  47.                 printf("恭喜你赢了\n");

  48.                 return 1;
  49.         }

  50.         return 0;
  51. }

  52. int check_mine(char **mine_map, int mine_x, int mine_y, int x, int y)
  53. {
  54.         int num = 0;

  55.         //判断该位置周围8格的地雷数

  56.         if(x - 1 > 0 && mine_map[x - 1][y] == '@')
  57.         {
  58.                 num++;
  59.         }

  60.         if(x + 1 < mine_x && mine_map[x + 1][y] == '@')
  61.         {
  62.                 num++;
  63.         }

  64.         if(y - 1 > 0 && mine_map[x][y - 1] == '@')
  65.         {
  66.                 num++;
  67.         }

  68.         if(y + 1 < mine_y && mine_map[x][y + 1] == '@')
  69.         {
  70.                 num++;
  71.         }

  72.         if(x - 1 > 0 && y - 1 > 0 && mine_map[x - 1][y - 1] == '@')
  73.         {
  74.                 num++;
  75.         }

  76.         if(x - 1 > 0 && y + 1 < mine_y && mine_map[x - 1][y + 1] == '@')
  77.         {
  78.                 num++;
  79.         }

  80.         if(x + 1 < mine_x && y + 1 < mine_x && mine_map[x + 1][y + 1] == '@')
  81.         {
  82.                 num++;
  83.         }

  84.         if(x + 1 < mine_x && y - 1 > 0 && mine_map[x + 1][y - 1] == '@')
  85.         {
  86.                 num++;
  87.         }

  88.         return num;
  89. }

  90. void expand(char **map, int map_x, int map_y, char **mine_map, int mine_x, int mine_y, int x, int y)
  91. {
  92.         int num;
  93.        
  94.         if(!(num = check_mine(mine_map, mine_x, mine_y, x, y)))        //判断这个位置的周围8格是否有地雷,如果有将该位置设置为地雷数,并停止对该位置后续的展开
  95.         {
  96.                 map[x][y] = ' ';
  97.                
  98.                 //向该位置的8个方向进行展开

  99.                 if(x - 1 > 0 && map[x - 1][y] == '+')
  100.                 {
  101.                         expand(map, map_x, map_y, mine_map, mine_x, mine_y, x - 1, y);
  102.                 }

  103.                 if(x + 1 < mine_x && map[x + 1][y] == '+')
  104.                 {
  105.                         expand(map, map_x, map_y, mine_map, mine_x, mine_y, x + 1, y);
  106.                 }

  107.                 if(y - 1 > 0 && map[x][y - 1] == '+')
  108.                 {
  109.                         expand(map, map_x, map_y, mine_map, mine_x, mine_y, x, y - 1);
  110.                 }

  111.                 if(y + 1 < mine_y && map[x][y + 1] == '+')
  112.                 {
  113.                         expand(map, map_x, map_y, mine_map, mine_x, mine_y, x, y + 1);
  114.                 }
  115.                
  116.                 if(x - 1 > 0 && y - 1 > 0 && map[x - 1][y - 1] == '+')
  117.                 {
  118.                         expand(map, map_x, map_y, mine_map, mine_x, mine_y, x - 1, y - 1);
  119.                 }

  120.                 if(x - 1 > 0 && y + 1 < mine_y && map[x - 1][y + 1] == '+')
  121.                 {
  122.                         expand(map, map_x, map_y, mine_map, mine_x, mine_y, x - 1, y + 1);
  123.                 }
  124.                
  125.                 if(x + 1 < mine_x && y + 1 < mine_y && map[x + 1][y + 1] == '+')
  126.                 {
  127.                         expand(map, map_x, map_y, mine_map, mine_x, mine_y, x + 1, y + 1);
  128.                 }

  129.                 if(x + 1 < mine_x && y - 1 > 0 && map[x + 1][y - 1] == '+')
  130.                 {
  131.                         expand(map, map_x, map_y, mine_map, mine_x, mine_y, x + 1, y - 1);
  132.                 }
  133.         }
  134.         else
  135.         {
  136.                 map[x][y] = num + 48;
  137.         }
  138. }

  139. int open_place(char **map, int map_x, int map_y, char **mine_map, int mine_x, int mine_y, int x, int y)
  140. {
  141.         if(mine_map[x][y] == '@')
  142.         {
  143.                 printf("游戏结束!\n");

  144.                 return 0;
  145.         }
  146.         else if(mine_map[x][y] == '+')
  147.         {
  148.                 expand(map, map_x, map_y, mine_map, mine_x, mine_y, x, y);        //如果玩家选中的位置没有踩雷,就需要展它周围的空位置

  149.                 return 1;
  150.         }

  151.         return 1;
  152. }

  153. int begin_game(char **map, int map_x, int map_y, char **mine_map, int mine_x, int mine_y, int mine_num)
  154. {
  155.         char x = ' ', y = ' ';
  156.         char choose;
  157.         static int num = 0;

  158.         do
  159.         {
  160.                 printf("总地雷数:%d 当前地雷数:%d\n", mine_num, mine_num - num);
  161.                 printf("请输入行和列(qq退出游戏):");
  162.                 scanf("%c %c", &x, &y);
  163.                 getchar();

  164.                 if(x == 'q' && y == 'q')
  165.                 {
  166.                         exit(0);
  167.                 }
  168.         }
  169.         while(x < '0' || y < '0' || x > (char)(map_x - 2 + 48) || y > (char)(map_y - 2 + 48));

  170.         do
  171.         {
  172.                 printf("1.打开:2.标记:3.取消标记:4.重新选择\n");
  173.                 printf("请选择你要执行的命令:");
  174.                 choose = getchar();
  175.                 getchar();
  176.         }
  177.         while(choose != '1' && choose != '2' && choose != '3');

  178.         switch(choose)
  179.         {
  180.                 case '1':
  181.                         {
  182.                                 return open_place(map, map_x, map_y, mine_map, mine_x, mine_y, (int)x - 48, (int)y - 48);        //因为我们的x和y设置的是字符型,要将他强制转换成int型,方便open_place函数定位
  183.                         }
  184.                 case '2':
  185.                         {
  186.                                 num++;

  187.                                 map[(int)x - 48][(int)y - 48] =        '^';

  188.                                 break;
  189.                         }

  190.                 case '3':
  191.                         {
  192.                                 num--;

  193.                                 map[(int)x - 48][(int)y - 48] = '+';

  194.                                 break;
  195.                         }
  196.                 case '4':
  197.                         {
  198.                                 break;
  199.                         }
  200.         }
  201. }

  202. void print_all_map(char **map, int map_x, int map_y, char **mine_map, int mine_x, int mine_y)
  203. {
  204.         int i, j;

  205.         for(i = 0; i < map_x; i++)
  206.         {
  207.                 for(j = 0; j < map_y; j++)
  208.                 {
  209.                         printf("%c ", map[i][j]);
  210.                 }

  211.                 putchar('\n');
  212.         }
  213.         
  214.         /*for(i = 0; i < mine_x; i++)
  215.         {
  216.                 for(j = 0; j < mine_y; j++)
  217.                 {
  218.                         printf("%c ", mine_map[i][j]);
  219.                 }

  220.                 putchar('\n');
  221.         }*/

  222. }

  223. char **make_mine_map(int mine_x, int mine_y, int mine_num)
  224. {
  225.         char **mine_map;
  226.         int i, j;
  227.         int x, y;
  228.         int num = 0;

  229.         mine_map = (char **)malloc(sizeof(char *) * mine_x);

  230.         for(i = 0; i < mine_x; i++)
  231.         {
  232.                 mine_map[i] = (char *)malloc(sizeof(char) * mine_y);
  233.         }

  234.         srand(time(NULL));

  235.         for(i = 0; i < mine_x; i++)
  236.         {
  237.                 for(j = 0; j < mine_y; j++)
  238.                 {
  239.                         mine_map[i][j] = '+';
  240.                 }
  241.         }

  242.         while(num < mine_num)
  243.         {
  244.                 do
  245.                 {
  246.                         x = rand()%(mine_x - 1) + 1;
  247.                         y = rand()%(mine_y - 1) + 1;
  248.                 }
  249.                 while(mine_map[x][y] != '+');

  250.                 mine_map[x][y] = '@';

  251.                 num++;
  252.         }

  253.         return mine_map;
  254. }

  255. char **make_map(int map_x, int map_y)
  256. {
  257.         char **map;
  258.         int i, j, k = 1;

  259.         map = (char **)malloc(sizeof(char *) * map_x);

  260.         for(i = 0; i < map_x; i++)
  261.         {
  262.                 map[i] = (char *)malloc(sizeof(char) * map_y);
  263.         }

  264.         for(i = 0; i < map_x - 1; i++)
  265.         {
  266.                 map[i][0] = i + 48;
  267.         }

  268.         for(j = 0; j < map_y - 1; j++)
  269.         {
  270.                 map[0][j] = j + 48;
  271.         }

  272.         for(i = 1; i < map_x - 1; i++)
  273.         {
  274.                 for(j = 1; j < map_y - 1; j++)
  275.                 {
  276.                         map[i][j] = '+';
  277.                 }
  278.         }
  279.        
  280.         return map;
  281. }

  282. void menu(int *map_x, int *map_y)
  283. {
  284.         char choose;

  285.         do
  286.         {
  287.                 printf("********************1.开始游戏*******************\n");
  288.                 printf("********************2.退出游戏*******************\n");
  289.                 printf("请选择:");
  290.                 choose = getchar();
  291.                 getchar();
  292.         }
  293.         while(choose != '1' && choose != '2');

  294.         if(choose == '1')
  295.         {
  296.                 do
  297.                 {
  298.                         printf("1.初级:2.中级:3.高级:4.自定义");
  299.                         printf("请选择:");
  300.                         choose = getchar();
  301.                         getchar();
  302.                 }
  303.                 while(choose != '1' && choose != '2' && choose != '3' && choose != '4');

  304.                 switch(choose)
  305.                 {
  306.                         case '1':
  307.                                 {
  308.                                         *map_x = 12;
  309.                                         *map_y = 12;
  310.                                         break;
  311.                                 }

  312.                         case '2':
  313.                                 {
  314.                                         *map_x = 22;
  315.                                         *map_y = 22;
  316.                                         break;
  317.                                 }

  318.                         case '3':
  319.                                 {
  320.                                         *map_x = 42;
  321.                                         *map_y = 42;
  322.                                         break;
  323.                                 }

  324.                         case '4':
  325.                                 {
  326.                                         do
  327.                                         {
  328.                                                 printf("请输入行:");
  329.                                                 scanf("%d", map_x);
  330.                                                 getchar();
  331.                                         }
  332.                                         while(*map_x <= 0 || *map_x > 100);

  333.                                         do
  334.                                         {
  335.                                                 printf("请输入列:");
  336.                                                 scanf("%d", map_y);
  337.                                                 getchar();
  338.                                         }
  339.                                         while(*map_y <= 0 || *map_y > 100);

  340.                                         *map_x += 2;
  341.                                         *map_y += 2;
  342.                                 }
  343.                 }
  344.         }
  345.         else exit(0);
  346. }

  347. int main(void)
  348. {
  349.         int map_x, map_y;

  350.         menu(&map_x, &map_y);

  351.         char **map;        //设置一个二级指针来接受返回的动态二维数组

  352.         map = make_map(map_x, map_y);        //为了使得行列可以自定义,用动态申请二维数组的方法

  353.         char **mine_map;        //同样的方法设置一个地雷地图的二级指针
  354.         int mine_x = map_x - 1;        //设置地雷地图的行列
  355.         int mine_y = map_y - 1;
  356.         int mine_num = mine_x + mine_y - 4;         //设置地雷数

  357.         mine_map = make_mine_map(mine_x, mine_y, mine_num);        //动态申请一个二维数组

  358.         do
  359.         {
  360.                 print_all_map(map, map_x, map_y, mine_map, mine_x, mine_y);        //打印地图

  361.                 if(check_win(map, mine_x, mine_y, mine_num))        //玩家每走一步就检测是否赢得比赛
  362.                 {
  363.                         win(map, map_x, map_y);

  364.                         break;
  365.                 }
  366.         }
  367.         while(begin_game(map, map_x, map_y, mine_map, mine_x, mine_y, mine_num));        //begin_game该游戏的主要函数


  368.         return 0;
  369. }
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
zyh1104 + 5 + 5 + 3 鱼C有你更精彩^_^

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-5-22 10:23:50 | 显示全部楼层
这是原创吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-22 15:02:21 | 显示全部楼层

嗯自己写的,写了三个半天。裂开了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-22 15:28:36 | 显示全部楼层
就是要努力呀 发表于 2020-5-22 15:02
嗯自己写的,写了三个半天。裂开了

很厉害
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-24 18:41:45 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-25 00:32:17 | 显示全部楼层
学习到了!顶
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-25 10:41:05 From FishC Mobile | 显示全部楼层
糖逗 发表于 2020-5-25 00:32
学习到了!顶

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-7 08:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表