手把手超详细教学用c语言实现扫雷小游戏

简介: 手把手超详细教学用c语言实现扫雷小游戏

1.分析问题需求和大致思路

       在开始设计之前,我们先分析一下,扫雷游戏大家可能都玩过,基本的信息都是呈现在一个10*10的方格上的。开始时我们应该打印一个菜单,让玩家选择是否进行游戏。

       然后是初始化的问题,用二维数组来的格子里面的信息的话,刚好非常契合,确定了用数组来存储以后,我们就可以思考一下怎么做初始化,我们可以用3种不同的符号来表示棋盘上的状态,没被玩家排查之前用#表示,在玩家查找以后要输出周围有多少炸弹,呈现出一个整数,呈现在屏幕上的是这些符号,因此我们在创建数组时就得注意用char型。具体的存储信息如下图:

       在完成初始化之后,我们要生成随机的地雷位置,可以用rand函数和srand函数以及time函数来保证生成数的随机性。对于以上3个函数有不了解的小伙伴们欢迎点击博主的这篇文章,里面对以上函数有非常详细的介绍和讲解:C语言实现猜数字小游戏以及如何生成真正的随机数

 在将地雷布置完成后,我们就可以构思扫雷部分的逻辑了,首先由玩家输入一个坐标,然后计算机进行判断,输入位置是否合法是否合理,在确认输入合理后,对玩家输入的坐标进行判断,如果有炸弹,就弹出失败的界面,然后退出游戏,如果没有炸弹,就使用一个函数来统计周围炸弹的数量并且打印出来,然后对以上做循环的封装处理,直到游戏胜利或者失败才跳出循环,完成循环后,我们就需要解决如何定义游戏胜利的条件,我们可以用所有的格子减去已经排除的格子,再减去剩余的炸弹数,也就是进行是否已经将所有格子排查的判断,在最后只剩10个炸弹时,结束游戏,跳出循环。


       为了保证程序的健全性和可读性,我们采用多文件的方法实现扫雷小游戏。用game.h存储头文件信息以及宏定义和函数声明,用board.c文件存储游戏里面的基本逻辑函数,用game.c文件存储游戏的主要功能以及主体

2.游戏主体逻辑实现以及代码

       这里#include包含的头文件是我们自定义的头文件,里面有我们需要的头文件和函数声明,首先我们定义一个input输入实现记录玩家对于是否开始游戏的选择,用do...while...循环来实现先运行循环体让玩家决定是否进入游戏,在判断玩家的输入,以便于让玩家重复输入以及重复的游玩游戏,其中的srand函数是生成随机数的种子,后文中会提及到,这里就不再继续赘述

include "game.h"
void game()
{
  char bomb[ROWS][COLS] = { 0 };
  char show[ROWS][COLS] = { 0 };
  //初始化棋盘
  initboard(bomb, ROWS, COLS, '0');
  initboard(show, ROWS, COLS, '#');
  //打印棋盘
  printboard(show, ROW, COL);
  //生成随机炸弹位置
  setbombs(bomb, ROWS, COLS);
  //开始扫雷
  findbombs(bomb, show, ROW, COL);
}
int main()
{
  int input = 0;
  srand((unsigned int)time(NULL));
  printf("请进行输入确认是否开始游戏\n");
  do
  {
    mune();//打印菜单
    scanf("%d", &input);
    switch(input)
    {
    case 1:
      printf("\t开始游戏\n");
      game();
      break;
    case 2:
      printf("\t退出游戏\n");
      break;
    default:
      printf("非法输入,请重试\n");
      break;
    }
  } while (input != 2);
  return 0;
}

3.游戏的初始化

       我们用俩个二维数组来做记录,一个用来保存我们实际上的地雷存储位置,一个用来打印在屏幕上让玩家观看,俩个数组同等大小,之所以使用11行和9行是为了方便后面判断周围的炸弹数,也是方便后面进行交换打印等等操作,但是实际上对玩家展示的只有1~9行和列,也就是最外边一圈不展示。这里利用传的参数(char ret)不同,来实现对俩个数组进行不同的初始化。至于ROW, ROWS, COL, COLS则是我们为了方便使用以及后期修改,对于行和列进行的宏定义

//定义行和列
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
  //初始化棋盘
  initboard(bomb, ROWS, COLS, '0');
  initboard(show, ROWS, COLS, '#');
//初始化
void initboard(char board[ROWS][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;
    }
  }
}

