C语言实现扫雷游戏完整实现(上)

文章目录

  • 前言
  • 一、新建好头文件和源文件
  • 二、实现游戏菜单选择功能
  • 三、定义游戏函数
  • 四、初始化棋盘
  • 五、 打印棋盘函数
  • 六、布置雷函数
  • 七、玩家排雷菜单
  • 八、标记功能的菜单
  • 九、标记功能菜单的实现
  • 总结


前言

C语言从新建文件到游戏菜单,游戏函数,初始化棋盘,打印棋盘,布置雷函数,玩家排雷菜单,标记功能菜单及实现等的操作。

一、新建好头文件和源文件

  • 库函数头文件常数都定义在game.h头文件中
  • 在test.c源文件和game.c源文件中通过#include "game.h"引入game.h头文件即可
    1. 在test.c源文件中实现菜单以及游戏函数的调用等功能。
    1. 在game.h头文件中主要完成游戏函数的声明等功能。
    1. 在game.c源文件中完成函数的定义/实现工程。

在这里插入图片描述

二、实现游戏菜单选择功能

// game.h 头文件
#include <stdio.h>

// test.c 源文件
#include "game.h"


// 定义游戏菜单函数
void menu()
{
	printf("**********************\n");
	printf("*****   1. Play  *****\n");
	printf("*****   0. Quit  *****\n");
	printf("**********************\n");
}
int main()
{
	int input = 0; // 定义输入菜单选项的变量
	do
	{
		// 游戏菜单
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		// 不同选择对应不同结果
		switch (input)
		{
		case 1:
			printf("扫雷游戏开始!!!\n");
			break;
		case 0:
			printf("推出游戏!!!\n");
			break;
		default:
			printf("选择错误,请重新输入\n");
			break; // 因为要重新输入所以从菜单开始循环
		}
	} while (input); // 输入为0退出游戏,同时停止循环
	return 0;
}

三、定义游戏函数

  • 以9×9为例
  • 需要首先定义 11 × 11(为了便于检测棋盘边边位置的雷) 的棋盘(二维数组)
  • 打印9×9的棋盘即可
  • -需要定义两个棋盘
  • 一个用来存放布置雷的信息
  • 一个用来存放玩家操作信息
// game.h 头文件
#include <stdio.h>

#define ROW 9
#define COL 9

#define ROWS ROW + 2
#define COLS COL + 2

// test.c 源文件
#include "game.h"
// 定义游戏菜单函数
void menu()
{
	printf("**********************\n");
	printf("*****   1. Play  *****\n");
	printf("*****   0. Quit  *****\n");
	printf("**********************\n");
}
--------------------------------------------------------------
void game()
{
	// 定义两个二维数组
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	// 初始化棋盘
}
---------------------------------------------------------------
int main()
{
	int input = 0; // 定义输入菜单选项的变量
	do
	{
		// 游戏菜单
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		// 不同选择对应不同结果
		switch (input)
		{
		case 1:
			printf("扫雷游戏开始!!!\n");
	-------------------------------------------------
			game();
	-------------------------------------------------
			break;
		case 0:
			printf("推出游戏!!!\n");
			break;
		default:
			printf("选择错误,请重新输入\n");
			break; // 因为要重新输入所以从菜单开始循环
		}
	} while (input); // 输入为0退出游戏,同时停止循环
	return 0;
}

四、初始化棋盘

  • 将存放布置雷信息的棋盘初始化为 ‘0’。----设计 ‘0’表示没有雷,‘1’表示雷。
  • 将玩家操作信息的棋盘初始化为 ‘*’。
// test.c --game函数
void game()
{
	// 定义两个二维数组
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	// 初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');
}

// game.h 头文件
#include <stdio.h>

#define ROW 9
#define COL 9

#define ROWS ROW + 2
#define COLS COL + 2

// 初始化棋盘函数的声明
void InitBoard(char board[ROWS][COLS], int rows, int cols, char sign);

// game.c 源文件
#include "game.h"

