前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于C语言扫雷游戏的实现(用到递归函数,循环语句,二维数组)(附带代码功能讲解)

基于C语言扫雷游戏的实现(用到递归函数,循环语句,二维数组)(附带代码功能讲解)

作者头像
发布2024-04-30 12:16:29
960
发布2024-04-30 12:16:29
举报
文章被收录于专栏:转自CSDN

扫雷游戏 我用到了递归函数 循环语句 二维数组 自定义函数为核心

1.首先是游戏的进入菜单界面

代码部分(不做讲解)

void menu()//菜单部分 {     printf("*****************\n");     printf("******1.play*****\n");     printf("******0.exit*****\n");     printf("*****************\n"); }

和游戏进入主函数口

 int main() {     int play ;     do     {         menu();         scanf("%d", &play);         if (play == 1)         {             printf("游戏开始\n");             game();//引用外部函数 用的头文字是自己定义的         }         else if(play != 1&& play !=0)         {             printf("输入错误请重新输入\n");         }     } while (play);     printf("游戏结束\n");     return 0; }

然后是基础参数的设置

 2.然后是最基础的游戏内的代码设置 (我全部批注在代码中)

void game() {     srand((unsigned int)time(NULL));//设置随机数的基础值     int x; int y; int z;     char arr[X][Y] = { 0 };//这个是开棋盘     char arr_1[X][Y] = { 0 };//这个是要生成雷的位置     Init_game_sc(arr,X,Y);//初始化外棋盘     Init_game_sc_l(arr_1, X, Y);//初始化内棋盘     printf("   左上角第一个为1 1 第二个为 1 2\n");     game_qp(arr, X, Y);//打印棋盘     game_scqp(arr_1);//生成炸弹 生成炸弹周围的数字     do//基础设置结束后游戏内部的代码     {         printf("请输入你要打开的位置>>");         scanf("%d %d", &x, &y);         while (1)         {             x -= 1; y -= 1;             if (x >= X || x < 0 || y >= Y || y < 0)             {                 printf("坐标输入错误请重新输入");                 printf("请输入你要打开的位置>>");                 scanf("%d %d", &x, &y);             }             else             {                 break;             }         }         int cango = game_pd(arr_1,arr, x, y);//判断是否合法,可以合并到这里面         if (cango == 1)         {             game_kq(arr_1, arr, x, y);//打开棋盘内的空位置 并且变成0         }         else if (cango == -1)         {             printf("踩雷了,游戏失败");             game_qp(arr_1, X, Y);             break;         }         z = gameover(arr);//判断游戏是否结束         if (z == L)         {             printf("游戏胜利\n");             game_qp(arr_1, X, Y);             break;         }         game_qp(arr, X, Y);     } while (1);     //game_qp(arr,X,Y); }

3.逐个功能代码分析

初始化棋盘

void  Init_game_sc(char arr[X][Y],int x,int y)//初始化棋盘 {     int i = 0;      int j = 0;     for (i = 0; i < x; i++)     {         for (j = 0; j < y; j++)         {             arr[i][j] = '#';         }     } } void  Init_game_sc_l(char arr[X][Y], int x, int y)//初始化雷的棋盘 {     int i = 0;     int j = 0;     for (i = 0; i < x+1; i++)     {         for (j = 0; j < y; j++)         {             arr[i][j] = ' ';         }     } }

 我认为这里可以合并,可以进一步简化

打印棋盘

void game_qp(char arr[X][Y], int x, int y)//打印棋盘 {     printf("\n");     int i = 0; int j = 0; int z = 0;     printf("     ");     for (z = 0; z < x; z++)     {         printf("%2d ",z + 1);         printf(" ");     }     printf("\n");     printf("     ");     for (z = 0; z < x; z++)     {         printf("---");         printf(" ");     }     printf("\n");     for (i = 0; i < y; i++)     {         printf(" %2d",i + 1);         for (j = 0; j < x; j++)         {             printf(" | ", arr[i][j]);             printf("%c", arr[i][j]);         }         printf(" | ", arr[i][j]);         printf("\n");         printf("     ");         for (z = 0; z < x; z++)         {             printf("---");             printf(" ");         }         printf("\n");     } }

 打印部分不做什么解释

判断是否合法

int game_pd(char arr_1[X][Y],char arr[X][Y], int x, int y)//是否合法 {     if (arr_1[x][y] != '*')     {         return 1;     }     else if (arr_1[x][y] == '*')     {         return -1;     } }

 这里的判断是否踩到雷了,踩到雷返回-1 没踩到雷返回1 这个可以合并到游戏主程序里

炸弹生成代码 和 周边数字生成代码

void game_scqp(char arr_1[X][Y])//集成炸弹生成 炸弹周围数字检测生成 {     for (int l = L;l > 0;l--)//炸弹生成 用的rand函数      {         int x = (rand() % X + 1);//0-9         int y = (rand() % Y + 1);//0-9         if(arr_1[x][y] != '*')         {             arr_1[x][y] = '*';         }         else         {             l += 1;         }     }     for (int i = 0; i < X; i++)//炸弹周围数字计数功能      {         for (int j = 0; j < Y; j++)         {             if (arr_1[i][j] == '*')             {                 continue;             }             else             {                 int a;                 int b;                 int count = 0;                 for (a = -1; a < 2; a++)                 {                     for (b = -1; b < 2; b++)                     {                         if (i + a < 0 || i + a >= X || j + b < 0 || j + b >= Y)                         {                             continue;                         }                         if (arr_1[i + a][j + b] == '*')                         {                             count++;                         }                     }                 }                 if (count != 0)                 {                     arr_1[i][j] = count + '0';                 }             }         }     } }

 炸弹周围数字计数功能,我写的并不是最优解,但是我个人认为比较直观,先找到一个坐标 然后定义数字初始为0 然后以 3 * 3的方式挨个扫描周围 如果有雷 数字加一 几个雷加几个数 数完以后 把数字填写到这个坐标里(我个人认为写的比较麻烦,希望能有更优解)

判定是否胜利

int gameover(char arr[X][Y]) {     int count = 0; int i = 0; int j = 0;     for (i = 0; i < X; i++)     {         for (j = 0; j < Y; j++)         {             if (arr[i][j] == '#')             {                 count++;             }         }     }     return count; }

到最后没有扫的地方 是 # 那么当#的数量等于雷的数量就判断成功 

这里返回#的数量给后面的程序判断


然后是打开空格

这里用到递归函数

我的思路就是以十字打开 然后在打开过的非数字的地方变成0 到有数字的地方停止

void game_kq(char arr_1[X][Y], char arr[X][Y], int x, int y)//开启棋盘 打开空棋盘位置 {     arr[x][y] = arr_1[x][y];     if (arr_1[x][y] != '0')     {         if(arr_1[x][y] == ' ')         arr_1[x][y] = '0';         if (x > 0)         {             if (arr_1[x - 1][y] == ' ')             {                 game_kq(arr_1, arr, x - 1, y);             }             if (arr_1[x - 1][y] != ' ' && arr_1[x - 1][y] != '*')             {                 arr[x - 1][y] = arr_1[x - 1][y];             }         }         if (x < X - 1)         {             if (arr_1[x + 1][y] == ' ')             {                 game_kq(arr_1, arr, x + 1, y);             }             if (arr_1[x + 1][y] != ' ' && arr_1[x + 1][y] != '*')             {                 arr[x + 1][y] = arr_1[x + 1][y];             }         }         if (y > 0)         {             if (arr_1[x][y - 1] == ' ')             {                 game_kq(arr_1, arr, x, y - 1);             }             if (arr_1[x][y - 1] != ' ' && arr_1[x][y - 1] != '*')             {                 arr[x][y - 1] = arr_1[x][y - 1];             }         }         if (y < Y - 1)         {             if (arr_1[x][y + 1] == ' ')             {                 game_kq(arr_1, arr, x, y + 1);             }             if (arr_1[x][y + 1] != ' ' && arr_1[x][y + 1] != '*')             {                 arr[x][y + 1] = arr_1[x][y + 1];             }         }     } }

 因为是十字 所以我写了四个方向的递归(希望有大佬可以给出简化版本,而且能让简化完之后给我的是空格而不是0)

以上是程序的各个部分


//全部函数程序 头文件 #pragma once #include <stdio.h> #define X 10//长 #define Y 10//宽 #define L 1//雷的个数 void menu(); void game();

主函数 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include "game.h" int main() {     int play ;     do     {         menu();         scanf("%d", &play);         if (play == 1)         {             printf("游戏开始\n");             game();         }         else if(play != 1&& play !=0)         {             printf("输入错误请重新输入\n");         }     } while (play);     printf("游戏结束\n");     return 0; }

 游戏函数 #define _CRT_SECURE_NO_WARNINGS #include "game.h" #include <stdlib.h> #include <time.h> void menu()//菜单部分 {     printf("*****************\n");     printf("******1.play*****\n");     printf("******0.exit*****\n");     printf("*****************\n"); } void  Init_game_sc(char arr[X][Y],int x,int y)//初始化棋盘 {     int i = 0;      int j = 0;     for (i = 0; i < x; i++)     {         for (j = 0; j < y; j++)         {             arr[i][j] = '#';         }     } } void  Init_game_sc_l(char arr[X][Y], int x, int y)//初始化雷的棋盘 {     int i = 0;     int j = 0;     for (i = 0; i < x+1; i++)     {         for (j = 0; j < y; j++)         {             arr[i][j] = ' ';         }     } } void game_qp(char arr[X][Y], int x, int y)//打印棋盘 {     printf("\n");     int i = 0; int j = 0; int z = 0;     printf("     ");     for (z = 0; z < x; z++)     {         printf("%2d ",z + 1);         printf(" ");     }     printf("\n");     printf("     ");     for (z = 0; z < x; z++)     {         printf("---");         printf(" ");     }     printf("\n");     for (i = 0; i < y; i++)     {         printf(" %2d",i + 1);         for (j = 0; j < x; j++)         {             printf(" | ", arr[i][j]);             printf("%c", arr[i][j]);         }         printf(" | ", arr[i][j]);         printf("\n");         printf("     ");         for (z = 0; z < x; z++)         {             printf("---");             printf(" ");         }         printf("\n");     } } int game_pd(char arr_1[X][Y],char arr[X][Y], int x, int y)//是否合法 {     if (arr_1[x][y] != '*')     {         return 1;     }     else if (arr_1[x][y] == '*')     {         return -1;     } } void game_kq(char arr_1[X][Y], char arr[X][Y], int x, int y)//开启棋盘 打开空棋盘位置 {     arr[x][y] = arr_1[x][y];     if (arr_1[x][y] != '0')     {         if(arr_1[x][y] == ' ')         arr_1[x][y] = '0';         if (x > 0)         {             if (arr_1[x - 1][y] == ' ')             {                 game_kq(arr_1, arr, x - 1, y);             }             if (arr_1[x - 1][y] != ' ' && arr_1[x - 1][y] != '*')             {                 arr[x - 1][y] = arr_1[x - 1][y];             }         }         if (x < X - 1)         {             if (arr_1[x + 1][y] == ' ')             {                 game_kq(arr_1, arr, x + 1, y);             }             if (arr_1[x + 1][y] != ' ' && arr_1[x + 1][y] != '*')             {                 arr[x + 1][y] = arr_1[x + 1][y];             }         }         if (y > 0)         {             if (arr_1[x][y - 1] == ' ')             {                 game_kq(arr_1, arr, x, y - 1);             }             if (arr_1[x][y - 1] != ' ' && arr_1[x][y - 1] != '*')             {                 arr[x][y - 1] = arr_1[x][y - 1];             }         }         if (y < Y - 1)         {             if (arr_1[x][y + 1] == ' ')             {                 game_kq(arr_1, arr, x, y + 1);             }             if (arr_1[x][y + 1] != ' ' && arr_1[x][y + 1] != '*')             {                 arr[x][y + 1] = arr_1[x][y + 1];             }         }     } } void game_scqp(char arr_1[X][Y])//集成炸弹生成 炸弹周围数字检测生成 {     for (int l = L;l > 0;l--)//炸弹生成     {         int x = (rand() % X + 1);//0-9         int y = (rand() % Y + 1);//0-9         if(arr_1[x][y] != '*')         {             arr_1[x][y] = '*';         }         else         {             l += 1;         }     }     for (int i = 0; i < X; i++)     {         for (int j = 0; j < Y; j++)         {             if (arr_1[i][j] == '*')             {                 continue;             }             else             {                 int a;                 int b;                 int count = 0;                 for (a = -1; a < 2; a++)                 {                     for (b = -1; b < 2; b++)                     {                         if (i + a < 0 || i + a >= X || j + b < 0 || j + b >= Y)                         {                             continue;                         }                         if (arr_1[i + a][j + b] == '*')                         {                             count++;                         }                     }                 }                 if (count != 0)                 {                     arr_1[i][j] = count + '0';                 }             }         }     } } int gameover(char arr[X][Y]) {     int count = 0; int i = 0; int j = 0;     for (i = 0; i < X; i++)     {         for (j = 0; j < Y; j++)         {             if (arr[i][j] == '#')             {                 count++;             }         }     }     return count; } void game() {     srand((unsigned int)time(NULL));//设置随机数的基础值     int x; int y; int z;     char arr[X][Y] = { 0 };//这个是开棋盘     char arr_1[X][Y] = { 0 };//这个是要生成雷的位置     Init_game_sc(arr,X,Y);//初始化外棋盘     Init_game_sc_l(arr_1, X, Y);//初始化内棋盘     printf("   左上角第一个为1 1 第二个为 1 2\n");     game_qp(arr, X, Y);//打印棋盘     game_scqp(arr_1);//生成炸弹 生成炸弹周围的数字     do//基础设置结束后游戏内部的代码     {         printf("请输入你要打开的位置>>");         scanf("%d %d", &x, &y);         while (1)         {             x -= 1; y -= 1;             if (x >= X || x < 0 || y >= Y || y < 0)             {                 printf("坐标输入错误请重新输入");                 printf("请输入你要打开的位置>>");                 scanf("%d %d", &x, &y);             }             else             {                 break;             }         }         int cango = game_pd(arr_1,arr, x, y);//判断是否合法,可以合并到这里面         if (cango == 1)         {             game_kq(arr_1, arr, x, y);//打开棋盘内的空位置 并且变成0         }         else if (cango == -1)         {             printf("踩雷了,游戏失败");             game_qp(arr_1, X, Y);             break;         }         z = gameover(arr);//判断游戏是否结束         if (z == L)         {             printf("游戏胜利\n");             game_qp(arr_1, X, Y);             break;         }         game_qp(arr, X, Y);     } while (1);     //game_qp(arr,X,Y); }

 后言,我的代码并不是最简化,按照直接的思路来写,希望大家能指出不好的地方,分享好的部分给我学习。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-04-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档