阅读 98

C语言实现扫雷游戏详解(附源码)

大家好,本篇文章主要讲的是C语言实现扫雷游戏详解(附源码),感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下

目录
  • 1.游戏的功能 

  • 2.游戏实现的基本思路

    • 2.1实现菜单给玩家选择

    • 2.2初始化棋盘

    • 2.3数组大小的问题

    • 2.4对棋盘赋值

    • 2.5打印棋盘

    • 2.6布置雷

    • 2.7排查雷

  • 3.代码基本实现部分

    • 3.1主函数部分

    • 3.2 初始化棋盘

    •  3.3对两个棋盘进行赋值

    • 3.4打印棋盘

    •  3.5布置雷

    •  3.6排查雷

    •  3.7函数声明

  • 4.扫雷游戏的源代码 

    • 总结

      1.游戏的功能 

      游戏的主要功能有

      1:棋盘内有若干个雷

      2:玩家输入要排查雷的坐标

      3:在玩家输入的坐标处显示周围八个坐标有几个雷

      3:若玩家将所有的雷排查完,结束游戏,玩家胜利

      4:若玩家输入有雷的坐标,则玩家游戏失败

      5:玩完一把玩家可继续选择进入或退出游戏

      2.游戏实现的基本思路

      2.1实现菜单给玩家选择

      站在玩家的角度,我们肯定是要制作一个简易的菜单来供玩家选择的,包括进入游戏,退出游戏等等,这个步骤也很简单,我们通常把这个步骤放到主函数内实现。

      2.2初始化棋盘

      大家看上面的棋盘可别以为我只定义了一个棋盘,其实不然,我们需要用到两个棋盘。

      一个棋盘专门用来存放我们布置好的雷 ,我们把这个棋盘命名为mine吧

      一个棋盘专门展示出来给大家进行排雷 ,并且把排雷的信息存入这个数组,我们把这个棋盘命名为show吧

      注意:这两个棋盘都要定义为字符型的二维数组,而不是整型的

      这两个棋盘都要先初始化为0,在后面的过程中,大家一定要分清这两个数组哦

      2.3数组大小的问题

      虽然图中我们的棋盘时9*9大小的,但是我们前面对游戏的功能进行约定过,我们要在玩家输入的坐标处周围八个坐标有几个雷。如果我们定义的棋盘是9*9大小的。当我们输入的坐标是偏中间 比如 4,4  3 ,6 这些,我们可以很好地访问到这些坐标处周围的八个坐标,但如果我们要排查边边上的那些坐标,在访问边边上的周围的八个坐标时,就会造成越界访问,所以我们要定义11*11大小的坐标刚刚好,上下和左右两边都多出一行。只要我们打印的时候只打印中间的9*9部分就可以了。

      2.4对棋盘赋值

      这里我们要先约定好,我们是有两个棋盘的

      一个是名为mine的棋盘,  我们把它数组的内容全部初始化为字符0,0表示不是雷,我们可以用1表示是雷,后面我们布置雷的时候会用到这个字符1

      一个是名为show的棋盘,我们把这个数组全部内容初始化为字符*,玩家就是在这个棋盘上进行扫雷,每扫一个,*就少一个

      注意:赋值的时候是整个数组的大小,是11*11的部分,而不是9*9的部分

      2.5打印棋盘

      将棋盘初始化好了,我们就要把棋盘打印出来,这样玩家才好进行排雷,我们是只打印中间9*9的部分,而且只打印show数组,如果把布置好雷的mine 数组打印出来了,玩家就可以看到雷了,但我们在后面布置好雷的时候可以把mine 数组打印出来观察一下,看一下有误问题

      2.6布置雷

      这里我们就先约定好在9*9的棋盘上布置10个雷

      布置10个雷,我们就要让电脑随机生成10个坐标,然后对应的二维数组的内容赋值为字符1

      产生随机值是要用到srand函数的,如果大家对这个还不了解,可以去了解一下它的用法

      这里我就不细讲了

      2.7排查雷

      我们要让玩家输入坐标,玩家没输入一次坐标,若玩家没有被雷炸死,需要在坐标处显示坐标周围有几个雷,我们约定过布置了10个雷,所以玩家要赢的话必须排查71个坐标,若玩家输入的坐标处有雷,玩家就被炸死了,结束游戏

      3.代码基本实现部分

      3.1主函数部分

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      void menu()
      {
          printf("***********************\n");
          printf("********1.play*********\n");
          printf("********0.exit*********\n");
          printf("***********************\n");
      }
      int main()
      {
          int input = 0;
          srand((unsigned int)time(NULL));    //产生随机数
          //我们将这个过程写成一个do……while循环,使玩家一进来就可以进行选择
          do
          {
              menu();        //打印菜单
              printf("请选择:\n");
              scanf_s("%d", &input);
              switch (input) //switch多分支语句
              {
              case 1:
                  printf("扫雷\n");
                  game();   //进入游戏
                  break;
              case 0:
                  printf("退出游戏\n");
                  break;
              default:
                  printf("选择错误,请重新选择\n");
                  break;
              }
        
          } while (input);
      }

      3.2 初始化棋盘

      棋盘的大小是11*11的,但我们后面有时只用到9*9的部分,所以我们只要分别定义两个行和列的大小,我们可以使用宏定义,方便以后修改

      1
      2
      3
      4
      5
      #define ROW 9        //定义行和列的大小
      #define COL 9
        
      #define ROWS ROW+2
      #define COLS COL+2
      1
      2
      3
      //定义两个字符型的二维数组,并初始化为0
      char mine[ROWS][COL] = { 0 };  //存放布置好雷的信息
      char show[ROWS][COLS] = { 0 }; //存放排查出来的雷的信息

       3.3对两个棋盘进行赋值

      1
      2
      3
      4
      5
      6
      7
      char mine[ROWS][COL] = { 0 };  //存放布置好雷的信息
      char show[ROWS][COLS] = { 0 }; //存放排查出来的雷的信息
       
      //初始化数组
      //第一个数组初始化为'0',第二个数组初始化为'*'
      initboard(mine, ROWS, COLS, '0');   //因为整个数组都要进行初始化,所以传ROWS和COLS
      initboard(show, ROWS, COLS, '*');
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      void initboard(char board[ROWS][COLS], int rows, int cols, char set)
      {
          int i = 0;
          int j = 0;
          for (i = 0; i < rows; i++)
          {
              for (j = 0; j < cols; j++)
              {
                  board[i][j] = set;
              }
          }
      }

      3.4打印棋盘

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      //将这段代码放到game函数内执行
      void displayboard(char board[ROWS][COLS], int row, int col)
      {
          //为了让玩家方便输入坐标,所以我们把棋盘的行和列打印出来
          int i = 0;
          int j = 0;
          printf("-----扫雷游戏-----\n");
          for (i = 0; i <= col; i++)  //打印行号
          {
              printf("%d ", i);
          }
          printf("\n");
          for (i = 1; i <= row; i++)
          {
              printf("%d ", i);//打印列号
              for (j = 1; j <= col; j++)
              {
                  printf("%c ", board[i][j]);
              }
              printf("\n");
          }
          printf("-----扫雷游戏-----\n");
      }

       3.5布置雷

      我们要在mine数组内布置10个雷

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      //布置雷
      void setmine(char mine[ROWS][COLS], int row, int col)  
                                         //因为要把雷布置在9*9格子内,所以接受的参数是ROW和COL
      {
          int count = 10;  //布置10个雷
          while (count)                   //当已经布置了10个雷,退出循环
          {
              //产生的坐标应该在1-9的坐标范围内
              int x = rand() % row + 1;    //任何正整数模上9再加上1结果就是1-9
              int y = rand() % col + 1;
              if (mine[x][y] == '0')       //如果棋盘棋盘上内容是'0',也就是说还没有布置雷的话
              {                            //才将'1'赋值给数组,否则重新生成坐标
                  mine[x][y] = '1';
                  count--;                 //没生成一个坐标,count--
              }
          }
      }

       3.6排查雷

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      int get_mine_count(char mine[ROWS][COLS], int x, int y)   //注意返回类型为int
      {
          //遍历周围八个坐标
          return mine[x - 1][y] +
              mine[x - 1][y - 1] +
              mine[x][y - 1] +
              mine[x + 1][y - 1] +
              mine[x + 1][y] +
              mine[x + 1][y + 1] +
              mine[x][y + 1] +
              mine[x - 1][y + 1] - 8 * '0';    //周围有8个坐标
             //这里利用的是字符的ASCII码值进行转换 字符0-9的ASCII码值分别是30-39
             //8*'0'总共就是240,减去240就是雷的个数
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
      {
          int x = 0;
          int y = 0;
          int win = 0;       //定义一个变量,统计玩家排了多少个坐标
          while (win<row*col-10)    //当win=9*9-10的时候,代表所有雷都排完了,不需要再进入循环
          {
              //1.输入排查的坐标     
              //2.检查坐标处是不是雷
              //(1)是雷 - 炸死了
              //(2)不是雷 -统计坐标周围有几个雷,存储排查雷的信息放到show数组内
              printf("请输入要排查的雷的坐标\n");
              scanf_s("%d %d", &x, &y);
              //判断坐标是否合法
              if (x >= 1 && x <= col && y >= 1 && y <= col)
              {
                  //不需要调整坐标
                  if (mine[x][y] == '1')
                  {
                      printf("很遗憾,你被炸死了\n");
                      displayboard(mine, ROW, COL);
                      break;
                  }
                  else if(mine[x][y] != '1')
                  {
                      //不是雷的话,统计x,y坐标周围有几个雷
                      int count = get_mine_count(mine, x, y);  //调用这个函数,获取雷的个数
                      show[x][y] = count + '0';    //将雷的个数加上'0'就是个数对应的ASCII码值
                      //显示排查出的信息
                      displayboard(show, ROW, COL); //没排完一次雷,显示数组最新的排查信息
                      win++;   //玩家每排一个坐标,win++一次
                  }
              }
              else
              {
                  printf("输入坐标不合法,请重新输入\n");  //若玩家输入坐标不合法,提示玩家重新输入
              }
          }
          if (win == 71)
          {
              printf("恭喜你排雷成功\n");
              displayboard(mine, ROW, COL);
          }
        
      }

       3.7函数声明

      最后大家不要忘了函数声明哦,我这是写在一个文件里的,大家也可以写在不同的文件里

      1
      2
      3
      4
      void initboard(char board[ROWS][COLS], int rows, int cols, char set);
      void displayboard(char board[ROWS][COLS], int row, int col);
      void setmine(char board[ROWS][COLS], int row, int col);
      void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

      get_mine_count函数是定义在void game函数内部的函数,因此get_mine_count函数不需要进行声明

      4.扫雷游戏的源代码 

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      136
      137
      138
      139
      140
      141
      142
      143
      144
      145
      146
      147
      148
      149
      150
      151
      152
      153
      154
      155
      156
      157
      158
      159
      160
      161
      162
      163
      164
      165
      166
      167
      168
      169
      170
      171
      172
      173
      174
      175
      176
      177
      178
      179
      180
      181
      182
      183
      184
      185
      186