【C语言】简单有趣的扫雷游戏

**©作者:末央&
©系列:C语言初阶(适合小白入门)
©说明:以凡人之笔墨,书写未来之大梦

在这里插入图片描述

目录

  • 一、分析游戏规则
  • 二、分文件
  • 三、菜单实现
  • 四、游戏内容核心实现
    • 1.初始化棋盘
    • 2.打印棋盘
    • 3.布置雷
    • 4.排查雷
    • 5.game()函数实现调用
  • 五、全部源码

一、分析游戏规则

我们大多数人在小时候都玩过扫雷游戏吧,大致的规则就是在9*9(也可以是更大的规模)的格子中选出一个方位,然后如果该位置是雷你就被炸死了,如果不是雷则统计8个位置的雷数有多少。例如下图
在这里插入图片描述
那么我们了解了游戏规则就应该考虑需要多少源文件来完成这个游戏项目了。扫雷这个游戏的代码肯定是有点多的,如果使用一个源文件来实现那就显得太复杂局限,这里建议分文件编写来实现。

二、分文件

就是把我们的程序代码划分成多个文件,这样就不会把所有的代码都放在main.c里面,采用分模块的编程思想,进行功能划分,把每个功能不一样的单独放在一个c文件里,然后写头文件把它封装成可调用的一个函数,在主函数调用这个封装好的函数,编译的时候一起编译即可。他的好处也很明显:大大提升了整个程序的可视化和可调试性

👀来让给我们看看具体操作如下:

头文件中创建game.h ----用来声明函数
源文件中创建game.c—函数具体实现 / test.c—主题流程
在这里插入图片描述
在这里插入图片描述

三、菜单实现

只要是游戏都要有菜单是吧,为了方便用户选择是否继续游戏。那么我们不妨在test文件中实现这个功能。
先用一个函数来打印菜单

void menu()
{printf("**********************\n");printf("******  1.play  ******\n");printf("******  0.exit  ******\n");printf("**********************\n");
}

打印完菜单后咱们还要对该菜单的选项的功能进行代码实现,我们是不是至少都有一次选择机会这里就考虑使用do…while循环来和switch语句来实现功能实现

int main()
{int input = 0;do{menu();printf("请输入选项>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏>\n");break;default:printf("选择错误,重新选择>\n");break;}} while (input);return 0;
}

四、游戏内容核心实现

1.如果这个位置是雷,那么游戏结束。
2.如果把不是雷的位置都找出来了,那么游戏结束。
3.如果这个位置不是雷,就计算这个位置的周围的8个格子有几个雷,并显示出雷的个数。

观看前面的扫雷游戏图知道,我们游戏至少得有个棋盘是吧。这个棋盘可以用来展示每一次选择位置.游戏环境的变化并且还要实现埋藏雷,那我们就应该用两个二维数组来实现两个功能,一个用于展示每一次选择后棋盘的变化,一个用来统计雷和排雷的功能。

1.初始化棋盘

在这里插入图片描述

图一:”1“为雷(mine) 图二:”1“为雷的个数(show)

注:由于行,列频繁使用在game.h中宏定义#define ROW 9
#define COL 9#define ROWS ROW + 2
#define COLS COL + 2

在这里插入图片描述

在game.h文件中声明创建棋盘函数:

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);

在game.c文件中实现初始化棋盘函数


void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
1
2
在game.c文件中实现初始化棋盘函数void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;int j = 0;for (i = 0; i < rows; i++){for (j = 0; j < cols; j++){board[i][j] = set;}}
}

这里值得注意的是这个参数set 我们开始因为要把棋盘mine初始化为’0’(因为雷是’1’),还要把show棋盘初始化为’#’
所以如果直接传参0和#的话那么便要设计两个函数,不妨直接多加一个参数来接受所需要初始化的字符

2.打印棋盘

在game.h中声明打印棋盘函数

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
1
2
在game.c中实现打印棋盘函数void DisplayBoard(char board[ROWS][COLS], int row, int col)
{int i = 0;int j = 0;printf("------------扫雷------------\n");for (i = 0; i <= row; i++){printf("%d ", i);}printf("\n");for (i = 1; i <= row; i++){printf("%d ", i);for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}printf("------------扫雷------------\n");
}
————————————————

3.布置雷

在game.h中声明布置雷函数

