经典游戏扫雷详解--你也可以写出扫雷和玩好扫雷(下)

简介: 经典游戏扫雷详解--你也可以写出扫雷和玩好扫雷(下)

3.详细步骤实现



1.创建数组


采取分模块写法:

1.test.c的主源文件中写主体步骤

2.game.h 中申明扫雷游戏模块相关的函数申明,自定义等

3.game.c 中实现函数定义


test.c 中代码如下:

void game()//游戏函数实现
{
  char mine[ROWS][COLS] = { 0 };//存放雷的数组
  char show_mine[ROWS][COLS] = { 0 };//存放展示扫雷的素组
}
void menu() //菜单函数实现
{
  printf("****************\n");
  printf("**** 1.play ****\n");
  printf("**** 0.exit ****\n");
  printf("****************\n");
}
int main()
{
  int input = 0;
  srand((unsigned)time(NULL));
  do
  {
    menu(); //菜单
    printf("请选择: \n");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      game();
      break;
    case 0:
      printf("即将退出游戏\n");
      break;
    default:
      printf("选择错误,请重新选择\n");
      break;
    }
  } while (input);//玩家输入的值来进行循环的判断,可达到循环玩游戏的效果
  return 0;
}


game.h 中代码如下:

#define ROW 9  //操作的行
#define COL 9  //操作的列
#define COLS COL+2  //防止数组越界
#define ROWS ROW+2  //防止素组越界

86142c0646384c77ac4a03ca8cab9419.png

由于我们看到的扫雷的棋盘是一个9*9的棋盘,因此我们操作的棋盘应该就是这个大小,但是当判断内容时,我们是以一个数字为中心的九宫格,那么,在边界上的数字(如上图所示)的九宫格就会超过需要的棋盘大小,为了防止越界,我们将棋盘的行列均扩大,上下左右均需要扩大,因此行列扩大两行。


2.初始化素组


test.c 中代码如下:

void game()
{
  char mine[ROWS][COLS] = { 0 };//存放雷的数组
  char show_mine[ROWS][COLS] = { 0 };//展示扫雷的素组--给玩家观察的数组
  Initboard(mine, ROWS, COLS, '0');  //初始化为字符‘0’  
  Initboard(show_mine, ROWS, COLS, '*');//初始化为字符‘*’
}


game.h 中代码如下:

//初始化数组中的内容
void Initboard(char board[ROWS][COLS], int rows, int cols ,char sz);


game.c 中代码如下:


game.c 中实现函数时所涉及的头文件我们放在game.h中,可以防止重复引用

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"//用了game.h 中 ROWS COLS 等自定义的变量须应用头文件
void Initboard(char board[ROWS][COLS], int rows, int cols,char sz)
{ 
  //**传入 sz 这个字符参数 方便我们一个函数可以解决 雷的棋盘和展示棋盘的初始化**
  int i = 0;
  int j = 0;
  for (i = 0; i < rows; i++)
  {
    for (j = 0; j < cols; j++)
    {
      board[i][j] = sz;
    }
  }
}


3.展示(打印)数组


test.c 中代码如下:

void game()
{
  char mine[ROWS][COLS] = { 0 };//存放雷的数组
  char show_mine[ROWS][COLS] = { 0 };//展示扫雷的数组--给玩家观察的数组
  Initboard(mine, ROWS, COLS, '0');  //初始化为字符‘0’  
  Initboard(show_mine, ROWS, COLS, '*');//初始化为字符‘*’
  print_board(show_mine, ROW, COL);//展示扫雷的数组
//注意的是,我们操作的是展示的9*9的棋盘,因此我们传入的棋盘行列大小也是9*9,即ROW,COL
}


game.h 中代码如下:

#include<stdio.h>
//打印初始化后的内容
void print_board(char board[ROWS][COLS], int row, int col);
我们传入的是show_mine 这个数组,因此这里的【ROWS】【COLS】也应当是和
show_mine创建的时候保持一直,但我们展示的却是9*9的棋盘,因此传入的行列是
row和col


game.c 中代码如下:

void print_board(char board[ROWS][COLS], int row, int col)
{
  printf("--------扫雷-------\n");//上分割线
  int i = 0;
  int j = 0;
  //打印横坐标
  for (i = 0; i <= row; i++)  
  {
    if (i == 0)
      printf("  ");
    else
      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");下分割线
}


效果展示:

b48d9358a9c547a98f3dc47a844cbd9f.png


4. 设置雷(埋雷)


test.c 中代码如下:

void game()
{
  char mine[ROWS][COLS] = { 0 };//存放雷的数组
  char show_mine[ROWS][COLS] = { 0 };//展示扫雷的数组--给玩家观察的数组
  Initboard(mine, ROWS, COLS, '0');  //初始化为字符‘0’  
  Initboard(show_mine, ROWS, COLS, '*');//初始化为字符‘*’
  print_board(show_mine, ROW, COL);//展示扫雷的数组
  Set_mine(mine, ROW, COL);
  //埋雷的过程,只操作我们存放雷的数组
    //print_board(mine, ROW, COL);//可以观察设置的雷是否正确
}


game.h 中代码如下:

#define junior_mine 10  //雷的数目
#include<stdlib.h>//srand,rand 的头文件
#include<time.h> //time 的头文件
//设置雷
void Set_mine(char board[ROWS][COLS], int row, int col);
同上面展示雷的数组一样,埋雷的这个数组操作的是创建的 mine这个数组
【ROWS】【COLS】需要保持一直,由于扫雷的方块是9*9大小,所以我们传
入的棋盘大小任然是row 和 col


game.c 中代码如下:

void Set_mine(char board[ROWS][COLS], int row, int col)
{
  int x = 0;
  int y = 0;
  int count = junior_mine;
  while (count) //雷的数量为0时跳出循环说明雷已经布置完了
  {
    //随机产生雷的坐标在 1~9的范围内
    x = rand() % row + 1;
    y = rand() % col + 1;
    if (board[x][y] == '0') //说明该坐标处没有雷并且可以设置雷
    {
      board[x][y] = '1';  //埋雷成功 用 字符 1表示
      count--;
    }
  }
}


5.扫雷


test.c 中代码如下:

void game()
{
  char mine[ROWS][COLS] = { 0 };//存放雷的数组
  char show_mine[ROWS][COLS] = { 0 };//展示扫雷的数组--给玩家观察的数组
  Initboard(mine, ROWS, COLS, '0');  //初始化为字符‘0’  
  Initboard(show_mine, ROWS, COLS, '*');//初始化为字符‘*’
  print_board(show_mine, ROW, COL);//展示扫雷的数组
  Set_mine(mine, ROW, COL);
  Find_mine(mine, show_mine, ROW, COL);
}


game.h 中代码如下:

//排雷
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);


