数组(3)

简介: 数组(3)


10. 扫雷游戏

三子棋思路类似,先把整个游戏的大体结构实现出来:

//game.h
#include <stdio.h>
//test.c
#include "game.h"
void menu()
{
  printf("***************************\n");
  printf("*****     1. play     *****\n");
  printf("*****     0. exit     *****\n");
  printf("***************************\n");
}
int main()
{
  int input = 0;
  do
  {
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      game();
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("选择错误,重新选择\n");
      break;
    }
  } while (input);
  return 0;
}

接下来,我们需要对游戏内容进行具体地实现:

分析:我们需要一个数组来存放布置好的雷,我们用1表示雷,0表示非雷;而我们在排查雷的时候,如果该坐标不是雷,需要显示它周围有多少个雷,那么如果有一个雷,这里的1和表示是雷的1就会让人产生歧义,所以我们还需要一个数组来用来排查雷,这个数组一开始全部用‘*’表示,那么为了两个数组能使用同一个函数,存放布置好的雷的数组可以定义为字符数组,‘1’表示雷,‘0’表示非雷。在排查雷的时候,如果该坐标在最边上,那么它周围的八个坐标中有一部分越界了,所以我们可以在边界外再加上一圈。


  1. 初始化棋盘
//game.h
#include <stdio.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//game.c
#include "game.h"
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
  int i = 0;
  for (i = 0; i < rows; i++)
  {
    int j = 0;
    for (j = 0; j < cols; j++)
    {
      board[i][j] = set;
    }
  }
  
}
//test.c
#include "game.h"
void game()
{
  char mine[ROWS][COLS];//存放布置好的雷
  char show[ROWS][COLS];//存放排查出的雷的信息
  //初始化棋盘
  //1. mine数组最开始是全'0'
  //2. show数组最开始是全'*'
  InitBoard(mine, ROWS, COLS, '0');
  InitBoard(show, ROWS, COLS, '*');
}

  1. 打印棋盘
//game.h
#include <stdio.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//game.c
#include "game.h"
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
  int i = 0;
  printf("------扫雷游戏------\n");
  for (i = 0; i <= col; i++)
  {
    printf("%d ", i);
  }
  printf("\n");
  for (i = 1; i <= row; i++)
  {
    int j = 0;
    printf("%d ", i);
    for (j = 1; j <= col; j++)
    {
      printf("%c ", board[i][j]);
    }
    printf("\n");
  }
}
//test.c
#include "game.h"
void game()
{
  char mine[ROWS][COLS];//存放布置好的雷
  char show[ROWS][COLS];//存放排查出的雷的信息
  //初始化棋盘
  //1. mine数组最开始是全'0'
  //2. show数组最开始是全'*'
  InitBoard(mine, ROWS, COLS, '0');
  InitBoard(show, ROWS, COLS, '*');
  //打印棋盘
  //DisplayBoard(mine, ROW, COL);
  DisplayBoard(show, ROW, COL);
}

  1. 布置雷
//game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define EASY_COUNT 10
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col);
//game.c
#include "game.h"
void SetMine(char board[ROWS][COLS], int row, int col)
{
  //布置10个雷
  //生成随机的坐标,布置雷
  int count = EASY_COUNT;
  while (count)
  {
    int x = rand() % row + 1;
    int y = rand() % col + 1;
    if ('0' == board[x][y])
    {
      board[x][y] = '1';
      count--;
    }
  }
}
//test.c
#include "game.h"
void game()
{
  char mine[ROWS][COLS];//存放布置好的雷
  char show[ROWS][COLS];//存放排查出的雷的信息
  //初始化棋盘
  //1. mine数组最开始是全'0'
  //2. show数组最开始是全'*'
  InitBoard(mine, ROWS, COLS, '0');
  InitBoard(show, ROWS, COLS, '*');
  //打印棋盘
  //DisplayBoard(mine, ROW, COL);
  DisplayBoard(show, ROW, COL);
  //1. 布置雷
  SetMine(mine, ROW, COL);
  //DisplayBoard(mine, ROW, COL);
}
int main()
{
  srand((unsigned int)time(NULL));
  return 0;
}

  1. 排查雷
