扫雷-包含空白展开,标记功能,游戏界面优化-控制台全力复刻

简介: 扫雷-包含空白展开,标记功能,游戏界面优化-控制台全力复刻


引入

这两天偶然间玩到了扫雷的游戏,下的是微软旗下的扫雷,感觉比起以前简陋的界面好了太多

感觉扫雷找到规律也可以玩的很有意思,仔细一想,扫雷不就一二维数组,给我也完全可以实现啊。便开始了我的设计扫雷之旅。

由于本人想兼顾扫雷的灵活性和与原版的功能相似性,我还是花了些时间去完善这些功能,标题也说了,包括空白展开,标记等。以下开始我们的讲解吧!

思路

主要思路是创建两个数组,一个用来记录扫雷的后台数据包括:雷的位置,并记录各个位置周围雷的数量。一个用来展示玩家能看到的界面--展示界面,根据玩家输入展示想给其展示的内容,我画张图来方便大家理解

用户输入一个地址,就将后台数组的数据传入展示数组并打印,这样就完成了对格子的探测。

如果选中的是雷,则判断游戏结束并退出,这样实现了失败的判定。

如果 总格子个数-排除的非雷个数=等于雷的个数,则完成了游戏胜利的判断。

如果选中的是0,则用一个递归函数展开,则完成了空白展开的功能。

将展示的内容根据传入地址将*改成$,则完成了对未知位置的标记。

以上便是主要的代码功能概述,下面详细讲解。

涉及头文件索引

在进行讲解之前,我想做一个多数博主都不会做的事,就是,把用到的较生僻头文件和功能都简单介绍下,见代码

以上内容如果不太懂的朋友强烈建议专门去看看相关内容,了解透这些运用之后,相信一定会更容易理解我的调用。那么开始我们的代码内容吧!

主函数

这里直接把代码放到下面,旁边有注释,还是比较好理解的

#define _CRT_SECURE_NO_WARNINGS
#include "mine_sweep.h"//头文件和函数声明太多我就单独创了个头文件放进去了
int main()
{
  int x = 0, y = 0;//关于游戏界面大小——行-列
  char mine[105][105];//后台界面
  char show[105][105];//展示界面
  srand((unsigned int)time(NULL));//随机生成种子
  int input = 0;
  int digit_m = 10;//雷数量
  do {
  input=menu();//打印菜单
  if (input == 1) {
    printf("开始");
    printf("\n请输入扫雷棋盘大小(长:宽):");
    scanf("%d%d", &x, &y);
    printf("\n请输入设置雷的个数:");
    scanf("%d", &digit_m);
    Initboard(x, y, mine, '0');//初始化棋盘--后台区
    Initboard(x, y, show, '*');//初始化棋盘--展示曲
    Init_mine(x, y, mine,show, digit_m);//初始化雷
    playgame(x, y, digit_m, mine, show);//游戏运行函数
    Sleep(15000); //结束界面展示停留
  }
  else if (input == 0);
  else { printf("输入错误"); Sleep(1000); }
  system("cls");  //清屏
  } while (input);//判断是否继续
  printf("退出游戏");
  return 0;
}

分支函数功能实现

菜单函数

int menu()
{
  printf("************************\n");
  printf("******欢迎来到扫雷******\n");
  printf("*****   1.开始玩   *****\n");
  printf("*****              *****\n");
  printf("*****    0.退出    *****\n");
  printf("************************\n");
  printf("请选择:");
  int m;
  scanf("%d", &m);
  return m;
}

也没啥好说的,就展示菜单以及一个返回值,通过返回值判断是否继续游戏

初始化棋盘函数

初始化棋盘函数对后台和展示棋盘都适用,根据传入的参数初始化相应的二维数组,见代码

void Initboard(int x,int y,char arr[105][105],char ch)
{
  for (int i = 0; i <= x+1; i++)
    for (int j = 0; j <= y+1; j++)
      arr[i][j] = ch;//将数组各个元素初始化为ch
}

初始化雷函数

雷的初始化就涉及到随机生成数字和种子了,随机生成种子在主函数中已经提前完成,在这里就只用 生成随机数就行,不过建议也要注意一下生成特定随机数范围的方式,见代码