4.地雷位置的随机生成

       还是这张图,我们是只需要使用中间部分的格子的,也就是1~9行以及1~9列,所以在放置炸弹时需要注意,不能放在外围去了

rand函数对9取模,随机数的范围就成了0~8,加上1刚好就是1~9,将值付给xy就得到了随机的坐标,while循环则可以反复的判断在放置地雷之前得先判断这个位置是否为空,再用count计数保证放置10个炸弹

//宏定义炸弹的个数
#define bomb_count 10
//生成随机炸弹位置
void setbombs(char board[ROWS][COLS],int row,int col);
//随机生成地雷位置
void setbombs(char board[ROWS][COLS], int row, int col)
{
  int x = 0;
  int y = 0;
  int count = bomb_count;
  while (count > 0)
  {
    x = rand() % 9 + 1;
    y = rand() % 9 + 1;
    if (board[x + 1][y + 1] == '0')
    {
      board[x + 1][y + 1] = '1';
      count--;
    }
  }
}

5.打印棋盘

玩家是需要看见棋盘长什么样的,要给玩家提供一个可视化的界面,实现如下:

//打印棋盘
void printboard(char board[ROWS][COLS], int row, int col)
{
  printf("------扫雷游戏------\n");
  printf(" ");
  for (int i = 1; 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");
  }
  printf("------扫雷游戏------\n");
}

6.扫雷

       做好好一切准备工作后,就可以开始正式的扫雷了,首先让玩家输入一个坐标,用x和y进行保存记录,然后判断这个坐标是否在9*9的格子里面,如果不在就让玩家重新输入,可以用while循环实现重复的过程,拿到这个坐标以后判断是否踩雷,如果踩雷则弹出被炸死的信息,然后打印炸弹的位置,结束游戏,如果没有,则用一个函数来计算周围有多少个炸弹,定义个整数win来统计已经判断安全的位置,最后用所有的格子数减去炸弹数,再让win和这个数比较,就可以得到是否已经全部盘查完毕,如果是,就宣布游戏胜利,结束游戏,如果没有排查完,就继续游戏继续排查

//扫雷
void findbombs(char bombs[ROWS][COLS],char show[ROWS][COLS], int row, int col)
{
  int x = 0;
  int y = 0;
  int win = 0;
  while (win<(row*col- bomb_count))
  {
    printf("请输入你想排查的坐标: ");
    scanf("%d %d", &x, &y);
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      if (bombs[x][y] == '1')
      {
        printf("你被炸弹炸死了\n");
        printboard(bombs, ROW, COL);
        break;
      }
      else
      {
        int count = countbombs(bombs, x, y);
        show[ x ][ y ] = count + '0';
        printboard(show, ROW, COL);
        win++;
      }
    }
    else
    {
      printf("输入坐标不合法,请重新输入\n");
    }
  }
  if (win == (row * col - bomb_count))
  {
    printf("恭喜你,排掉了全部的炸弹,游戏胜利!!!\n");
    printboard(bombs, ROW, COL);
  }
}

这里我们定义一个函数来判断周围炸弹数量

//统计周围炸弹数量
int countbombs(char bombs[ROWS][COLS], int x, int y)
{
  int ret = 0;
  ret=bombs[x - 1][y - 1] + bombs[x - 1][y] + bombs[x - 1][y + 1] + bombs[x][y - 1] + bombs[x][y + 1] + bombs[x + 1][y - 1] + bombs[x + 1][y] + bombs[x + 1][y + 1] - 8 * '0';
  return ret;
}

 以上就完成了扫雷游戏的绝大部分内容,剩下的只需要稍微拼接,修补一下就可以得到完整的程序代码,以下完整的一下代码奉上

7.游戏的完整代码

1.头文件代码

