扫雷——C语言实现(二)

简介: 扫雷——C语言实现

排查地雷

  • 接下来就需要用户排查地雷了
  • 我们利用循环提醒用户输入要排查的坐标,有以下五种情况:
  • 如果排查的坐标是雷,那么直接退出game()函数,表示排雷失败(如果排雷失败,那么就要向用户展示存放雷的数组,让用户明白到底错在了哪)
  • 如果排查的坐标已经被检查过,那么提醒用户,重新输入
  • 如果排查的坐标非法,那么提醒用户,重新输入
  • 如果排查的坐标不是雷,并且还未排雷完毕,那么显示该区域周围有几个雷,继续循环
  • 如果排查的坐标不是雷,并且所有雷已经排查完毕,那么退出game()函数,表示排雷成功
  • 每排查完一次,都要重新打印一次展示数组

记录指定区域周围地雷的个数

  • 上面我们讲到,要确定一个指定坐标(X,Y)周围地雷的个数,只需要查看(X,Y-1), (X,Y+1), (X+1,Y), (X+1,Y+1), (X+1,Y-1), (X-1,Y), (X-1,Y+1), (X-1,Y-1)这八个坐标的值
  • 前面我们已经假设字符‘1’代表地雷,字符‘0’代表非地雷,由于字符‘0’的ASCII的值为48,字符‘1’的ASCII值为49(比字符‘0’大一),那么我们统计(X,Y)周围地雷的个数就只需要将周围八个坐标储存的值相加,然后减去8个字符‘0’即可
  • 这也是将字符‘1’设置为地雷,字符‘0’设置为非地雷的巧妙之处,可以在计算地雷个数的时候少去很多操作
/*
  这里row = ROWS,col = COLS
  这样可以确保排查任意区域操作的一致性(数组不会越界)    
*/
int MineNumber(char board[][COLS], int x, int y)
{
  return (board[x][y - 1] + board[x][y + 1]
    + board[x - 1][y] + board[x - 1][y - 1] + board[x - 1][y + 1]
    + board[x + 1][y] + board[x + 1][y - 1] + board[x + 1][y + 1]
    - 8 * '0');
}

判断排雷成功

  • 如果被排查完的区域的总个数等于整块区域的个数减去地雷个数,那就说明排雷成功
/*
  传入的是展示数组showBoard
  这里row = ROW,col = COL,扩容区域不需要排查
  扩容区域只是为了方便记录边界区域周围的地雷个数
*/
//如果排雷成功,就返回真,否则返回假
bool MineFinish(char board[][COLS], int row, int col)
{
  int count = 0;  //count用来记录已经排查的区域的个数
  for(int i = 1; i <= row; i++)
    for (int j = 1; j <= col; j++)
    {
      if (board[i][j] != '*')
      {
        count++;
        if (count == row * col - MINENUMBER)  //MINENUMBER就是地雷总个数
          return true;
      }
    }
  return false;
}

排查地雷实现代码