void Init_mine(int x, int y, char mine[105][105],char show[105][105], int digit)
{
  int mine_x, mine_y;
  for (int i = 0; i < digit; i++) {//随机生成数字
  start:;
    mine_x = rand() % x + 1;
    mine_y = rand() % y + 1;
    if (mine[mine_x][mine_y] == '0')//防止两个雷生成在同一位置
      mine[mine_x][mine_y] = '*';
    else goto start;
  }
  for (int i = 1; i <= x; i++) {//处理雷周围的数字,放到mine中,便于后期调用
    for (int j = 1; j <= y; j++) {
      if (mine[i][j] == '*')continue;
      if (mine[i - 1][j] == '*')mine[i][j]++;
      if (mine[i + 1][j] == '*')mine[i][j]++;
      if (mine[i][j + 1] == '*')mine[i][j]++;
      if (mine[i][j - 1] == '*')mine[i][j]++;
      if (mine[i - 1][j - 1] == '*')mine[i][j]++;
      if (mine[i + 1][j - 1] == '*')mine[i][j]++;
      if (mine[i - 1][j + 1] == '*')mine[i][j]++;
      if (mine[i + 1][j + 1] == '*')mine[i][j]++;
    }
  }
}

建议大家都注意下后台数组的处理方式,对编写扫雷代码很有帮助,方便处理数据

游戏运行函数

其实也没有多复杂,就是对两个数组的处理而已,见代码

void playgame(int x, int y, int digit_m, char mine[105][105], char show[105][105])
{
  int x1, y1, judge;
  int m = 0;
  int* blank = &m;
  while (*blank < x * y - digit_m) {
    system("cls");
    Showboard(x, y, show);
    printf("或者输入标记的格子(1 行 列)\n");
    printf("请输入要探测格子的位置(0 行 列):");
    scanf("%d%d%d", &judge, &x1, &y1);
    if (mine[x1][y1] == '*'&&judge!=1) { *blank = 0; break; }
    else if (x1<1 && x1>x && y1<1 && y1>y) {
      printf("\n输入错误,请重新输入!");
      continue;
    }
    if (judge == 0) {
      blank_unfold(x, y, x1, y1, mine, show, blank);
    }
    else if (show[x1][y1] != '*' && judge == 1) { printf("已展示格子不可标记!"); Sleep(1500); }
    else if (judge == 1)show[x1][y1] = '$';
    else { printf("输入错误!"); Sleep(1500); }
  }
  system("cls");
  Showboard(x, y, mine);
  if (*blank) { 
    win_maliao();
  }
  else { 
    printf("\n踩到雷了,游戏结束!\n");
    printf("15秒后返回初始界面。\n");
  }
}

其中还涉及到了胜利界面展示,展示界面函数和空白展开函数,下面进行讲解

界面展示函数

对于界面的展示还是很重要的,有时一个游戏的美观与舒适与否很大程度决定了一个游戏的品质,见代码

void Showboard(int x, int y, char arr[105][105])
{
  printf("%d |", 0);
  for (int i = 1; i <= y; i++)
    printf(" %d |", i);
  printf("\n");
  for (int i = 0; i <= y; i++)
    printf("----");
  printf("\n");
  for (int i = 1; i <= x; i++) {
    printf("%d ", i);
    
    for (int j = 1; j <= y; j++) {
      if (arr[i][j] == '*' || arr[i][j] == '$')
        printf("| %c ", arr[i][j]);
      else printf("| %d ", arr[i][j] - '0');
    }
    printf("|");
    printf("\n");
    for (int b = 0; b <= y; b++)
      printf("----");
    printf("\n");
  }
}

主要用|和-符号来优化界面,最后的效果是这样的,见下图

空白展开函数

空白展开在这里算是个拓展功能,不实现的话其实也玩的动,但是有的话会大大提高其可玩性,主要运用到函数的递归,由于有标记功能,这里的代码也需要有一定改动,见代码

