C语言扫雷小游戏实现

简介: C语言扫雷小游戏实现

1.游戏主逻辑

游戏我创建了三个文件来完成,便于分工和包装,分别是头文件game.h用来存放函数声明和库函数,test.c用来编写游戏主逻辑,以及game.c用来编写是实现整个游戏的函数

1.1创建游戏菜单以及开始选项

游戏至少玩一次,还可以继续玩,所以用do while循环实现主逻辑,首先打印一个菜单,用switch语句给玩家两个选项:1.开始游戏,2.退出游戏,输入其他提示输入错误重新输入。

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
  {
    //打印菜单
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      printf("开始游戏\n");
      play_game();
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("选择错误,请重新选择:>\n");
      break;
    }
  } while (input);
  return 0;
}

1.2游戏规则和思路

游戏规则:输入要排查的坐标,会显示以该坐标为中心的周围8个格子内的雷的个数,如果排查的位置是雷则游戏失败,排查完所有的雷即游戏成功。

游戏思路:根据规则就需要我们首先来初始化并打印一个棋盘,在棋盘中随机置雷,让玩家来输入坐标排雷,据此来判断坐标周围雷的个数有以及游戏的成败。

1.3游戏主逻辑代码实现

1.3.1棋盘越界问题

这里我们要考虑一下判断时的棋盘越界问题,看图:

97652c4457814ba48201c4489d154e45.png

这里咱想到一种解决方法,那就是初始化时使用11*11的棋盘,而在使用和在屏幕上显示时使用9*9的棋盘,这样就不用考虑越界问题了,如下图:

faa58a91896842c98fa25bed837b1eef.png

1.3.2设置置雷棋盘和排雷棋盘

用户每排查一个坐标次我们都需要将棋盘打印出来让用户观察该坐标周围有几个雷的情况,如果这样的话一旦我们将棋盘打印出来那么所有的雷不就暴露了吗?为了解决这一问题,我使用了两个棋盘,一个置雷棋盘用0来初始化用1来布置雷(0表示非雷,1表示有雷),一个排雷棋盘用*来初始化给用户观察,根据输入的坐标在置雷棋盘中判断,然后将数字在排雷棋盘中显示出来,其他位置依旧是全*覆盖,这样就能很好的解决这一问题

解决了上面这两个问题我们就可以来初始化棋盘了

1.3.3初始化棋盘

创建两个数组存放信息

//设置两个数组存放信息
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };

行和列在头文件中用#define来定义:

//9*9棋盘
#define ROW 9
#define COL 9
//11*11棋盘
#define ROWS ROW+2
#define COLS COL+2

初始化棋盘:

置雷棋盘全部初始化为0,排雷棋盘全部初始化为*,共用一个初始化数组

//初始化棋盘
void init_board(char board[ROWS][COLS],int rows,int cols,int set)
{
  int i = 0;
  int j = 0;
  for (i = 0; i < rows; i++)
  {
    for (j = 0; j < cols; j++)
    {
      board[i][j] = set;
    }
  }
}
//初始化置雷棋盘
init_board(mine, ROWS, COLS, '0');
//初始化排雷棋盘
init_board(show, ROWS, COLS, '*');

1.3.4布置雷

要实现随机布置雷,这里需要使用随机值调用rand()函数,要用到srand()随机生成器,这个生成器只需要调用一次,所以放在main()函数开头不必进入循环,这里要注意加一个该坐标是否被占用的判断,没有就将该坐标赋值为1,反之则重新随机布置

void set_mine(char mine[ROWS][COLS], int row, int col)//9*9
{
  //随机布10个雷
  int count = EASY_COUNT;
  while (count)
  {
    //在11*11的棋盘中给9*9棋盘布置雷,所以横纵坐标都+1
    int x = rand() % row + 1;
    int y = rand() % col + 1;
    //判断该坐标是否被占用,没有的话就赋值'1'表示有雷
    if (mine[x][y] == '0')
    {
      mine[x][y] = '1';
      count--;
    }
  }
}

1.3.5打印排雷棋盘

我们将棋盘整的尽量整洁美观便于用户观察,像这样:

5af29b59d23e4903b99fe87e26c07ac8.png

具体代码实现:

void display_board(char board[ROWS][COLS], int row, int col)
{
  int i = 0;
  int j = 0;
  //列号
  for (j=0;j<=col;j++)
  {
    printf("%d ", j);
  }
  printf("\n");
  for (i = 1; i <= row; i++)
  {
    //行号
    printf("%d ", i);
    //排雷棋盘
    for (j = 1; j <= col; j++)
    {
      printf("%c ", board[i][j]);
    }
    printf("\n");
  }
}

1.3.6排查雷

我们需要注意几个点:1.判断坐标是否越界;2.判断坐标是否被排查过;3.判断所排查的坐标周围有几个雷;4.每排查一次都需要打印一遍置雷棋盘方便用户观察

这里我们重点讲一下实现第三点:由于咱们是用0来初始化用1来布置雷,这里将想要排查的坐标的周围的8个坐标的值相加再减去8 * '0'就可以得到周围雷的个数将其赋给想要排查的坐标打印出来就完成了。

具体代码实现:

//判断坐标周围有几个雷
int get_mine_count(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 find_mine(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);
    //判断是否越界(9*9)
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      //判断坐标是否被排查过
      if (show[x][y] == '*')
      {
        if (mine[x][y] == '1')
        {
          printf("很遗憾,你被炸死了\n");
          //打印一遍置雷棋盘
          display_board(mine, ROW, COL);
          break;
        }
        else
        {
          //判断坐标周围有几个雷
          int count = get_mine_count(mine, x, y);
          show[x][y] = count + '0';
          //打印一遍排雷棋盘
          display_board(show, ROW, COL);
          win++;
        }
      }
      else
      {
        printf("该坐标已经被排查过了\n");
      }
    }
    else
    {
      printf("坐标非法,请重新输入\n");
    }
    //排完雷则游戏结束
    if (win == row * col - EASY_COUNT)
    {
      printf("恭喜你,扫雷成功!\n");
      display_board(mine, ROW, COL);
    }
  }
}

2.整个游戏代码

2.1game.h 函数声明和库函数

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//9*9棋盘
#define ROW 9
#define COL 9
//11*11棋盘
#define ROWS ROW+2
#define COLS COL+2
//设置雷的个数
#define EASY_COUNT 10
//初始化棋盘
void init_board(char board[ROWS][COLS], int rows, int cols, int set);
//打印棋盘
void display_board(char board[ROWS][COLS], int row, int col);
//布置雷
void set_mine(char mine[ROWS][COLS], int row, int col); 
//排查雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

2.2test.c 游戏主逻辑

#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()
{
  printf("**********************************\n");
  printf("********      1.play      ********\n");
  printf("********      0.exit      ********\n");
  printf("**********************************\n");
}
void play_game()
{
  //设置两个数组存放信息
  char mine[ROWS][COLS] = { 0 };
  char show[ROWS][COLS] = { 0 };
  //初始化棋盘
  //将mine初始化为全'0',将show初始化为全'*'
  //直接将'0'和'*'传入函数,用char类型接收,,方便一个函数初始化两个数组
  init_board(mine, ROWS, COLS, '0');
  init_board(show, ROWS, COLS, '*');
  //打印棋盘
  //布置雷
  set_mine(mine, ROW, COL);
  //排查雷
  display_board(show, ROW, COL);
  find_mine(mine, show, ROW, COL);
}
int main()
{
  int input = 0;
  srand((unsigned int)time(NULL));
  do
  {
    //打印菜单
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      printf("开始游戏\n");
      play_game();
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("选择错误,请重新选择:>\n");
      break;
    }
  } while (input);
  return 0;
}

2.3game.c 游戏函数实现