void MineFind(char mine[][COLS], char show[][COLS], int row, int col)
{
  int x, y;
  while (1)
  {
    printf("请输入您要排查的坐标(用空格分隔):");
    scanf_s("%d %d", &x, &y);
        //如果排查的区域未被检查并且坐标合法
    if (show[x][y] == '*' && x > 0 && x <= row && y > 0 && y <= col)
    {
            //如果踩到了雷
      if (mine[x][y] == '1')
      {
        printf("很遗憾,排雷失败\n");
        BoardDisplay(mine, row, col);
        return;
      }
            //否则继续排雷
      else
      {
        show[x][y] = MineNumber(mine, x, y) + '0';
                //
        if (MineFinish(show, row,col))
        {
          printf("恭喜你,排雷成功\n");
          BoardDisplay(mine, row, col);
          return;
        }
        BoardDisplay(show, row, col);
      }
    }
        //如果排查的区域合法但已经被检查
    else if (show[x][y] != '*' && x > 0 && x <= row && y > 0 && y <= col)
    {
      printf("该位置已经被检查,请重新输入:\n");
      BoardDisplay(show, row, col);
    }
    //如果排查的区域不合法  
    else
    {
      printf("坐标非法,请重新输入:\n");
      BoardDisplay(show, row, col);
    }
  }

基本功能的实现代码和效果展示

  • 我们先来看看实现效果:

  • 实现代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<stdbool.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define MINENUMBER 10
void BoardInit(char board[][COLS], int row, int col, char set);
void BoardDisplay(char board[][COLS], int row, int col);
void MineSet(char board[][COLS], int row, int col);
int MineNumber(char board[][COLS], int x, int y);
void MineFind(char mine[][COLS], char show[][COLS], int row, int col);
bool MineFinish(char board[][COLS], int row, int col);
void meau()
{
  printf("****************\n");
  printf("*****1.Play*****\n");
  printf("*****0.Exit*****\n");
  printf("****************\n");
}
void game()
{
  //生成时间戳
  srand((unsigned int)time(NULL));
  //定义存放地雷的数组,和展示结果的数组
  char mineBoard[ROWS][COLS];
  char showBoard[ROWS][COLS];
  //对两个数组进行初始化
  BoardInit(mineBoard, ROWS, COLS, '0');
  BoardInit(showBoard, ROWS, COLS, '*');
  //设置地雷
  MineSet(mineBoard, ROW, COL);
    //打印展示数组
  BoardDisplay(showBoard, ROW, COL);
  //排查地雷
  MineFind(mineBoard, showBoard, ROW, COL);
}
void BoardInit(char board[][COLS], int row, int col, char set)
{
  for (int i = 0; i < row; i++)
    for (int j = 0; j < col; j++)
      board[i][j] = set;
}
void BoardDisplay(char board[][COLS], int row, int col)
{
  for (int i = 0; i <= col; i++)
    printf("%d ", i);
  printf("\n");
  for (int i = 1; i <= row; i++)
  {
    printf("%d ", i);
    for (int j = 1; j <= col; j++)
      printf("%c ", board[i][j]);
    printf("\n");
  }
}
void MineSet(char board[][COLS], int row, int col)
{
  int count = 0;
  while (count < MINENUMBER)
  {
    int x = rand() % row + 1;
    int y = rand() % col + 1;
    if (board[x][y] == '0')
    {
      board[x][y] = '1';
      count++;
    }
  }
}
void MineFind(char mine[][COLS], char show[][COLS], int row, int col)
{
  int x, y;
  while (1)
  {
    printf("请输入您要排查的坐标(用空格分隔):");
    scanf_s("%d %d", &x, &y);
    if (show[x][y] == '*' && x > 0 && x <= row && y > 0 && y <= col)
    {
      if (mine[x][y] == '1')
      {
        printf("很遗憾,排雷失败\n");
        BoardDisplay(mine, row, col);
        return;
      }
      else
      {
        show[x][y] = MineNumber(mine, x, y) + '0';
        if (MineFinish(show, row,col))
        {
          printf("恭喜你,排雷成功\n");
          BoardDisplay(mine, row, col);
          return;
        }
        BoardDisplay(show, row, col);
      }
    }
    else if (show[x][y] != '*' && x > 0 && x <= row && y > 0 && y <= col)
    {
      printf("该位置已经被检查,请重新输入:\n");
      BoardDisplay(show, row, col);
    }
    else
    {
      printf("坐标非法,请重新输入:\n");
      BoardDisplay(show, row, col);
    }
  }
}
int MineNumber(char board[][COLS], int x, int y)
{
  return (board[x][y - 1] + board[x][y + 1]
    + board[x - 1][y] + board[x - 1][y - 1] + board[x - 1][y + 1]
    + board[x + 1][y] + board[x + 1][y - 1] + board[x + 1][y + 1]
    - 8 * '0');
}
bool MineFinish(char board[][COLS], int row, int col)
{
  int count = 0;
  for(int i = 1; i <= row; i++)
    for (int j = 1; j <= col; j++)
    {
      if (board[i][j] != '*')
      {
        count++;
        if (count == row * col - MINENUMBER)
          return true;
      }
    }
  return false;
}
int main()
{
  int input;
  meau(); //展示选择菜单
  printf("请输入您的选择:");
  while (1)
  {
    scanf_s("%d", &input);
    switch (input)
    {
    case 1:
      game();
      break;
    case 0:
      printf("退出游戏,感谢游玩\n");
      break;
    default :
      printf("输入错误,请重新输入:");
      break;
    }
    meau();
    printf("是否重新游玩:");
  }
  return 0;
}

拓展功能

简化游戏界面

  • 根据上面的展示我们可以看到,我们每排查一次,展示数组就要打印一次,这样就会使得游戏界面太过复杂
  • 我们可以使用system(“cls”)函数来清除已经不需要的打印结果
  • 注:要包含头文件
  • 修改后的MineFind()函数:
void MineFind(char mine[][COLS], char show[][COLS], int row, int col)
{
  int x, y;
  while (1)
  {
    printf("请输入您要排查的坐标(用空格分隔):");
    scanf_s("%d %d", &x, &y);
        //就是多了这样一条语句
    system("cls");
    if (show[x][y] == '*' && x > 0 && x <= row && y > 0 && y <= col)
    {
      if (mine[x][y] == '1')
      {
        printf("很遗憾,排雷失败\n");
        BoardDisplay(mine, row, col);
        return;
      }
      else
      {
        show[x][y] = MineNumber(mine, x, y) + '0';
        if (MineFinish(show, row,col))
        {
          printf("恭喜你,排雷成功\n");
          BoardDisplay(mine, row, col);
          return;
        }
        BoardDisplay(show, row, col);
      }
    }
    else if (show[x][y] != '*' && x > 0 && x <= row && y > 0 && y <= col)
    {
      printf("该位置已经被检查,请重新输入:\n");
      BoardDisplay(show, row, col);
    }
    else
    {
      printf("坐标非法,请重新输入:\n");
      BoardDisplay(show, row, col);
    }
  }
}
  • 实现效果:

改变字体颜色

  • 为了将坐标数字和代表地雷个数的数字作出区分,我们可以改变这两种数字的颜色
  • 如果对如何改变字体颜色和背景色还不是太了解,可以先看看C语言——修改控制台背景色和字体颜色这篇博客
  • 直接上代码(只需要调整打印数组的函数BoardDisplay且在主函数最开始加上system(“color”)函数即可)
int main()
{
    system("color 17");
    ………………;
}
void BoardDisplay(char board[][COLS], int row, int col)
{
  for (int i = 0; i <= col; i++)
  {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4 | 16);
    printf("%d ", i);
  }
  printf("\n");
  for (int i = 1; i <= row; i++)
  {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4 | 16);
    printf("%d ", i);
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7 | 16);
    for (int j = 1; j <= col; j++)
      printf("%c ", board[i][j]);
    printf("\n");
  }
}
  • 看看效果:


相关文章
|
1月前
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
83 0
|
3月前
|
机器学习/深度学习 C语言
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
【8月更文挑战第5天】本篇文章用C语言采用多文件编写实现了一个基础的扫雷游戏(附源码),并讲解了关于函数递归的基础概念及其相对应的习题练习(附源码)
41 1
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
|
2月前
|
存储 安全 算法
C 语言——实现扫雷小游戏
本文介绍了使用二维数组创建棋盘并实现扫雷游戏的方法。首先,通过初始化数组创建一个9x9的棋盘,并添加行列标识以便操作。接着,利用随机数在棋盘上布置雷。最后,通过判断玩家输入的坐标来实现扫雷功能,包括显示雷的数量和处理游戏胜利或失败的情况。文中提供了完整的代码实现。
43 1
C 语言——实现扫雷小游戏
|
1月前
|
存储 算法 安全
C语言实现扫雷游戏
C语言实现扫雷游戏
|
1月前
|
C语言
初学者指南:使用C语言实现简易版扫雷游戏
初学者指南:使用C语言实现简易版扫雷游戏
34 0
|
1月前
|
C语言
C语言扫雷游戏(详解)
C语言扫雷游戏(详解)
38 0
|
1月前
|
存储 编译器 C语言
【C语言篇】数组和函数的实践:扫雷游戏(附源码)
【C语言篇】数组和函数的实践:扫雷游戏(附源码)
35 0
|
3月前
|
C语言
扫雷(C语言)
扫雷(C语言)
43 4
|
4月前
|
存储 编译器 C语言
|
5月前
|
C语言
【海贼王编程冒险 - C语言海上篇】怎样用C语言实现简单的扫雷游戏?
【海贼王编程冒险 - C语言海上篇】怎样用C语言实现简单的扫雷游戏?
31 1