//game.h
#include <stdio.h>
#define EASY_COUNT 10
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//game.c
#include "game.h"
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
  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');
}
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-EASY_COUNT))
  {
    printf("请输入要排查的坐标:>");
    scanf("%d %d", &x, &y);
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      
      if ('1' == mine[x][y])
      {
        printf("很遗憾,你被炸死了\n");
        DisplayBoard(mine, ROW, COL);
        break;
      }
      else
      {
        //该位置不是雷,就统计这个坐标周围有几个雷
        int count = GetMineCount(mine, x, y);
        show[x][y] = count + '0';
        DisplayBoard(show, ROW, COL);
        win++;
      }
    }
    else
    {
      printf("坐标非法,重新输入\n");
    }
  }
  if ((row * col - EASY_COUNT) == win)
  {
    printf("恭喜你,排雷成功\n");
    DisplayBoard(mine, ROW, COL);
  }
}

那么,我们能不能做到输入一个坐标,如果不是雷的话,它就可以展开一片呢?

这是可以做到的,但是我们需要用到递归。

展开的条件:

  1. 该坐标不是雷
  2. 该坐标周围没有雷
  3. 该坐标没有被排查过
//game.c
#include "game.h"
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
  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');
}
void Expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
  if ('*' == show[x][y])
  {
    int count = GetMineCount(mine, x, y);
    if (count != 0)
    {
      show[x][y] = count + '0';
    }
    else
    {
      show[x][y] = ' ';
      Expand(mine, show, x - 1, y - 1);
      Expand(mine, show, x - 1, y);
      Expand(mine, show, x - 1, y + 1);
      Expand(mine, show, x, y - 1);
      Expand(mine, show, x, y + 1);
      Expand(mine, show, x + 1, y - 1);
      Expand(mine, show, x + 1, y);
      Expand(mine, show, x + 1, y + 1);
    }
  }
  
}
int IsWin(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
  int i = 0;
  for (i = 1; i <= row; i++)
  {
    int j = 0;
    for (j = 1; j <= col; j++)
    {
      
      if ('*' == show[i][j] && '0' == mine[i][j])
      {
        return 0;
      }
    }
  }
  return 1;
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
  int x = 0;
  int y = 0;
  int ret = 0;
  while (0 == ret)
  {
    printf("请输入要排查的坐标:>");
    scanf("%d %d", &x, &y);
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      if ('1' == mine[x][y])
      {
        printf("很遗憾,你被炸死了\n");
        DisplayBoard(mine, ROW, COL);
        break;
      }
      else
      {
        Expand(mine, show, x, y);
        DisplayBoard(show, ROW, COL);
        ret = IsWin(mine, show, ROW, COL);
      }
    }
    else
    {
      printf("坐标非法,重新输入\n");
    }
  }
  if (1 == ret)
  {
    printf("恭喜你,排雷成功\n");
    DisplayBoard(mine, ROW, COL);
  }
}
//test.c
#include "game.h"
void game()
{
  char mine[ROWS][COLS];//存放布置好的雷
  char show[ROWS][COLS];//存放排查出的雷的信息
  //初始化棋盘
  //1. mine数组最开始是全'0'
  //2. show数组最开始是全'*'
  InitBoard(mine, ROWS, COLS, '0');
  InitBoard(show, ROWS, COLS, '*');
  //打印棋盘
  //DisplayBoard(mine, ROW, COL);
  DisplayBoard(show, ROW, COL);
  //1. 布置雷
  SetMine(mine, ROW, COL);
  //DisplayBoard(mine, ROW, COL);
  //2. 排查雷
  FindMine(mine, show, ROW, COL);
}

完整代码:

//game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define EASY_COUNT 10
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
//初始化棋盘
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);
//game.c
#include "game.h"
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
  int i = 0;
  for (i = 0; i < rows; i++)
  {
    int j = 0;
    for (j = 0; j < cols; j++)
    {
      board[i][j] = set;
    }
  }
  
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
  int i = 0;
  printf("------扫雷游戏------\n");
  for (i = 0; i <= col; i++)
  {
    printf("%d ", i);
  }
  printf("\n");
  for (i = 1; i <= row; i++)
  {
    int j = 0;
    printf("%d ", i);
    for (j = 1; j <= col; j++)
    {
      printf("%c ", board[i][j]);
    }
    printf("\n");
  }
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
  //布置10个雷
  //生成随机的坐标,布置雷
  int count = EASY_COUNT;
  while (count)
  {
    int x = rand() % row + 1;
    int y = rand() % col + 1;
    if ('0' == board[x][y])
    {
      board[x][y] = '1';
      count--;
    }
  }
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
  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');
}
void Expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
  if ('*' == show[x][y])
  {
    int count = GetMineCount(mine, x, y);
    if (count != 0)
    {
      show[x][y] = count + '0';
    }
    else
    {
      show[x][y] = ' ';
      Expand(mine, show, x - 1, y - 1);
      Expand(mine, show, x - 1, y);
      Expand(mine, show, x - 1, y + 1);
      Expand(mine, show, x, y - 1);
      Expand(mine, show, x, y + 1);
      Expand(mine, show, x + 1, y - 1);
      Expand(mine, show, x + 1, y);
      Expand(mine, show, x + 1, y + 1);
    }
  }
  
}
int IsWin(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
  int i = 0;
  for (i = 1; i <= row; i++)
  {
    int j = 0;
    for (j = 1; j <= col; j++)
    {
      
      if ('*' == show[i][j] && '0' == mine[i][j])
      {
        return 0;
      }
    }
  }
  return 1;
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
  int x = 0;
  int y = 0;
  int ret = 0;
  while (0 == ret)
  {
    printf("请输入要排查的坐标:>");
    scanf("%d %d", &x, &y);
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      if ('1' == mine[x][y])
      {
        printf("很遗憾,你被炸死了\n");
        DisplayBoard(mine, ROW, COL);
        break;
      }
      else
      {
        Expand(mine, show, x, y);
        DisplayBoard(show, ROW, COL);
        ret = IsWin(mine, show, ROW, COL);
      }
    }
    else
    {
      printf("坐标非法,重新输入\n");
    }
  }
  if (1 == ret)
  {
    printf("恭喜你,排雷成功\n");
    DisplayBoard(mine, ROW, COL);
  }
}
//test.c
#include "game.h"
void menu()
{
  printf("***************************\n");
  printf("*****     1. play     *****\n");
  printf("*****     0. exit     *****\n");
  printf("***************************\n");
}
void game()
{
  char mine[ROWS][COLS];//存放布置好的雷
  char show[ROWS][COLS];//存放排查出的雷的信息
  //初始化棋盘
  //1. mine数组最开始是全'0'
  //2. show数组最开始是全'*'
  InitBoard(mine, ROWS, COLS, '0');
  InitBoard(show, ROWS, COLS, '*');
  //打印棋盘
  //DisplayBoard(mine, ROW, COL);
  DisplayBoard(show, ROW, COL);
  //1. 布置雷
  SetMine(mine, ROW, COL);
  //DisplayBoard(mine, ROW, COL);
  //2. 排查雷
  FindMine(mine, show, ROW, COL);
}
int main()
{
  int input = 0;
  srand((unsigned int)time(NULL));
  do
  {
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      game();
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("选择错误,重新选择\n");
      break;
    }
  } while (input);
  return 0;
}


目录
相关文章
|
5月前
|
存储 C语言
|
19天前
|
存储 索引
数组的特点
数组是一种线性数据结构,用于存储固定大小的顺序集合。每个元素在数组中都有一个唯一的索引,可以快速访问和修改。数组支持随机访问,但插入和删除操作较慢,因为需要移动后续元素。适用于需要频繁读取数据的场景。
|
20天前
关于数组的两个应用
关于数组的两个应用
23 0
关于数组的两个应用
|
6月前
|
存储 搜索推荐 算法
C数组
C数组
34 0
|
6月前
|
存储 搜索推荐 程序员
C++ 数组
C++ 数组
44 0
|
存储 C语言 索引
C 数组
C 数组。
38 0
|
6月前
|
程序员 索引
C 中数组详解
C 中数组详解。
32 3
|
6月前
|
存储 程序员 C++
c++数组详细介绍(一)
前言 深入理解C++的数组和字符串是成为熟练C++程序员的重要一步。本文将探索C++中数组和字符串的基本概念,从基础到进阶,包括数组的声明、初始化、访问和多维数组的操作,以及字符串类的使用和与字符数组的转换。还将涉及异常处理、动态内存分配、STL中的其他容器、常用字符串操作。
106 0
|
6月前
|
存储 JavaScript 前端开发
数组
数组
56 0
数组相关练习
数组相关练习
52 0