【C语言】实现扫雷游戏

目录

前言

1、test.c文件

main函数

game函数

2、game.c文件

初始化棋盘 init_board函数

打印棋盘display_board函数

 设置雷setmine函数

找雷finemine函数

getmine函数

3、test.c   game.c  game.h所有的代码

test.c代码

game.c代码

game.h

4 、后面可以改进的部分


前言

大家好,今天利用C语言实现9行9列扫雷游戏的全过程,十分详细,供大家参考

需要创建三个文件 一个test.c用来调用函数   game.c用于各种函数的具体实现 ,game.h头文件用于各种函数的声明 以及宏常量的一些定义

1、test.c文件

main函数

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));  //时间随机函数
	do
	{
		menu();//菜单界面
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();//实现游戏函数
			break;
		case 0:
			printf("退出游戏!");
			break;
		default:
			printf("输出错误,请重新输入\n");
			break;
		}
	}
	while (input);



	return 0;
}

这部分主要用于菜单的选择界面  输入1开始游戏 输入0退出游戏 输入其他重新输入

其中首先会调用menu菜单函数 代码如下

void menu()
{

	printf("*****************************\n");
	printf("*****************************\n");
	printf("*******1、开始游戏***********\n");
	printf("*******0、exit***************\n");
	printf("*****************************\n");
	printf("*****************************\n");
	printf("*****************************\n");


}

game函数

然后玩家打1 怎会调用 game函数 开始扫雷游戏

void game()
{
	char mine[ROWS][COLS];  //设置成11行11列是防止数组越界
	char show[ROWS][COLS];
	init_board(mine, ROWS, COLS, '0');  //初始化这两个棋盘  一个埋雷 一个显示
	init_board(show, ROWS, COLS, '*');
	//display_board(mine, ROW, COL); //打印棋盘时 打印9行9列就好
	//printf("---------------------\n");
	//display_board(show, ROW, COL); //打印棋盘时 打印9行9列就好
	setmine(mine, ROW, COL);        //设置雷  在mine初始化的棋盘中设置
	//display_board(mine, ROW, COL);//打印棋盘
	//printf("---------------------\n");
    display_board(show, ROW, COL);
	findmine(mine,show, ROW, COL);   //找雷  在show初始化的棋盘中去找雷
}

game函数中包含有创建了两个数组  该数组都是11行11列的 因为防止在第一行和列 以及最后一行和列在判断四周列时会发生数组越界

初始化两个棋盘    其中一个棋盘设置雷(这部分不会显示出来玩家不能看到) 一个是玩家棋盘(玩家可以看到)

用init_board函数初始化这两个棋盘 设置雷的棋盘刚开始全是‘0’   玩家棋盘初始化设置全是‘ * ’

然后display_board函数可以将这些棋盘显示出来(只是设置雷的棋盘最后不会显示)

setmine函数用来设置雷

findmine函数用来使玩家找雷

以上就是test.c的主要函数

2、game.c文件

这部分主要展示game函数中的各个函数的具体实现

初始化棋盘 init_board函数

void init_board(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}

}

使用set可以决定传‘0’或者‘ * ’  是雷棋盘和玩家的棋盘都可以初始化

打印棋盘display_board函数

void display_board(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (j = 0; j <=col; j++)  //从0开始 多打印一列
	{
		printf("%d ", j);//打印列号
	}
	printf("\n");
	for (i = 1; i <= row; i++)  
	{
		printf("%d ", i);  //打印行号
		for (j = 1; j <=col; j++)
		{
			
			printf("%c ", board[i][j]);

		}
		printf("\n");
	}

}

将二维数组打印出来  注意打印出来行号和列号 打印9行9列 但在第一行前面一行打印每列的列号 

在第一列前面打印每行的行号 

要注意的是打印列号因为第一列前面多了一列行号    因此 i 应从0开始 这样才能将9行9列对齐 其余都是从1开始的

 设置雷setmine函数