void blank_unfold(int x, int y, int x1, int y1, char mine[105][105], char show[105][105], int* blank)
{
  if (x1<1 || x1>x || y1<1 || y1>y)return;//当输入超出范围时返回
  if (show[x1][y1] == '0' || (show[x1][y1] != '*' && show[x1][y1] != '$'))
        return; //在位置已被探测时返回
  else if (mine[x1][y1] != '0') {//在位置不是空白时展开返回
    show[x1][y1] = mine[x1][y1];
    (*blank)++;
    return;
  }
  else {    //递归同时将空白展开
    show[x1][y1] = '0';
    (*blank)++;
    blank_unfold(x, y, x1 - 1, y1, mine, show,blank);
    blank_unfold(x, y, x1 + 1, y1, mine, show,blank);
    blank_unfold(x, y, x1, y1 - 1, mine, show,blank);
    blank_unfold(x, y, x1, y1 + 1, mine, show,blank);
    blank_unfold(x, y, x1 - 1, y1 - 1, mine, show, blank);
    blank_unfold(x, y, x1 - 1, y1 + 1, mine, show, blank);
    blank_unfold(x, y, x1 + 1, y1 - 1, mine, show, blank);
    blank_unfold(x, y, x1 + 1, y1 + 1, mine, show, blank);
  }
}

彩蛋函数(胜利界面展示)

皮一下,闲着的时候弄得马里奥,胜利的时候免费批发

void win_maliao()
{
  printf("\n恭喜获得胜利!\n");
  printf("送你个马里奥\n");
  printf("                ********\n");
  printf("               ************\n");
  printf("               ####....#.\n");
  printf("             #..###.....##....\n");
  printf("             ###.......######              ###            ###\n");
  printf("                ...........               #...#          #...#\n");
  printf("               ##*#######                 #.#.#          #.#.#\n");
  printf("            ####*******######             #.#.#          #.#.#\n");
  printf("           ...#***.****.*###....          #...#          #...#\n");
  printf("           ....**********##.....           ###            ###\n");
  printf("           ....****    *****....\n");
  printf("             ####        ####\n");
  printf("           ######        ######\n");
  printf("##############################################################\n");
  printf("#...#......#.##...#......#.##...#......#.##------------------#\n");
  printf("###########################################------------------#\n");
  printf("#..#....#....##..#....#....##..#....#....#####################\n");
  printf("##########################################    #----------#\n");
  printf("#.....#......##.....#......##.....#......#    #----------#\n");
  printf("##########################################    #----------#\n");
  printf("#.#..#....#..##.#..#....#..##.#..#....#..#    #----------#\n");
  printf("##########################################    ############\n");
  printf("15秒后返回初始界面。\n");
}

代码总和---CV可游玩

到这里差不多就要结束了,以上代码涉及了很多头文件,想来整合运行会比较困难,这些工作我就代大家做了,也是希望大家能玩玩我编的扫雷,见代码