// 初始化棋盘函数的定义
void InitBoard(char board[ROWS][COLS], int rows, int cols, char sign)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = sign;
		}
	}
}

五、 打印棋盘函数

  • 只打印9×9的棋盘,所以传入参数 ROW 和 COL。
  • 打印棋盘的同时还可以打印出每行每列的数字,方便玩家操作。
  • 同时打印出分割线例如 -----------扫雷游戏---------------
//test.c 源文件
void game()
{
	// 定义两个二维数组
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	// 初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	// 打印棋盘
	DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);
}

//game.h 头文件
#include <stdio.h>

#define ROW 9
#define COL 9

#define ROWS ROW + 2
#define COLS COL + 2

// 初始化函数声明
void InitBoard(char board[ROWS][COLS], int rows, int cols, char sign);


// 打印函数声明
void DisplayBoard(char board[ROWS][COLS], int row, int col);

//game.c 源文件
// 打印棋盘函数定义
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	// 打印游戏开头分割线
	printf("-----扫雷游戏------\n");
	int i = 0;
	// 打印每一列数字
	for (i = 0; i <= row; i++)
	{
		printf("%d ", i); // 打印每一列数字
	}
	printf("\n");// 打印列数字完换行

	for (i = 1; i <= row; i++)
	{
		// 打印每一列数字之前先打印出行号
		printf("%d ", i);
		int j = 0;
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	// 打印游戏结尾分割线
	printf("-----扫雷游戏------\n");
}

目前可以实现的效果如下图
在这里插入图片描述

六、布置雷函数

  • 在初始化棋盘和打印棋盘之间,应该先布置雷。在mine棋盘(数组)中布置。
  • 在game.h文件中定义常量 EASY_COUNT 来表示雷的数量。
  • 雷只用在9×9的范围内布置即可,所以传入参数 ROW 和 COL。
  • 通过生成9×9范围内的随机数,来布置雷。
  • 用到rand函数,引入 stdlib.h 和 time.h 头文件。
  • 为了保证随机数的随机性,需要在test.c的主函数一开始使用srand函数如下图
    在这里插入图片描述
//test.c 源文件 -- game函数
void game()
{
	// 定义两个二维数组
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	// 初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	// 布置雷
	SetBoard(mine, ROW, COL);

	// 打印棋盘
	DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);
}

//game.h 头文件
#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 sign);


// 打印函数声明
void DisplayBoard(char board[ROWS][COLS], int row, int col);

// 布置雷函数声明
void SetBoard(char board[ROWS][COLS], int row, int col);