void setmine(char board[ROWS][COLS], int row, int col)
{
	//布置10个雷
	int count = EASY_COUNT; //初始化10个
	while (count)
	{
		int x = rand() % row + 1;   // 之前是0~8 后面+1 变成1~9的数字
		int y = rand() % col + 1;  // 之前是0~8 后面+1 变成1~9的数字
		if (board[x][y]=='0')  //如果有1 说明已经布置过雷 需要重新布置  如果是0说明没有布置过雷
		{
			board[x][y] = '1';
			count--; //直到10个雷全部布置完
		}
	}	
}

也是利用到随机时间函数 后面用行与列取模加1 得到1~9的数字 可以放在二维9乘9的数组中

将雷设置为1 循环直到雷数全部设置完

找雷finemine函数

void findmine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col)  //找雷
{
	int win = 0;
	int sum = row*col-EASY_COUNT;  //表示的是行乘列在减去布置的雷数 就是空雷的数量
	int x = 0;
	int y = 0;
	while (win < sum) //循环到把是所有没有雷的坐标都点到 则游戏结束
	{
		printf("请输入坐标:\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')  //这里避免该雷判断过 避免重复需要重新判断 没判断过才去显示
			{
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被雷炸死了,游戏结束\n");
					break;
				}
				else
				{
					int count = getminecount(mine, x, y);  //函数内定义一个得到count的函数
					show[x][y] = count + '0';  //因为数组里存放的是字符 而count是整型 所以加上‘0’让整型数字变成字符数字
					display_board(show, ROW, COL);  //打印这个棋盘
					win++;
				}
			}
			else
			{
				printf("该坐标已经判断过,请重新输入坐标\n");
			}
			
		}
		else
		{
			printf("输入的坐标非法,请重新输入\n");
		}
	}
	if (win == sum)
	{
		printf("恭喜你,游戏胜利!");
		display_board(show, ROW, COL);
	}

}

具体思路就是玩家输入坐标将全部没有雷的坐标全部填满 则玩家就会获胜 

如果没满的情况下就一直输入坐标并且判断  如果输入的坐标不等于‘*’说明这个位置已经输入过了 没有的话则输入

如果输入的坐标在设置雷的棋盘里等于1 说明这个位置是雷 则直接退出循环 游戏失败  

如果输入的坐标在雷的棋盘不是1 则需要用到自己定义的getmine函数来计算周围雷的数量 在将这个数量用字符的形式赋给玩家的那个棋盘  这是win++  在与没有雷的sum比较 如果小于继续输入判断 等于了则退出循环 游戏胜利!

getmine函数

int getminecount(char mine[ROWS][COLS], int x, int y)  //统计mine里面有多少了雷
{
	return(mine[x][y - 1] + mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1]
		+ mine[x + 1][y] + mine[x + 1][y - 1]-8*'0');   //切记不要忘了这个8*‘0’ 因为需要返回的count是整形 而存在数组中的是字符  
	                                                    //每一个字符都应该减去一个字符‘0’ 才能是整型  8个字符就减8个‘0’
	                                                    
	
}

该函数将雷棋盘里传入的坐标上下左右都加起来 因为有雷为1 加起来周围有几个雷就有几个1 

注意的是需要返回的是整型数 而数组是字符 需要每一个字符1减去‘0’转换成整型1 8个则需要减8*‘0’  再返回 

至此  game.c中所有函数的实现细节已经完成

3、test.c   game.c  game.h所有的代码

test.c代码

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"




void menu()
{

	printf("*****************************\n");
	printf("*****************************\n");
	printf("*******1、开始游戏***********\n");
	printf("*******0、exit***************\n");
	printf("*****************************\n");
	printf("*****************************\n");
	printf("*****************************\n");


}

void game()
{
	char mine[ROWS][COLS];  //设置成11行11列是防止数组越界
	char show[ROWS][COLS];
	init_board(mine, ROWS, COLS, '0');  //初始化这两个棋盘  一个埋雷 一个显示
	init_board(show, ROWS, COLS, '*');
	//display_board(mine, ROW, COL); //打印棋盘时 打印9行9列就好
	//printf("---------------------\n");
	//display_board(show, ROW, COL); //打印棋盘时 打印9行9列就好
	setmine(mine, ROW, COL);        //设置雷  在mine初始化的棋盘中设置
	//display_board(mine, ROW, COL);//打印棋盘
	//printf("---------------------\n");
    display_board(show, ROW, COL);
	findmine(mine,show, ROW, COL);   //找雷  在show初始化的棋盘中去找雷
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));  //时间随机函数
	do
	{
		menu();//菜单界面
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();//实现游戏函数
			break;
		case 0:
			printf("退出游戏!");
			break;
		default:
			printf("输出错误,请重新输入\n");
			break;
		}
	}
	while (input);



	return 0;
}

