简单扫雷游戏(C语言)

今天,我们再来编写一个简单的扫雷游戏,和三子棋很相似,同样,我们需要有逻辑的编写完代码,就需要分文件编写,我上次已经说过,对于简单的游戏编写,我们可以分三个文件,头文件负责声明以及对应头文件的编写,源文件负责函数的定义,主源文件则负责去选择是否玩游戏,然后通过主源文件调用源文件中的game函数,通过game函数调用面板初始化,面板显示等等函数,去玩这个游戏,好了,下面我们就开始今天的游戏之旅
老样子,首先声明函数以及填写需要的头文件

#ifndef _mine_h
#define _mine_h
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>
#pragma warning(disable:4996)
#define LINE 8     //行
#define COL 8      //列
#define MINE 5     //雷的个数
void menu();     //菜单
void game();     
void initboard(char board[][COL], int line, int col, char face);   //面板初始化
void SetMine(char board[][COL], int line, int col);  //再面板中放雷
void ShowBoard(char board[][COL], int line, int col);  //展示用户所看到的面板
char GetNum(char mine[][COL], int x, int y);   //该位置周围雷的个数
#endif

通过头文件也可以看出,本次扫雷游戏编写,相对于三子棋,更简单了,
下面我们接着去编写我们的主源文件,为了让让读者更为清楚,我们这里先定义一个菜单(menu函数)

void menu()
{
      printf("##########################\n");
      printf("##   欢迎来到扫雷游戏   ##\n");
      printf("##########################\n");
      printf("#1.开始游戏    2.结束游戏#\n");
      printf("##########################\n");
      printf("您的选择是");
}

menu函数可以放在源文件,也可以放在主源文件。

#include"mine.h"
int main()
{
 int quit = 0;
 int select = 0;
 while (!quit){
  menu();
  scanf("%d", &select);
  switch (select){
  case 1:
   game();
   break;
  case 2:
   quit = 1;
   break;
  default:
   printf("您输错了,请重新输!");
   break;
   }
 }
 system("pause");
 return 0;
}

主源函数基本和三子棋游戏的一样,在这里就不多解释了,这里我们就可以看出,再头文件去声明函数,然后让主源文件去包含所有声明以及各种头文件,则就能实现去调用在源文件中定义的函数了。
下面,我们就开始对扫雷的面板进行编写
在编写之前,我们先聊聊,扫雷是什么样的,是不是在去扫所对应的位置,如果是雷,则你被炸死了,如果不是雷,则在该位置会显示四周(与该位置所有挨着的位置,这里也包括该位置的对角位置)对应雷的个数(“大型”扫雷其实会去将周围的位置也被展开,但是我们这里技术有限哈,所以就相当于一个规定吧)。

void initboard(char board[][COL], int line, int col, char face)
{
 int i = 0;
 for (; i < line; i++){
  for (int j = 0; j < col;j++){
   board[i][j] = face;
  }
 }
}

这是定义了一个line行col列的数组,并且在每个位置都放着一个face这么一个字符。

void SetMine(char mine[][COL], int line, int col)
{
 int t = MINE;
 while (t){
  int i = rand() % (line - 2);
  int j = rand() % (col - 2);
  if (mine[i + 1][j + 1] == '1'){
   continue;
  }
  mine[i + 1][j + 1] = '1';
  t--;
 }
}

这里就是放雷函数(Setmine),让随机数(在三子棋游戏中,我们也说过,先在game函数中种下一个随机数的种子,然后去使用就行)去将雷放在数组中,如果放雷的位置重复,则重新放,直到放够MINE个雷为止。
好了,这里我们解释一样为什么去模上行或者列减去2,我在上面也说了扫雷的一个简单过程,要么碰上雷,要么没碰上,但是最关键的就是如果没碰上了,则需要在被扫位置输出一个对应的周围雷的个数,如果这个被扫位置在面板中间的某个地方,就非常简单,只用判断周围是否有雷就行,但是如果被扫位置,在面板的边上或者角落,则它的周围就会有超出面板范围的位置,所以我么那就需要对一个面板多定义两行,两列去包围这个面板,然后对这多出来的两行两列进行初始化无雷,让这个雷只在被包围的面板中显示。(这样还可以扫雷后对周围位置是否有雷很好的显示)
下面就是去个用户展示面板

void ShowBoard(char board[][COL], int line, int col)
{
 int i = 1;
 for (; i <= col - 2; i++){
  printf("  %-2d|", i-1);
 }
 printf("\n");
 printf("------------------------------\n");
 for (i = 1; i <= line - 2; i++){
  printf("  %-2d|", i);
  for (int j = 1; j < col - 2; j++){
   printf("  %-2c|", board[i][j]);
  }
  printf("\n");
  printf("------------------------------\n");
 }
}

展示面板分为用户需要看到的面板(该面板雷的位置用户是不知道的,并且每次扫雷,该位置会出现周围对应的雷的个数),当碰到雷时,就要去显示第二个面板就是,一个完整雷分布的面板或者当用户扫完所有未碰到雷,也会出现该面板。

char GetNum(char mine[][COL], int x, int y)
{
 return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + \
  mine[x][y - 1] + mine[x][y + 1] + \
  mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 7 * '0';
}

这就是在扫所对应位置是,如果没碰到雷,则在该位置显示周围所对应雷的个数。(这里我们再说一点,周围字符减去7个字符0是为了,让该函数返回一个字符0到字符8之间的一个字符)
下面就是咱们去玩这个游戏的game函数

game()
{
       srand((unsigned long)time(NULL));
       char board[LINE][COL];
       char mine[LINE][COL];
       initboard(board, LINE, COL, '*');
       initboard(mine, LINE, COL, '0');
       SetMine(mine, LINE, COL);ShowBoard(board, LINE, COL);
       int t = (LINE - 2)*(COL - 2) - MINE;
       while (t > 0){
              system("cls");
              ShowBoard(board, LINE, COL);
              int i = 0;
              int j = 0;
              printf("请输入您要扫的位置:");
              scanf("%d %d", &i,&j);
              if (i<1 || i>(LINE - 1) || j<1 || j>(COL - 1)){
                  printf("您输错了,请重输入!");
                  Sleep(1000);
                  continue;
                                }
            if (board[i][j] != '*'){
                 printf("您扫的地方已经扫过,请重新输入位置!");
                 Sleep(1000);
                 continue;
        }
          if ('1' == mine[i][j]){
                printf("%d,%d位置有雷,您被炸死了!\n", i, j);
                break;
          }
         else{
                t--;
                char num = GetNum(mine, i, j);
                board[i][j] = num;
        }   
    }
          ShowBoard(mine, LINE, COL);
}

game函数中定义用户所看到的面板,还有一个我刚刚说过的面板,咱们就叫他答案面板吧,然后给两个面板都初始化,在mine板放雷,但是用户所看到的是初始话全为*的面板,所以最终通过用户输入的位置,进行判定,知道被炸死或者游戏胜利,最终显示答案面板(mine面板)。
还是,最开始说的,对于游戏本身,首先我们需要知道它怎么玩,最终要的还是要逻辑清晰,打好框架,一步一步,一个函数一个函数的来,最终就会得到对应的游戏!!!!!

初学者,如果那里有不对的地方,希望各位指教!!!
加油!!!在这里插入图片描述

发布了5 篇原创文章 · 获赞 13 · 访问量 2320

猜你喜欢

转载自blog.csdn.net/weixin_46052798/article/details/105716919