//game.c 源文件
// 布置雷函数定义
void SetBoard(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	int x = 0;
	int y = 0;
	while (count)
	{
		x = rand() % row + 1;
		y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

七、玩家排雷菜单

  • 玩家排雷之前要有标记,排雷,以及退出终止的菜单。
  • 菜单选择需要玩家输入,所以定义变量,如若出入错误,循环输入。
//test.c 源文件 --- game函数
void game()
{
	int choose = 0;
	// 定义两个二维数组
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	// 初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	// 布置雷
	SetBoard(mine, ROW, COL);

	// 打印棋盘
	DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);

	// 玩家开始排雷
	do
	{
		printf("****************\n");
		printf("*** 1. 标记  ***\n");
		printf("*** 2. 排雷  ***\n");
		printf("*** 0. 退出  ***\n");
		printf("****************\n");
		printf("请选择:>");
		scanf("%d", &choose);

		if (1 == choose)
		{
			printf("标记功能\n");
		}
		else if (2 == choose)
		{
			printf("排雷功能\n");
		}
		else if (0 == choose)
		{
			printf("退出游戏\n");
			break;
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	} while (choose);

}

实现效果如下图:
在这里插入图片描述

八、标记功能的菜单

  • 标记功能是玩家操作信息,传入show棋盘(数组)。
  • 玩家只在9×9棋盘中标记,所以使用 ROW 和 COL。
  • 标记功能应该有 1. 标记位置 2. 取消标记 3. 不标记了等三个功能。
  • 标记功能实现的同时对标记的雷进行计数,方便判断胜利。
//test.c 源文件 -- game函数
void game()
{
	int choose = 0;
	// 定义两个二维数组
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	// 初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	// 布置雷
	SetBoard(mine, ROW, COL);

	// 打印棋盘
	DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);

	// 玩家开始排雷
	do
	{
		printf("****************\n");
		printf("*** 1. 标记  ***\n");
		printf("*** 2. 排雷  ***\n");
		printf("*** 0. 退出  ***\n");
		printf("****************\n");
		printf("请选择:>");
		scanf("%d", &choose);

		if (1 == choose)
		{
			printf("标记功能\n");
			SignBoard(show, mine, ROW, COL);
		}
		else if (2 == choose)
		{
			printf("排雷功能\n");
		}
		else if (0 == choose)
		{
			printf("退出游戏\n");
			break;
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	} while (choose);

}

//game.h 头文件
#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 sign);


// 打印函数声明
void DisplayBoard(char board[ROWS][COLS], int row, int col);

// 布置雷函数声明
void SetBoard(char board[ROWS][COLS], int row, int col);

// 标记功能函数声明
int SignBoard(char show[ROWS][COLS],char mine[ROWS][COLS], int row, int col);

//game.c 源文件 ---SignBoard函数
// 标记功能函数定义
int SignBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
	int choose = 0;
	do
	{
		printf("******************\n");
		printf("*** 1.标记位置 ***\n");
		printf("*** 2.取消标记 ***\n");
		printf("*** 0.不标记了 ***\n");
		printf("******************\n");
		printf("请选择:>");
		scanf("%d", &choose);

		if (1 == choose)
		{
			printf("标记位置\n");
		}
		else if (2 == choose)
		{
			printf("取消标记\n");
		}
		else if (0 == choose)
		{
			printf("不标记了\n");
			break;
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}

	} while (choose);
}

实现效果如下图:
在这里插入图片描述

九、标记功能菜单的实现

  • 标记位置需要玩家输入
  • 需要判断合法性
  • 需要判断是否被排查
  • 定义两个计数变量,若两变量相等,并且等于雷的个数时,判定排雷成功
  • 每次标记完成或取消标记后,打印棋盘
//game.c 源文件---SignBoard函数完整
// 标记功能函数定义
int SignBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int choose = 0;
	static int sum = 0; // 定义标记的总数
	static int count = 0; // 定义标记的雷的总数
	do
	{
		printf("******************\n");
		printf("*** 1.标记位置 ***\n");
		printf("*** 2.取消标记 ***\n");
		printf("*** 0.不标记了 ***\n");
		printf("******************\n");
		printf("请选择:>");
		scanf("%d", &choose);

		if (1 == choose)
		{
			printf("请输入标记坐标(空格隔开):>");
			scanf("%d %d", &x, &y);

			if (x >= 1 && x <= row && y >= 1 && y <= col) // 判断坐标合法性
			{
				if (show[x][y] == '*') // 判断坐标是否排查过
				{
					show[x][y] = '$';
					sum++; // 没标记一个加1
					if (mine[x][y] == '1')
					{
						count++; // 标记的位置如果是雷 加1
					}
				}
				else
				{
					printf("坐标已经被排查过了,请勿重复排查\n");
				}
			}
			else
			{
				printf("超出棋盘范围,请重新输入\n");
			}
			DisplayBoard(show, ROW, COL);
			break;
		}
		else if (2 == choose)
		{
			printf("请输入标记坐标(空格隔开):>");
			scanf("%d %d", &x, &y);

			if (x >= 1 && x <= row && y >= 1 && y <= col) // 判断坐标合法性
			{
				if (show[x][y] == '$') // 判断坐标是否标记过
				{
					show[x][y] = '*';
					sum--; // 没标记一个加1
					if (mine[x][y] == '1')
					{
						count--; // 标记的位置如果是雷 加1
					}
				}
				else
				{
					printf("坐标未被标记,请重新选择\n");
				}
			}
			else
			{
				printf("超出棋盘范围,请重新输入\n");
			}
			DisplayBoard(show, ROW, COL);
			break;
		}
		else if (0 == choose)
		{
			// 不标记直接跳转
			break;
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}

	} while (choose);

	if (sum == count && count == EASY_COUNT)
	{
		sum = 0;
		count = 0;
		return EASY_COUNT;
	}
	else
	{
		return 0;
	}
	
}
  • 把雷的个数设置为1进行测试
  • 主要过程是
    1. 先标记一个不是雷的位置。
    1. 再标记雷的位置。
    1. 最后取消标记不是雷的位置。
    1. 测试是否判定成功。
  • 效果如下图:
    在这里插入图片描述

