c语言实现扫雷游戏

举报
luming_02 发表于 2023/12/05 13:33:01 2023/12/05
【摘要】 1.分析问题需求和大致思路        在开始设计之前,我们先分析一下,扫雷游戏大家可能都玩过,基本的信息都是呈现在一个10*10的方格上的。开始时我们应该打印一个菜单,让玩家选择是否进行游戏。        然后是初始化的问题,用二维数组来的格子里面的信息的话,刚好非常契合,确定了用数组来存储以后,我们就可以思考一下怎么做初始化,我们可以用3种不同的符号来表示棋盘上的状态,没被玩家排查之...

1.分析问题需求和大致思路

        在开始设计之前,我们先分析一下,扫雷游戏大家可能都玩过,基本的信息都是呈现在一个10*10的方格上的。开始时我们应该打印一个菜单,让玩家选择是否进行游戏。

        然后是初始化的问题,用二维数组来的格子里面的信息的话,刚好非常契合,确定了用数组来存储以后,我们就可以思考一下怎么做初始化,我们可以用3种不同的符号来表示棋盘上的状态,没被玩家排查之前用#表示,在玩家查找以后要输出周围有多少炸弹,呈现出一个整数,呈现在屏幕上的是这些符号,因此我们在创建数组时就得注意用char型。具体的存储信息如下图:

        在完成初始化之后,我们要生成随机的地雷位置,可以用rand函数和srand函数以及time函数来保证生成数的随机性

        在将地雷布置完成后,我们就可以构思扫雷部分的逻辑了,首先由玩家输入一个坐标,然后计算机进行判断,输入位置是否合法是否合理,在确认输入合理后,对玩家输入的坐标进行判断,如果有炸弹,就弹出失败的界面,然后退出游戏,如果没有炸弹,就使用一个函数来统计周围炸弹的数量并且打印出来,然后对以上做循环的封装处理,直到游戏胜利或者失败才跳出循环,完成循环后,我们就需要解决如何定义游戏胜利的条件,我们可以用所有的格子减去已经排除的格子,再减去剩余的炸弹数,也就是进行是否已经将所有格子排查的判断,在最后只剩10个炸弹时,结束游戏,跳出循环。

        为了保证程序的健全性和可读性,我们采用多文件的方法实现扫雷小游戏。用game.h存储头文件信息以及宏定义和函数声明,用board.c文件存储游戏里面的基本逻辑函数,用game.c文件存储游戏的主要功能以及主体

 2.游戏主体逻辑实现以及代码

        这里#include包含的头文件是我们自定义的头文件,里面有我们需要的头文件和函数声明,首先我们定义一个input输入实现记录玩家对于是否开始游戏的选择,用do...while...循环来实现先运行循环体让玩家决定是否进入游戏,在判断玩家的输入,以便于让玩家重复输入以及重复的游玩游戏,其中的srand函数是生成随机数的种子

include "game.h"

void game()
{
	char bomb[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘
	initboard(bomb, ROWS, COLS, '0');
	initboard(show, ROWS, COLS, '#');

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

	//生成随机炸弹位置
	setbombs(bomb, ROWS, COLS);

	//开始扫雷
	findbombs(bomb, show, ROW, COL);

}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	printf("请进行输入确认是否开始游戏\n");

	do
	{
		mune();//打印菜单
		scanf("%d", &input);

		switch(input)
		{
		case 1:
			printf("\t开始游戏\n");
			game();
			break;
		case 2:
			printf("\t退出游戏\n");
			break;
		default:
			printf("非法输入,请重试\n");
			break;
		}
	} while (input != 2);

	return 0;
}

3.游戏的初始化

        我们用俩个二维数组来做记录,一个用来保存我们实际上的地雷存储位置,一个用来打印在屏幕上让玩家观看,俩个数组同等大小,之所以使用11行和9行是为了方便后面判断周围的炸弹数,也是方便后面进行交换打印等等操作,但是实际上对玩家展示的只有1~9行和列,也就是最外边一圈不展示。这里利用传的参数(char ret)不同,来实现对俩个数组进行不同的初始化。至于ROW, ROWS, COL, COLS则是我们为了方便使用以及后期修改,对于行和列进行的宏定义

//定义行和列
#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2
	//初始化棋盘
	initboard(bomb, ROWS, COLS, '0');
	initboard(show, ROWS, COLS, '#');
//初始化
void initboard(char board[ROWS][COLS], int row, int col,char set)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = set;
		}
	}
}

4.地雷位置的随机生成

        还是这张图,我们是只需要使用中间部分的格子的,也就是1~9行以及1~9列,所以在放置炸弹时需要注意,不能放在外围去了

         用rand函数对9取模,随机数的范围就成了0~8,加上1刚好就是1~9,将值付给xy就得到了随机的坐标,while循环则可以反复的判断在放置地雷之前得先判断这个位置是否为空,再用count计数保证放置10个炸弹

//宏定义炸弹的个数
#define bomb_count 10

//生成随机炸弹位置
void setbombs(char board[ROWS][COLS],int row,int col);
//随机生成地雷位置
void setbombs(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = bomb_count;

	while (count > 0)
	{
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;
		if (board[x + 1][y + 1] == '0')
		{
			board[x + 1][y + 1] = '1';
			count--;
		}
	}
	
}

5.打印棋盘

玩家是需要看见棋盘长什么样的,要给玩家提供一个可视化的界面,实现如下:

//打印棋盘
void printboard(char board[ROWS][COLS], int row, int col)
{
	printf("------扫雷游戏------\n");
	printf(" ");
	for (int i = 1; i <= col; i++)
	{
		printf(" %d", i);
	}
	printf("\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (int j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("------扫雷游戏------\n");
}

6.扫雷

        做好一切准备工作后,就可以开始正式的扫雷了,首先让玩家输入一个坐标,用xy进行保存记录,然后判断这个坐标是否在9*9的格子里面,如果不在就让玩家重新输入,可以用while循环实现重复的过程,拿到这个坐标以后判断是否踩雷,如果踩雷则弹出被炸死的信息,然后打印炸弹的位置,结束游戏,如果没有,则用一个函数来计算周围有多少个炸弹,定义个整数win来统计已经判断安全的位置,最后用所有的格子数减去炸弹数,再让win和这个数比较,就可以得到是否已经全部盘查完毕,如果是,就宣布游戏胜利,结束游戏,如果没有排查完,就继续游戏继续排查

//扫雷
void findbombs(char bombs[ROWS][COLS],char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;

	while (win<(row*col- bomb_count))
	{
		printf("请输入你想排查的坐标: ");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (bombs[x][y] == '1')
			{
				printf("你被炸弹炸死了\n");
				printboard(bombs, ROW, COL);
				break;
			}
			else
			{
				int count = countbombs(bombs, x, y);
				show[ x ][ y ] = count + '0';
				printboard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("输入坐标不合法,请重新输入\n");
		}
	}
	if (win == (row * col - bomb_count))
	{
		printf("恭喜你,排掉了全部的炸弹,游戏胜利!!!\n");
		printboard(bombs, ROW, COL);
	}
}

这里我们定义一个函数来判断周围炸弹数量

//统计周围炸弹数量
int countbombs(char bombs[ROWS][COLS], int x, int y)
{
	int ret = 0;
	ret=bombs[x - 1][y - 1] + bombs[x - 1][y] + bombs[x - 1][y + 1] + bombs[x][y - 1] + bombs[x][y + 1] + bombs[x + 1][y - 1] + bombs[x + 1][y] + bombs[x + 1][y + 1] - 8 * '0';
	return ret;
}

        以上就完成了扫雷游戏的绝大部分内容,剩下的只需要稍微拼接,修补一下就可以得到完整的程序代码,以下完整的一下代码奉上

7.游戏的完整代码

1.头文件代码

#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>

//定义行和列
#define ROW 9
#define COL 9

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

#define bomb_count 10


//打印菜单
void mune();

//游戏逻辑主程序
void game();

//棋盘初始化
void initboard(char board[ROWS][COLS],int row,int col,char temp);

//打印棋盘
void printboard(char board[ROWS][COLS], int row, int col);

//生成随机炸弹位置
void setbombs(char board[ROWS][COLS],int row,int col);

//扫雷
void findbombs(char bombs[ROWS][COLS], char show[ROWS][COLS], int row, int col);

//统计周围炸弹数量
int countbombs(char bombs[ROWS][COLS], int x, int y);

2.游戏逻辑代码

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

//打印菜单
void mune()
{
	printf("--------------------------\n");
	printf("---------1.Play ----------\n");
	printf("--------------------------\n");
	printf("---------2.Esc  ----------\n");
	printf("--------------------------\n");
}

//初始化
void initboard(char board[ROWS][COLS], int row, int col,char set)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = set;
		}
	}
}

//打印棋盘
void printboard(char board[ROWS][COLS], int row, int col)
{
	printf("------扫雷游戏------\n");
	printf(" ");
	for (int i = 1; i <= col; i++)
	{
		printf(" %d", i);
	}
	printf("\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (int j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("------扫雷游戏------\n");
}

//随机生成地雷位置
void setbombs(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = bomb_count;

	while (count > 0)
	{
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;
		if (board[x + 1][y + 1] == '0')
		{
			board[x + 1][y + 1] = '1';
			count--;
		}
	}
	
}

//统计周围炸弹数量
int countbombs(char bombs[ROWS][COLS], int x, int y)
{
	int ret = 0;
	ret=bombs[x - 1][y - 1] + bombs[x - 1][y] + bombs[x - 1][y + 1] + bombs[x][y - 1] + bombs[x][y + 1] + bombs[x + 1][y - 1] + bombs[x + 1][y] + bombs[x + 1][y + 1] - 8 * '0';
	return ret;
}

//扫雷
void findbombs(char bombs[ROWS][COLS],char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;

	while (win<(row*col- bomb_count))
	{
		printf("请输入你想排查的坐标: ");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (bombs[x][y] == '1')
			{
				printf("你被炸弹炸死了\n");
				printboard(bombs, ROW, COL);
				break;
			}
			else
			{
				int count = countbombs(bombs, x, y);
				show[ x ][ y ] = count + '0';
				printboard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("输入坐标不合法,请重新输入\n");
		}
	}
	if (win == (row * col - bomb_count))
	{
		printf("恭喜你,排掉了全部的炸弹,游戏胜利!!!\n");
		printboard(bombs, ROW, COL);
	}
}

3.游戏主体代码

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void game()
{
	char bomb[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘
	initboard(bomb, ROWS, COLS, '0');
	initboard(show, ROWS, COLS, '#');

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

	//生成随机炸弹位置
	setbombs(bomb, ROWS, COLS);
	//printboard(bomb, ROW, COL);

	//开始扫雷
	findbombs(bomb, show, ROW, COL);

}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	printf("请进行输入确认是否开始游戏\n");

	do
	{
		mune();
		scanf("%d", &input);

		switch(input)
		{
		case 1:
			printf("\t开始游戏\n");
			game();
			break;
		case 2:
			printf("\t退出游戏\n");
			break;
		default:
			printf("非法输入,请重试\n");
			break;
		}
	} while (input != 2);

	return 0;
}


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。