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

news2025/1/14 20:41:50

**©作者:末央&
©系列: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-9
		int y = rand() % col + 1;//y坐标为1-9
		if (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.coloradmin.cn/o/1644843.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JAVA项目】基于ssm的协同过滤算法的【图书推荐系统】

技术简介&#xff1a;采用B/S架构、ssm 框架、Java技术、MySQL等技术实现。 系统简介&#xff1a;系统权限按管理员和用户这两类涉及用户划分。&#xff08;1&#xff09;管理员功能需求 管理员登陆后&#xff0c;主要包括首页、个人中心、用户管理、书籍管理、书籍分类管理、热…

手搓链式结构队列(C语言)

Queue.h #pragma once#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <stdbool.h>typedef int QDataType;// 链式结构&#xff1a;表示队列 typedef struct QListNode {struct QListNode* next;QDataType data; }QNode;// 队…

基于java+springboot+vue实现的新闻资讯系统(文末源码+Lw)216

摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;文章信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行处理不能满足广…

Java 基础重点知识-(泛型、反射、注解、IO)

文章目录 什么是泛型? 泛型有什么用?泛型原理是什么? Java 反射什么是反射? 反射作用是什么?动态代理有几种实现方式? 有什么特点? Java 注解什么是注解, 作用是什么? Java I/O什么是序列化?Java 是怎么实现系列化的?常见的序列化协议有哪些?BIO/NIO/AIO 有什么区别…

代码随想录day51 | 动态规划P12 | ● 309. ● 714. ●买卖股票总结

309.最佳买卖股票时机含冷冻期 给定一个整数数组 prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;: 卖出股票后&…

linux文本三剑客之grep

目录 1、三剑客特点和应用场景 2、三件客之grep 1) -v 参数使用示例&#xff1a; 1、三剑客特点和应用场景 命令特点场景grep过滤grep命令过滤速度最快sed替换&#xff0c;修改文件内容&#xff0c;取行 如果要进替换/修改文件内容 取出某个范围的内容&#xff08;从中午12.到…

【Unity】位图字体制作工具:蒲公英

一般来讲&#xff0c;如果需要制作位图字体&#xff0c;一般是使用 BMFont 这种第三方工具&#xff1a;BMFont - AngelCode.comhttp://www.angelcode.com/products/bmfont/ 然而这个工具对于非程序员来说&#xff0c;操作起来较为繁琐困难。每次美术修改了字体之后&…

C语言 | Leetcode C语言题解之第69题x的平方根

题目&#xff1a; 题解&#xff1a; int mySqrt(int x) {long int i 0;for(i0;;i){long int a i*i;long int b (i1)*(i1);if(a < x&&b > x){break;}}return i; }

AI部署指南

部署指南 建议大家尽可能的自己去部署&#xff0c;如果实在懒得搞&#xff0c;可以找我来帮你部署&#xff0c;详情参考 服务器代部署说明。 由于时间仓促&#xff0c;文档可能尚未详尽&#xff0c;我将在后续逐步补充详细的说明文档。 架构草图 项目依赖 必选依赖 MySQ…

【工具使用】如何查看电脑的显存大小

操作步骤&#xff1a; winR&#xff0c;输入“dxdiag”&#xff1a; 点击显示&#xff1a; 可以看到&#xff0c;显存为8G左右。

【SpringBoot整合系列】SpringBoot整合Thymeleaf

目录 背景Thymeleaf简介Thymeleaf的特征模板引擎是什么 代码示例1.引入依赖2.修改配置文件&#xff0c;添加Thymeleaf的配置信息3.编写HTML模板文件4.编写控制器&#xff0c;返回ModelAndView&#xff0c;进行视图渲染 Thymeleaf语法1.常用标签/属性1.1 th:action1.2 th:method…

Java 函数式编程 的基础使用2-BiConsumer

1、创建函数时&#xff0c;确定函数的参数类型和具体操作。 2、使用accept接收函数参数&#xff0c;并执行函数操作。 public class MyBiConsumer {public static void main(String[] args) {BiConsumer<String, Integer> printNameAndAge (param1, param2) -> {Sys…

Android中TabLayout与ViewPager结合使用生命周期详解

博主前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住也分享一下给大家&#xff0c; &#x1f449;点击跳转到教程 效果 使用的布局如下&#xff1a; <?xml version"1.0" encoding"utf-8"?> …

HDU - 3988 Harry Potter and the Hide Story 题解 数论

Harry Potter and the Hide Story 传送门&#xff08;建议到 vjudge 上去提交&#xff09; iSea is tired of writing the story of Harry Potter, so, lucky you, solving the following problem is enough. Input The first line contains a single integer T T T, indic…

黄历择日网php程序源码/日历老皇历万年历带免登录发布模块

黄历择日网php程序源码/日历老皇历万年历带免登录发布模块&#xff0c;不调用接口的&#xff0c;带数据库带黄历算法类&#xff0c;完整版免授权&#xff0c;完全开源程序&#xff0c;可二开&#xff01; 演示地址&#xff1a; https://s22.21sq.top/ 手机端地址&#xff1a…

等保建设技术建议书(Word原件)

1信息系统详细设计方案 1.1安全建设需求分析 1.1.1网络结构安全 1.1.2边界安全风险与需求分析 1.1.3运维风险需求分析 1.1.4关键服务器管理风险分析 1.1.5关键服务器用户操作管理风险分析 1.1.6数据库敏感数据运维风险分析 1.1.7“人机”运维操作行为风险综合分析 1.2…

Shiro-Action:基于Shiro的RESTful权限管理系统

摘要&#xff1a; 随着RESTful API的广泛应用&#xff0c;对权限管理的需求也日益增长。Shiro-Action是一个基于Shiro的权限管理系统&#xff0c;专注于RESTful风格的URL授权。本文将深入探讨Shiro-Action的设计思路、技术实现以及在实际项目中的应用价值。 一、引言 RESTful…

VGA项目:联合精简帧+双fifo+sobel算法 实现VGA显示

前言&#xff1a;该项目实际上是在很多基础的小练习上合成起来的&#xff0c;例如涉及到uart&#xff08;rs232&#xff09;的数据传输、双fifo流水线操作、VGA图像显示&#xff0c;本次内容在此基础上又增添了sobel算法&#xff0c;能实现图像的边沿监测并VGA显示。 文章目录…

算法学习007-进制转换 c++递归算法实现 中小学算法思维学习 信奥算法解析

目录 C进制转换 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 C进制转换 一、题目要求 1、编程实现 小明学c有一段时间了&#xff0c;今天他想做一个进制转换的小程序&#xff0c;将十进…

如何省下5000培训费学会月薪8000的嵌入式Linux?

嵌入式底层开发无疑是一项极为关键的技术&#xff0c;它在众多嵌入式系统中都有着广泛而重要的应用。在当今科技飞速发展的时代&#xff0c;嵌入式系统已经深入到我们生活的每一个角落&#xff0c;成为了我们日常生活中不可或缺的一部分&#xff0c;这也更加凸显了嵌入式开发的…