总结

C语言从新建文件到游戏菜单,游戏函数,初始化棋盘,打印棋盘,布置雷函数,玩家排雷菜单,标记功能菜单及实现等的操作及实现效果。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ElasticSearch笔记一

随着这个业务的发展&#xff0c;我们的数据量越来越庞大。那么传统的这种mysql的数据库就渐渐的难以满足我们复杂的业务需求了。 所以在微服务架构下一般都会用到一种分布式搜索的技术。那么今天呢我们就会带着大家去学习分布搜索当中最流行的一种ElasticSearch&#xff0c;Ela…

【折半处理 二分查找】1755. 最接近目标值的子序列和

本文涉及知识点 折半处理 二分查找算法合集 LeetCode1755. 最接近目标值的子序列和 给你一个整数数组 nums 和一个目标值 goal 。 你需要从 nums 中选出一个子序列&#xff0c;使子序列元素总和最接近 goal 。也就是说&#xff0c;如果子序列元素和为 sum &#xff0c;你需要…

关于Java的三个小题目(很容易错!)

第一题 char运算后的数据类型 最后输出的是什么类型&#xff1f; 答案&#xff1a;int char与byte的联系和区别 char是无符号型的&#xff0c;能够表示一个整数&#xff0c;不能表示负数&#xff08;0~65535&#xff09;&#xff1b;而byte是有符号型的&#xff0c;能够表示…

elasticsearch-8.1.0安装记录

目录 零、版本说明一、安装二、使用客户端访问 零、版本说明 centos [rootnode1 ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)elasticsearch elasticsearch-8.1.0-linux-x86_64一、安装 systemctl stop firewalld.servicesystemctl disable firewal…

笔记本电脑耗电和发热比较厉害怎么处理

工作中会遇到有同事反馈笔记本电脑耗电和发热比较厉害&#xff0c;主要检查以下几个地方 1、CPU频率 很多人觉得是cpu使用率高就代表电脑跑得快&#xff0c;发热量就大&#xff0c;其实不是的&#xff0c;主要是看的cpu频率&#xff0c;频率越高&#xff0c;电脑发热量越大。如…

Laravel 6 - 第十一章 中间件

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

如何在 Flutter 中制作多种颜色的 TextField

TextField widget 本身并不施加任何样式。相反&#xff0c;它会要求 TextEditingController 生成一个样式化的 TextSpan 对象&#xff0c;即一段带有样式的文本。 TextField 将其样式传递给 TextEditingController &#xff0c;默认实现只是将其放入 TextSpan 对象中&#xff0…

C#通过Qt使用VTK

需求&#xff1a; 一个项目&#xff0c;界面是C# 开发的&#xff0c;但是业务上有三维可视化的需求&#xff0c;VTK基于C#的绑定版本需要收费&#xff0c;并且资料很少。因此将VTK嵌入到Qt里&#xff0c;并封装成一个dll&#xff0c;通过接口提供给C#访问。 实现&#xff1a;…

HTTP慢连接攻击的原理和防范措施

随着互联网的快速发展&#xff0c;网络安全问题日益凸显&#xff0c;网络攻击事件频繁发生。其中&#xff0c;HTTP慢速攻击作为一种隐蔽且高效的攻击方式&#xff0c;近年来逐渐出现的越来越多。 为了防范这些网络攻击&#xff0c;我们需要先了解这些攻击情况&#xff0c;这样…

贪吃蛇(C语言版)