#include<stdio.h>//各种头文件
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#include<string.h>
void Initboard(int x,int y, char arr[105][105],char ch);//初始棋盘函数
void Showboard(int x, int y, char arr[105][105]);//打印界面函数
int menu();//菜单初始化函数
void Init_mine(int x, int y, char arr[105][105],char show[105][105], int digit);//随机初始化雷函数
void playgame(int x,int y,int digit_m, char mine[105][105], char show[105][105]);//游戏运行函数
void blank_unfold(int x, int y, int x1, int y1, char mine[105][105], char show[105][105],int* blank);//空白展开函数
void win_maliao();//胜利界面展示
void Initboard(int x,int y,char arr[105][105],char ch)
{
  for (int i = 0; i <= x+1; i++)
    for (int j = 0; j <= y+1; j++)
      arr[i][j] = ch;
}
void Showboard(int x, int y, char arr[105][105])
{
  printf("%d |", 0);
  for (int i = 1; i <= y; i++)
    printf(" %d |", i);
  printf("\n");
  for (int i = 0; i <= y; i++)
    printf("----");
  printf("\n");
  for (int i = 1; i <= x; i++) {
    printf("%d ", i);
    
    for (int j = 1; j <= y; j++) {
      if (arr[i][j] == '*' || arr[i][j] == '$')
        printf("| %c ", arr[i][j]);
      else printf("| %d ", arr[i][j] - '0');
    }
    printf("|");
    printf("\n");
    for (int b = 0; b <= y; b++)
      printf("----");
    printf("\n");
  }
}
int menu()
{
  printf("************************\n");
  printf("******欢迎来到扫雷******\n");
  printf("*****   1.开始玩   *****\n");
  printf("*****              *****\n");
  printf("*****    0.退出    *****\n");
  printf("************************\n");
  printf("请选择:");
  int m;
  scanf("%d", &m);
  return m;
}
void Init_mine(int x, int y, char mine[105][105],char show[105][105], int digit)
{
  int mine_x, mine_y;
  for (int i = 0; i < digit; i++) {
  start:;
    mine_x = rand() % x + 1;
    mine_y = rand() % y + 1;
    if (mine[mine_x][mine_y] == '0')
      mine[mine_x][mine_y] = '*';
    else goto start;
  }
  for (int i = 1; i <= x; i++) {
    for (int j = 1; j <= y; j++) {
      if (mine[i][j] == '*')continue;
      if (mine[i - 1][j] == '*')mine[i][j]++;
      if (mine[i + 1][j] == '*')mine[i][j]++;
      if (mine[i][j + 1] == '*')mine[i][j]++;
      if (mine[i][j - 1] == '*')mine[i][j]++;
      if (mine[i - 1][j - 1] == '*')mine[i][j]++;
      if (mine[i + 1][j - 1] == '*')mine[i][j]++;
      if (mine[i - 1][j + 1] == '*')mine[i][j]++;
      if (mine[i + 1][j + 1] == '*')mine[i][j]++;
    }
  }
}
void playgame(int x, int y, int digit_m, char mine[105][105], char show[105][105])
{
  int x1, y1, judge;
  int m = 0;
  int* blank = &m;
  while (*blank < x * y - digit_m) {
    system("cls");
    Showboard(x, y, show);
    printf("或者输入标记的格子(1 行 列)\n");
    printf("请输入要探测格子的位置(0 行 列):");
    scanf("%d%d%d", &judge, &x1, &y1);
    if (mine[x1][y1] == '*'&&judge!=1) { *blank = 0; break; }
    else if (x1<1 && x1>x && y1<1 && y1>y) {
      printf("\n输入错误,请重新输入!");
      continue;
    }
    if (judge == 0) {
      blank_unfold(x, y, x1, y1, mine, show, blank);
    }
    else if (show[x1][y1] != '*' && judge == 1) { printf("已展示格子不可标记!"); Sleep(1500); }
    else if (judge == 1)show[x1][y1] = '$';
    else { printf("输入错误!"); Sleep(1500); }
  }
  system("cls");
  Showboard(x, y, mine);
  if (*blank) { 
    win_maliao();
  }
  else { 
    printf("\n踩到雷了,游戏结束!\n");
    printf("15秒后返回初始界面。\n");
  }
}
void blank_unfold(int x, int y, int x1, int y1, char mine[105][105], char show[105][105], int* blank)
{
  if (x1<1 || x1>x || y1<1 || y1>y)return;
  if (show[x1][y1] == '0' || (show[x1][y1] != '*' && show[x1][y1] != '$'))return;
  else if (mine[x1][y1] != '0') {
    show[x1][y1] = mine[x1][y1];
    (*blank)++;
    return;
  }
  else {
    show[x1][y1] = '0';
    (*blank)++;
    blank_unfold(x, y, x1 - 1, y1, mine, show,blank);
    blank_unfold(x, y, x1 + 1, y1, mine, show,blank);
    blank_unfold(x, y, x1, y1 - 1, mine, show,blank);
    blank_unfold(x, y, x1, y1 + 1, mine, show,blank);
    blank_unfold(x, y, x1 - 1, y1 - 1, mine, show, blank);
    blank_unfold(x, y, x1 - 1, y1 + 1, mine, show, blank);
    blank_unfold(x, y, x1 + 1, y1 - 1, mine, show, blank);
    blank_unfold(x, y, x1 + 1, y1 + 1, mine, show, blank);
  }
}
void win_maliao()
{
  printf("\n恭喜获得胜利!\n");
  printf("送你个马里奥\n");
  printf("                ********\n");
  printf("               ************\n");
  printf("               ####....#.\n");
  printf("             #..###.....##....\n");
  printf("             ###.......######              ###            ###\n");
  printf("                ...........               #...#          #...#\n");
  printf("               ##*#######                 #.#.#          #.#.#\n");
  printf("            ####*******######             #.#.#          #.#.#\n");
  printf("           ...#***.****.*###....          #...#          #...#\n");
  printf("           ....**********##.....           ###            ###\n");
  printf("           ....****    *****....\n");
  printf("             ####        ####\n");
  printf("           ######        ######\n");
  printf("##############################################################\n");
  printf("#...#......#.##...#......#.##...#......#.##------------------#\n");
  printf("###########################################------------------#\n");
  printf("#..#....#....##..#....#....##..#....#....#####################\n");
  printf("##########################################    #----------#\n");
  printf("#.....#......##.....#......##.....#......#    #----------#\n");
  printf("##########################################    #----------#\n");
  printf("#.#..#....#..##.#..#....#..##.#..#....#..#    #----------#\n");
  printf("##########################################    ############\n");
  printf("15秒后返回初始界面。\n");
}
int main()
{
  int x = 0, y = 0;
  char mine[105][105];//后台界面
  char show[105][105];//展示界面
  srand((unsigned int)time(NULL));
  int input = 0;
  int digit_m = 10;
  do {
  input=menu();//打印菜单
  if (input == 1) {
    printf("开始");
    printf("\n请输入扫雷棋盘大小(长:宽):");
    scanf("%d%d", &x, &y);
    printf("\n请输入设置雷的个数:");
    scanf("%d", &digit_m);
    Initboard(x, y, mine, '0');//初始化棋盘--后台区
    Initboard(x, y, show, '*');//初始化棋盘--展示曲
    Init_mine(x, y, mine,show, digit_m);//初始化雷
    playgame(x, y, digit_m, mine, show);//游戏运行函数
    Sleep(15000); //结束界面展示
  }
  else if (input == 0);
  else { printf("输入错误"); Sleep(1000); }
  system("cls");  //清屏
  } while (input);//判断是否继续
  printf("退出游戏");
  return 0;
}