在此函数中输入x和y的坐标来判断输入的位置是否有雷,如果有直接被炸死了,如果不是雷则要通过GetMineCount函数来统计周围雷的个数,如果输入了71次后(9*9有十个雷)则排雷成功

//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);

通过rand()来实现随机坐标生成范围公式A-B rand()%B-A+1+A
随机数在game.h中进行宏定义

#define EASY_COUNT 10

调用rand()需要srand()

srand((unsigned int)time(NULL));

1 注:包含头文件

#include<stdlib.h>—>srand
#include<time.h>----->time

void SetMine(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count){int x = rand() % row + 1;//x坐标为1-9int y = rand() % col + 1;//y坐标为1-9if (board[x][y] == '0'){board[x][y] = '1';}count--;}
}

4.排查雷

void FindMine(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);if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] != '*'){printf("输入坐标重复,请重新输入\n");}else if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");DisplayBoard(mine, ROW, COL);break;}else{//不是雷,就统计x,y坐标周围有几个雷int c = GetMineCount(mine, x, y);show[x][y] = c + '0';DisplayBoard(show, ROW, COL);win++;}}else{printf("输入坐标错误,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("排雷成功\n");DisplayBoard(mine, ROW, COL);}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{return mine[x + 1][y] + mine[x - 1][y] +mine[x][y + 1] + mine[x][y - 1] +mine[x + 1][y + 1] + mine[x - 1][y + 1] +mine[x - 1][y - 1] + mine[x + 1][y - 1] - 8 * '0';
}

第二种方法:

int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
int i, j,count=0;
for (i = -1; i <= 1; i++)
{for (j = -1; j <= 1; j++){count += (mine[x + i][y + j] - '0');}
}
return count;
}

每次从-1开始到1就实现了x-1到+1的位置遍历

5.game()函数实现调用

void game()
{char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');DisplayBoard(show, ROW, COL);SetMine(mine, ROW, COL);FindMine(mine, show, ROW, COL);
}

五、全部源码

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{printf("*************************\n");printf("*******   1. play  ******\n");printf("*******   0. exit  ******\n");printf("*************************\n");
}
void game()
{char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');DisplayBoard(show, ROW, COL);SetMine(mine, ROW, COL);FindMine(mine, show, ROW, COL);
}
int main()
{srand((unsigned int)time(NULL));int input = 0;do{menu();printf("请输入选项>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏");break;default:printf("输入错误,请重新输入");break;}} while (input);return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;int j = 0;for (i = 0; i < rows; i++){for (j = 0; j < cols; j++){board[i][j] = set;}}
}void DisplayBoard(char board[ROWS][COLS], int row, int col)
{int i = 0;int j = 0;printf("------------扫雷------------\n");for (i = 0; i <= row; i++){printf("%d ", i);}printf("\n");for (i = 1; i <= row; i++){printf("%d ", i);for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}printf("------------扫雷------------\n");
}void SetMine(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (board[x][y] == '0'){board[x][y] = '1';}count--;}
}int GetMineCount(char mine[ROWS][COLS], int x, int y)
{return mine[x + 1][y] + mine[x - 1][y] +mine[x][y + 1] + mine[x][y - 1] +mine[x + 1][y + 1] + mine[x - 1][y + 1] +mine[x - 1][y - 1] + mine[x + 1][y - 1] - 8 * '0';
}void FindMine(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);if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] != '*'){printf("输入坐标重复,请重新输入\n");}else if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");DisplayBoard(mine, ROW, COL);break;}else{//不是雷,就统计x,y坐标周围有几个雷int c = GetMineCount(mine, x, y);show[x][y] = c + '0';DisplayBoard(show, ROW, COL);win++;}}else{printf("输入坐标错误,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("排雷成功\n");DisplayBoard(mine, ROW, COL);}
}

game.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>#define ROW 9
#define COL 9#define ROWS ROW + 2
#define COLS COL + 2#define EASY_COUNT 10//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);//排查雷
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/669615.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenHarmony实战开发-如何实现动画帧

请求动画帧 请求动画帧时通过requestAnimationFrame函数逐帧回调&#xff0c;在调用该函数时传入一个回调函数。 runframe在调用requestAnimationFrame时传入带有timestamp参数的回调函数step&#xff0c;将step中的timestamp赋予起始的startTime。当timestamp与startTime的差…

VScode添加c/c++头文件路径

1.设置工作区include path方法&#xff1a; 命令面板 -> 输入c/c 修改配置文件&#xff0c;添加路径&#xff1a; 2.全局路径&#xff1a; 设置 - > 搜索include path