在我们学习完C语言 和单链表知识点后 我们开始写个贪吃蛇的代码 目标&#xff1a;使用C语言在Windows环境的控制台模拟实现经典小游戏贪吃蛇 贪吃蛇代码实现的基本功能&#xff1a; 地图的绘制 蛇、食物的创建 蛇的状态&#xff08;正常 撞墙 撞到自己 正常退出&#xf…

vscode将本地服务转发到外网地址访问

示例中将本地的5500端口&#xff0c;用vscode进行端口转发&#xff0c;在外网地址访问服务 要转发的端口 转发端口 点击转发端口 输入要转发的端口&#xff0c;按下回车 Enter 点击允许&#xff0c;弹出确认界面后点击打开 转发端口已经成功配置上&#xff0c;右键可见性…

Git和Github绑定

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

爬虫中怎么判断一个网页是否包含ajax请求

1、前言 在用爬虫抓取数据的时候&#xff0c;如果一个网页包含ajax请求&#xff0c;由于数据时动态加载的&#xff0c;直接根据网址是不能获取到想要的数据。因此&#xff0c;在爬虫需要首先判断一个网页是否包含ajax请求数据。 2、ajax请求 2.1 什么是ajax请求 AJAX Asynch…

20240424codeforces刷题题解

240424刷题题解 Walk on Matrix CodeForces - 1332D 思路 构造题&#xff0c;每个 d p i , j dp_{i,j} dpi,j​​​都是由其左上方向中的按位与最大值决定的。 我们需要从使得贪心解与正确解的差值为 k k k。 为了方便获得 k k k&#xff0c;可以考虑构造一个贪心解为 0…

社交媒体数据恢复:Facebook

在使用Facebook的过程中&#xff0c;可能会出现数据丢失的情况&#xff0c;如误删了重要的帖子、照片或其他文件。在这种情况下&#xff0c;你可以尝试以下方法来恢复Facebook的数据。 首先&#xff0c;确保你备份了Facebook的数据。如果你定期备份数据&#xff0c;那么恢复起…

第26天:安全开发-PHP应用模版引用Smarty渲染MVC模型数据联动RCE安全

第二十六天 一、PHP新闻显示-数据库操作读取显示 1.新闻列表 数据库创建新闻存储代码连接数据库读取页面进行自定义显示 二、PHP模版引用-自写模版&Smarty渲染 1.自写模版引用 页面显示样式编排显示数据插入页面引用模版调用触发 2.Smarty模版引用 1.下载&#xff1a…

【C语言回顾】操作符详解

前言1. 操作符分类2. 二进制和进制转换2.1 二进制2.2 进制转换2.2.1 二进制转十进制2.2.2 二进制转八进制2.2.3 二进制转十六进制 3. 原码、反码、补码4. 移位操作符4.1 左移操作符4.2 右移操作符 5. 位操作符6. 单目操作符7. 逗号表达式8. 下标引用操作符9. 函数调用操作符10.…

Linux:进程与计划任务

文章目录 Linux&#xff1a;进程与计划任务一、进程1、进程是什么2、进程状态 二、列出进程命令1、查看静态的进程统计信息——“ps”Play1&#xff1a;“ps aux”Play2:ps -elf 2、查看静态的进程统计信息——“top”段首解析进程信息区解释 三、运行与终止进程3.1、运行进程3…

一致性hash

一、什么是一致性hash 普通的hash算法 (hashcode % size )&#xff0c;如果size发生变化&#xff0c;几乎所有的历史数据都需要重hash、移动&#xff0c;代价非常大&#xff0c;常见的java中的hashmap就是如此。 那如果在hash表扩容或者收缩的时候size能够保持不变&#xff0…

React-editor-js not showing up in a function component

React-editor-js not showing up in a function component react-editor-js 在react 函数组件中显示不出来 真的&#xff0c;我马上就想放弃它了。但是看它周下载量还挺多&#xff0c;我不信别人没遇到过。于是我继续在网络上挖呀挖。只是我一开始的方向错了。我一直以为我的写…