运行截图

本篇文章已经代码制作编写不易,还请大家在走之前给一个小小的赞啊!!!

如果对你有帮助的话,别忘了放收藏夹关注我哦--比心(> - < )---♥

同时如果博主的文章有任何错误,都欢迎在评论区提出来,我会积极去改,也感谢大家对我的支持捏。

相关文章
|
8月前
|
Java
往控制台打字(实例:游戏开局输入名字)
往控制台打字(实例:游戏开局输入名字)
30 0
|
6月前
|
Python
python pyqt5 cmd 命令行 控制台 打印 print 输出 显示打印内容 实时显示 界面
python pyqt5 cmd 命令行 控制台 打印 print 输出 显示打印内容 实时显示 界面
210 0
|
9月前
|
存储 算法 安全
c++游戏制作指南(一):在冷峻的控制台上,种满缤纷
c++游戏制作指南(一):在冷峻的控制台上,种满缤纷
292 0
|
6天前
|
运维 Cloud Native 数据可视化
OpenKruiseGame × KubeSphere 联合发布游戏服运维控制台,推动云原生游戏落地
OpenKruiseGame × KubeSphere 联合发布游戏服运维控制台,推动云原生游戏落地
|
9月前
|
C语言 C++ Windows
【c++】设置控制台窗口字体颜色和背景色(system和SetConsoleTextAttribute函数 )(内含超好玩的c++游戏链接)
【c++】设置控制台窗口字体颜色和背景色(system和SetConsoleTextAttribute函数 )(内含超好玩的c++游戏链接)
303 0
【c++】设置控制台窗口字体颜色和背景色(system和SetConsoleTextAttribute函数 )(内含超好玩的c++游戏链接)
|
9月前
|
Windows
Visual Studio 2019 界面开发额外开启控制台
界面开发时,开启控制台,用于打印调试输出
200 0
Visual Studio 2019 界面开发额外开启控制台
|
12月前
|
Python
Python 控制台操作的文字版“数独”游戏(非GUI版本)
Python 控制台操作的文字版“数独”游戏(非GUI版本)
162 0
|
存储 Java
Java初学者作业——实现控制台的猜数字游戏。游戏运行时产生一个1~100之间的随机数字
Java初学者作业——实现控制台的猜数字游戏。游戏运行时产生一个1~100之间的随机数字
871 0
Java初学者作业——实现控制台的猜数字游戏。游戏运行时产生一个1~100之间的随机数字
|
算法 C语言
C语言控制台界版2048游戏-既然是这样的!
C语言控制台界版2048游戏-既然是这样的!
1462 0

热门文章

最新文章