即将完成60亿美元最大融资,马斯克旗下xAI公司牛在哪里?

【科技明说 &#xff5c; 科技热点关注】 60亿美元融资&#xff0c;约合人民币435亿元。xAI公司之所以这么牛&#xff0c;如此吸金&#xff0c;主要得益于几个关键因素。科技明说尝试为大家捋一捋。 首先是高估值&#xff0c;xAI以180亿美元的估值进行融资&#xff0c;显示出市…

代码随想录算法训练营DAY48|C++动态规划Part9|121.买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III

文章目录 121.买卖股票的最佳时机思路CPP代码 122.买卖股票的最佳时机II思路CPP代码 123.买卖股票的最佳时机III思路CPP代码 121.买卖股票的最佳时机 力扣题目链接 文章讲解&#xff1a;121.买卖股票的最佳时机 视频讲解&#xff1a;动态规划之 LeetCode&#xff1a;121.买卖股…

Spring IoC注解式开发无敌详细(细节丰富)

1. Spring IoC注解式开发无敌详细&#xff08;细节丰富&#xff09; 文章目录 1. Spring IoC注解式开发无敌详细&#xff08;细节丰富&#xff09;每博一文案2. 注解回顾3. Spring 声明Bean的注解3.1 Spring注解的使用3.1.1 特别的&#xff1a;如果要扫描的是多个包3.1.2 Sprin…

面向新手在无人机竞速场景下的飞行辅助系统——浙大 FAST-Lab 高飞团队 ICRA 论文三项 Best Paper 入围

恭喜浙江大学 FAST-Lab 钟宇航同学的论文 A Trajectory-based Flight Assistive System for Novice Pilots in Drone Racing Scenario 顺利发表 ICRA 2024&#xff0c;并同时入选三项 Finalist&#xff1a; the IEEE ICRA Best Conference Paper Awardthe IEEE ICRA Best Pape…

滑动验证码登陆测试编程示例

一、背景及原理 处理登录时的滑动验证码有两个难点&#xff0c;第一个是找到滑块需要移动的距离&#xff0c;第二个是模拟人手工拖动的轨迹。模拟轨迹在要求不是很严的情况下可以用先加速再减速拖动的方法&#xff0c;即路程的前半段加速度为正值&#xff0c;后半段为负值去模…

二氧化碳加氢制烯烃具有经济、环境、社会效应 行业发展意义重大

二氧化碳加氢制烯烃具有经济、环境、社会效应 行业发展意义重大 二氧化碳加氢制烯烃&#xff0c;是以二氧化碳、氢气为原料&#xff0c;在一定温度与压力条件下以及催化剂作用下&#xff0c;反应制备烯烃的过程。 全球每年二氧化碳排放量大&#xff0c;导致气候变暖。在此背景下…

【Unity动画系统】详解Root Motion动画在Unity中的应用(二)

Root Motion遇到Blend Tree 如果Root Motion动画片段的速度是1.8&#xff0c;那么阈值就要设置为1.8&#xff0c;那么在代码中的参数就可以直接反映出Root Motion的最终移动速度。 Compute Thresholds&#xff1a;根据Root Motion中某些数值自动计算这里的阈值。 Velocity X/…

leetCode74. 搜索二维矩阵

leetCode74. 搜索二维矩阵 二分法模板&#xff1a;见到背过就行 // 区间[L,R]被划分为[L,mid]和[mid 1, R]时使用这个模板 int bsearch_1(int l, int r){while(l < r){int mid l r >> 1;if(check(mid)) r mid; //check()判断mid是否满足性质else l mid 1;}retu…

来一篇错题集(虽然简单吧)

一.Assembly via Remainders #include<bits/stdc.h> using namespace std; typedef long long ll; int a[2000]; int b[2000]; int main(){int t;cin>>t;while(t--){int n;cin>>n;for(int i1;i<n-1;i){cin>>b[i];}int x1000000000;//使用1000000000…

pyqt标签常用qss格式设置

pyqt标签常用qss格式设置 QSS介绍标签常用的QSS设置效果代码 QSS介绍 Qt Style Sheets (QSS) 是 Qt 框架中用于定制应用程序界面样式的一种语言。它类似于网页开发中的 CSS&#xff08;Cascading Style Sheets&#xff09;&#xff0c;但专门为 Qt 应用程序设计。使用 QSS&…