#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>
//定义行和列
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define bomb_count 10
//打印菜单
void mune();
//游戏逻辑主程序
void game();
//棋盘初始化
void initboard(char board[ROWS][COLS],int row,int col,char temp);
//打印棋盘
void printboard(char board[ROWS][COLS], int row, int col);
//生成随机炸弹位置
void setbombs(char board[ROWS][COLS],int row,int col);
//扫雷
void findbombs(char bombs[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//统计周围炸弹数量
int countbombs(char bombs[ROWS][COLS], int x, int y);

2.游戏逻辑代码

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//打印菜单
void mune()
{
  printf("--------------------------\n");
  printf("---------1.Play ----------\n");
  printf("--------------------------\n");
  printf("---------2.Esc  ----------\n");
  printf("--------------------------\n");
}
//初始化
void initboard(char board[ROWS][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 printboard(char board[ROWS][COLS], int row, int col)
{
  printf("------扫雷游戏------\n");
  printf(" ");
  for (int i = 1; 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");
  }
  printf("------扫雷游戏------\n");
}
//随机生成地雷位置
void setbombs(char board[ROWS][COLS], int row, int col)
{
  int x = 0;
  int y = 0;
  int count = bomb_count;
  while (count > 0)
  {
    x = rand() % 9 + 1;
    y = rand() % 9 + 1;
    if (board[x + 1][y + 1] == '0')
    {
      board[x + 1][y + 1] = '1';
      count--;
    }
  }
}
//统计周围炸弹数量
int countbombs(char bombs[ROWS][COLS], int x, int y)
{
  int ret = 0;
  ret=bombs[x - 1][y - 1] + bombs[x - 1][y] + bombs[x - 1][y + 1] + bombs[x][y - 1] + bombs[x][y + 1] + bombs[x + 1][y - 1] + bombs[x + 1][y] + bombs[x + 1][y + 1] - 8 * '0';
  return ret;
}
//扫雷
void findbombs(char bombs[ROWS][COLS],char show[ROWS][COLS], int row, int col)
{
  int x = 0;
  int y = 0;
  int win = 0;
  while (win<(row*col- bomb_count))
  {
    printf("请输入你想排查的坐标: ");
    scanf("%d %d", &x, &y);
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      if (bombs[x][y] == '1')
      {
        printf("你被炸弹炸死了\n");
        printboard(bombs, ROW, COL);
        break;
      }
      else
      {
        int count = countbombs(bombs, x, y);
        show[ x ][ y ] = count + '0';
        printboard(show, ROW, COL);
        win++;
      }
    }
    else
    {
      printf("输入坐标不合法,请重新输入\n");
    }
  }
  if (win == (row * col - bomb_count))
  {
    printf("恭喜你,排掉了全部的炸弹,游戏胜利!!!\n");
    printboard(bombs, ROW, COL);
  }
}

3.游戏主体代码

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void game()
{
  char bomb[ROWS][COLS] = { 0 };
  char show[ROWS][COLS] = { 0 };
  //初始化棋盘
  initboard(bomb, ROWS, COLS, '0');
  initboard(show, ROWS, COLS, '#');
  //打印棋盘
  printboard(show, ROW, COL);
  //生成随机炸弹位置
  setbombs(bomb, ROWS, COLS);
  //printboard(bomb, ROW, COL);
  //开始扫雷
  findbombs(bomb, show, ROW, COL);
}
int main()
{
  int input = 0;
  srand((unsigned int)time(NULL));
  printf("请进行输入确认是否开始游戏\n");
  do
  {
    mune();
    scanf("%d", &input);
    switch(input)
    {
    case 1:
      printf("\t开始游戏\n");
      game();
      break;
    case 2:
      printf("\t退出游戏\n");
      break;
    default:
      printf("非法输入,请重试\n");
      break;
    }
  } while (input != 2);
  return 0;
}
目录
相关文章
|
2月前
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
128 0
|
2月前
|
C语言 C++
【C语言】编写“猜数字“小游戏
【C语言】编写“猜数字“小游戏
108 1
|
2月前
|
C语言 C++
保姆式教学C语言——数组
保姆式教学C语言——数组
21 0
保姆式教学C语言——数组
|
2月前
|
存储 API C语言
【C语言】实践:贪吃蛇小游戏(附源码)(一)
【C语言】实践:贪吃蛇小游戏(附源码)
|
2月前
|
C语言 定位技术 API
【C语言】实践:贪吃蛇小游戏(附源码)(二)
【C语言】实践:贪吃蛇小游戏(附源码)
【C语言】实践:贪吃蛇小游戏(附源码)(二)
|
2月前
|
C语言 开发者
C语言实现猜数字小游戏(详细教程)
C语言实现猜数字小游戏(详细教程)
|
2月前
|
存储 算法 安全
C语言实现扫雷游戏
C语言实现扫雷游戏
|
2月前
|
C语言
保姆级教学 - C语言 之 动态内存管理
保姆级教学 - C语言 之 动态内存管理
25 0
|
2月前
|
C语言
初学者指南:使用C语言实现简易版扫雷游戏
初学者指南:使用C语言实现简易版扫雷游戏
48 0
|
2月前
|
C语言
C语言扫雷游戏(详解)
C语言扫雷游戏(详解)
45 0