game.c 中代码如下:

//统计该坐标周围雷的个数
int sum_mine(char board[ROWS][COLS], int x, int y)
{
  int sum = 0;
  int i = 0;
  int j = 0;
  for (i = x - 1; i <= x + 1; i++)   
  {
    //产生以该坐标为中心的九宫格内的八个坐标
    for (j = y - 1; j <= y + 1; j++)
    {
      sum+=board[i][j] - '0'; //注意数字和字符之间的转换
    }
  }
  return sum;
}
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
  printf("请输入坐标进行排查:\n");
  int x = 0;
  int y = 0;
  //IsWin函数用于判断是否胜利 下在一步具体实现
  while (IsWin(show,row,col)==0) 
  {
    scanf("%d %d", &x, &y);
    if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标合法性
    {
      if (mine[x][y] == '1')
      {
        printf("踩雷!\n");
        print_board(mine, ROW, COL);//踩雷后给玩家展示踩雷在哪里
                                    //和雷的全部坐标
        break;
      }
      else  //没有踩雷
      {
        int count = sum_mine(mine, x, y);//先统计该做标的周围的雷
        show[x][y] = count + '0';//注意int类型和字符类型转换
        Open_Not_mine(mine, show, x, y);//展开该坐标周围没有雷的方块
        print_board(show, ROW, COL);//展示完以及雷的个数统计后,展示给玩家观察
      }
    }
    else
      printf("输入错误,请重新输入\n");
  }


6.展开该坐标周围没有雷的全部方块


由于展开周围坐标没有雷的方块这个函数不属于游戏模块test.c 中的game()里的函数,因此不需要写在game.h中声明


game.c 中代码如下:

void Open_Not_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
  int i = 0;
  int j = 0;
  int count = 0;
  //判断坐标是否合法
  if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
  {        
    for (i = -1; i<= 1; i++)
    {    //该坐标为中心的八个坐标的循环写法
      for (j = -1; j<= 1; j++)
      {
        //如果这个坐标不是雷的情况下
        if (mine[x + i][y + j] == '0')
        {     
         // 注意是 [x+i]和[y+i] 是改坐标周围其他坐标
          //统计这个坐标周围的雷
          count = sum_mine(mine, x + i, y + j);
          if (count == 0) //坐标周围没有雷,说明可以展开
          {
            if (show[x + i][y + j] == '*')
            {
              show[x + i][y + j] = ' ';
              Open_Not_mine(mine, show, x + i, y + j);  
              //回去递归调用周围坐标判断
            }
          }
          else //周围有雷 则这个坐标轴为中心的九宫格将不展开
          {
            show[i + x][j + y] = count + '0'; 
            //统计这个坐标周围有几个雷并显示在改坐标处
          }
        }
      }
    }
  }
}


7.判断输赢


同展开函数 Open_Not_mine 一样, 判断输赢这个函数也不需要在game.h中进行声明


game.c中代码如下:

int IsWin(char show[ROWS][COLS], int row, int col)
{
  int i = 0;
  int j = 0;
  int count = 0;
  for (i = 1; i <= row;i++)
  {
    //判断坐标范围
    for (j = 1; j <= col; j++)
    {
      if (show[i][j] == '*')
      {
        count++; //统计show数组在9*9中棋盘上一共有多少个不是雷的个数
      }
    }
  }               //雷的个数
  return count == junior_mine;//相等返回1  不想动返回0
  //相等时说明 没有雷的方块都已经找到了,其余的位置都为雷--胜利
  //不相等的时候表明,不是雷的方块还没有全部找出来--未胜利
}
相关文章
|
2天前
|
C语言
扫雷游戏
扫雷游戏
6 0
|
2天前
|
存储
扫雷游戏的实现
扫雷游戏的实现
|
5月前
|
C语言
扫雷游戏的实现(上)
扫雷游戏的实现
20 0
|
2天前
leetcode-529:扫雷游戏
leetcode-529:扫雷游戏
22 0
|
9月前
|
C语言
C/关于扫雷小游戏的创建
C/关于扫雷小游戏的创建
|
5月前
扫雷游戏的实现(详解)
扫雷游戏的实现(详解)
44 0
|
5月前
|
C语言
扫雷游戏的实现(下)
扫雷游戏的实现(下)
27 0
|
5月前
|
存储
扫雷小游戏
扫雷小游戏
53 0
|
7月前
|
C语言

相关实验场景

更多