#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
//初始化棋盘
void init_board(char board[ROWS][COLS],int rows,int cols,int set)
{
  int i = 0;
  int j = 0;
  for (i = 0; i < rows; i++)
  {
    for (j = 0; j < cols; j++)
    {
      board[i][j] = set;
    }
  }
}
//打印棋盘
void display_board(char board[ROWS][COLS], int row, int col)
{
  int i = 0;
  int j = 0;
  //列号
  for (j=0;j<=col;j++)
  {
    printf("%d ", j);
  }
  printf("\n");
  for (i = 1; i <= row; i++)
  {
    //行号
    printf("%d ", i);
    //排雷棋盘
    for (j = 1; j <= col; j++)
    {
      printf("%c ", board[i][j]);
    }
    printf("\n");
  }
}
//布置雷
void set_mine(char mine[ROWS][COLS], int row, int col)//9*9
{
  //随机布10个雷
  int count = EASY_COUNT;
  while (count)
  {
    //在11*11的棋盘中给9*9棋盘布置雷,所以横纵坐标都+1
    int x = rand() % row + 1;
    int y = rand() % col + 1;
    //判断该坐标是否被占用,没有的话就赋值'1'表示有雷
    if (mine[x][y] == '0')
    {
      mine[x][y] = '1';
      count--;
    }
  }
}
//判断坐标周围有几个雷
int get_mine_count(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 find_mine(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);
    //判断是否越界(9*9)
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      //判断坐标是否被排查过
      if (show[x][y] == '*')
      {
        if (mine[x][y] == '1')
        {
          printf("很遗憾,你被炸死了\n");
          //打印一遍置雷棋盘
          display_board(mine, ROW, COL);
          break;
        }
        else
        {
          //判断坐标周围有几个雷
          int count = get_mine_count(mine, x, y);
          show[x][y] = count + '0';
          //打印一遍排雷棋盘
          display_board(show, ROW, COL);
          win++;
        }
      }
      else
      {
        printf("该坐标已经被排查过了\n");
      }
    }
    else
    {
      printf("坐标非法,请重新输入\n");
    }
    //排完雷则游戏结束
    if (win == row * col - EASY_COUNT)
    {
      printf("恭喜你,扫雷成功!\n");
      display_board(mine, ROW, COL);
    }
  }
}

整个小游戏到这里就结束,友友们喜欢的话不妨来个关注加三连支持一下,后期会持续更新C语言干货!

目录
相关文章
|
19天前
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
61 0
|
3月前
|
机器学习/深度学习 C语言
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
【8月更文挑战第5天】本篇文章用C语言采用多文件编写实现了一个基础的扫雷游戏(附源码),并讲解了关于函数递归的基础概念及其相对应的习题练习(附源码)
39 1
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
|
19天前
|
C语言 C++
【C语言】编写“猜数字“小游戏
【C语言】编写“猜数字“小游戏
|
2月前
|
定位技术 API C语言
C语言——实现贪吃蛇小游戏
本文介绍了一个基于Windows控制台的贪吃蛇游戏的实现方法。首先,需调整控制台界面以便更好地显示游戏。接着,文章详细描述了如何使用Win32 API函数如`COORD`、`GetStdHandle`、`GetConsoleCursorInfo`等来控制控制台的光标和窗口属性。此外,还介绍了如何利用`GetAsyncKeyState`函数实现键盘监听功能。文中还涉及了`&lt;locale.h&gt;`库的使用,以支持本地化字符显示。
51 1
C语言——实现贪吃蛇小游戏
|
2月前
|
存储 安全 算法
C 语言——实现扫雷小游戏
本文介绍了使用二维数组创建棋盘并实现扫雷游戏的方法。首先,通过初始化数组创建一个9x9的棋盘,并添加行列标识以便操作。接着,利用随机数在棋盘上布置雷。最后,通过判断玩家输入的坐标来实现扫雷功能,包括显示雷的数量和处理游戏胜利或失败的情况。文中提供了完整的代码实现。
40 1
C 语言——实现扫雷小游戏
|
24天前
|
C语言 定位技术 API
【C语言】实践:贪吃蛇小游戏(附源码)(二)
【C语言】实践:贪吃蛇小游戏(附源码)
【C语言】实践:贪吃蛇小游戏(附源码)(二)
|
27天前
|
C语言 开发者
C语言实现猜数字小游戏(详细教程)
C语言实现猜数字小游戏(详细教程)
|
26天前
|
存储 算法 安全
C语言实现扫雷游戏
C语言实现扫雷游戏
|
20天前
|
C语言
初学者指南:使用C语言实现简易版扫雷游戏
初学者指南:使用C语言实现简易版扫雷游戏
27 0
|
21天前
|
C语言
C语言扫雷游戏(详解)
C语言扫雷游戏(详解)
32 0