game.c代码

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"


void init_board(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}

}

void display_board(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (j = 0; j <=col; j++)  //从0开始 多打印一列
	{
		printf("%d ", j);//打印列号
	}
	printf("\n");
	for (i = 1; i <= row; i++)  
	{
		printf("%d ", i);  //打印行号
		for (j = 1; j <=col; j++)
		{
			
			printf("%c ", board[i][j]);

		}
		printf("\n");
	}

}

void setmine(char board[ROWS][COLS], int row, int col)
{
	//布置10个雷
	int count = EASY_COUNT; //初始化10个
	while (count)
	{
		int x = rand() % row + 1;   // 之前是0~8 后面+1 变成1~9的数字
		int y = rand() % col + 1;  // 之前是0~8 后面+1 变成1~9的数字
		if (board[x][y]=='0')  //如果有1 说明已经布置过雷 需要重新布置  如果是0说明没有布置过雷
		{
			board[x][y] = '1';
			count--; //直到10个雷全部布置完
		}
	}	
}
int getminecount(char mine[ROWS][COLS], int x, int y)  //统计mine里面有多少了雷
{
	return(mine[x][y - 1] + mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1]
		+ mine[x + 1][y] + mine[x + 1][y - 1]-8*'0');   //切记不要忘了这个8*‘0’ 因为需要返回的count是整形 而存在数组中的是字符  
	                                                    //每一个字符都应该减去一个字符‘0’ 才能是整型  8个字符就减8个‘0’
	                                                    
	
}

void findmine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col)  //找雷
{
	int win = 0;
	int sum = row*col-EASY_COUNT;  //表示的是行乘列在减去布置的雷数 就是空雷的数量
	int x = 0;
	int y = 0;
	while (win < sum) //循环到把是所有没有雷的坐标都点到 则游戏结束
	{
		printf("请输入坐标:\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')  //这里避免该雷判断过 避免重复需要重新判断 没判断过才去显示
			{
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被雷炸死了,游戏结束\n");
					break;
				}
				else
				{
					int count = getminecount(mine, x, y);  //函数内定义一个得到count的函数
					show[x][y] = count + '0';  //因为数组里存放的是字符 而count是整型 所以加上‘0’让整型数字变成字符数字
					display_board(show, ROW, COL);  //打印这个棋盘
					win++;
				}
			}
			else
			{
				printf("该坐标已经判断过,请重新输入坐标\n");
			}
			
		}
		else
		{
			printf("输入的坐标非法,请重新输入\n");
		}
	}
	if (win == sum)
	{
		printf("恭喜你,游戏胜利!");
		display_board(show, 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 init_board(char board[ROWS][COLS], int rows, int cols, char set);  //这里面声明 注意int rows 和int cols不能写成大写因为实参是宏常量 形参是变量 这里形参和实参不能相同
void display_board(char board[ROWS][COLS], int rows, int cols);  //打印棋盘声明
void setmine(char board[ROWS][COLS], int row, int col);  //设置雷的声明
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);  //找类的声明
int getminecount(char mine[ROWS][COLS], int x, int y);    //getminecount函数的声明



4 、后面可以改进的部分

以上就可以实现建议的扫雷 但现有的游戏中如果周围没有雷时会展开一大片 这项功能目前并没有在此实现  目前只能玩家一个一个输入 将全部没有雷的坐标全部填满才可以 

未来可以实现此功能

满足此功能需要满足以下条件

1、确保输入的次坐标不是雷

2、之前没有输入过并且周围没有雷

3、如果满足count是0则递归实现     直到周围有雷的情况再继续往后执行 show[x][y] = count + '0'; 

后面可以将此功能加入 实现如果输入此坐标周围没有雷的话递归 实现输入一次win不止加一个

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值