C语言之扫雷(递归、文件)

这是一个C语言版本的扫雷小游戏,自我感觉还比较完善,首先我们先来说一下扫雷的游戏思路
//1、打印菜单(1、 开始游戏 2 、退出游戏)
//2、开始游戏后,需要打印玩家地图
//3、初始地图为*表示,字符‘o’代表地雷
//4、玩家开始排雷(分四种情况:1、玩家踩雷,游戏结束 2、玩家没有踩雷,提示周围有多少颗雷 3、如果周围没有地雷,则递归找出该位置相应的没有地雷的位置 4、玩家排雷完成,游戏胜利)
//5、游戏结束,打印雷区分布图,显示玩家耗时,排名(这里用文件保存所用时间,按时间排名)
示例代码如下

//扫雷游戏思路
//1、打印菜单(1、 开始游戏 2 、退出游戏)
//2、开始游戏后,需要打印玩家地图
//3、初始地图为*表示,字符‘o’代表地雷
//4、玩家开始排雷(分三种情况:1、玩家踩雷,游戏结束 2、玩家没有踩雷,提示周围有多少颗雷 3、玩家排雷完成,游戏胜利)
//5、游戏结束,打印雷区分布图
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define MINE_COUNT 10

char player_map[ROW + 2][COL + 2]; //玩家地图
char mine_map[ROW + 2][COL + 2];   //雷区地图


//打印玩家扫雷地图
void print(char map[ROW+2][COL+2])
{
	printf("  ");
	for (int i = 1; i <= ROW; i++)
	{
		printf(" %d", i);
	}
	printf("\n");
	printf("   -----------------\n");
	for (int row = 1;  row<= ROW; row++)
	{
		printf("%d| ", row);
		printf("%c %c %c %c %c %c %c %c %c",map[row][1], map[row][2], map[row][3], map[row][4],
			map[row][5], map[row][6], map[row][7], map[row][8], map[row][9]);
		
		printf("\n");
	}
}


//玩家没有踩雷,判断该位置周围存在几颗雷
int  exist_mine(char mine_map[ROW + 2][COL + 2], char player_map[ROW + 2][COL + 2], int row, int col) {

	if (player_map[row][col] == '*') {
		int num = 0;
		for (int i = row - 1; i <= row + 1; i++)
		{
			for (int j = col - 1; j <= col + 1; j++)
			{
				if (mine_map[i][j] == 'o')
				{
					num++;
				}
			}
		}
		player_map[row][col] = num + '0';
		if (player_map[row][col] == '0'&&row >= 1 && row <= ROW && col >= 1 && col <= COL) {
			return (exist_mine(mine_map, player_map, row - 1, col) +
				exist_mine(mine_map, player_map, row - 1, col - 1) +
				exist_mine(mine_map, player_map, row - 1, col + 1) +
				exist_mine(mine_map, player_map, row, col - 1) +
				exist_mine(mine_map, player_map, row, col + 1) +
				exist_mine(mine_map, player_map, row + 1, col - 1) +
				exist_mine(mine_map, player_map, row + 1, col) +
				exist_mine(mine_map, player_map, row + 1, col + 1)) + 1;
		}
		else 
		{
			if (row >= 1 && row <= ROW && col >= 1 && col <= COL) 
			{
				return 1;
			}
			return 0;
		}
	}
	else {
		return 0;
	}
}

int check_mine(char mine_map[ROW + 2][COL + 2], int row, int col) {
	//判定是不是扫到了雷,如果是扫到了就直接退出游戏并且打印棋盘
	if (mine_map[row][col] == 'o') {
		print(mine_map);
		return 1;
	}
	//如果不是扫到了雷就统计周围雷的数量并且打印出现在的棋盘
	return 0;
}


//初始化(初始化玩家地图为“*”,初始化雷区分布)
void Init(char player_map[ROW + 2][COL + 2],char mine_map[ROW+2][COL+2])
{
	for (int row = 1; row <= ROW; row++)
	{
		for (int col = 1; col <= COL; col++)
		{
			player_map[row][col] = '*';
			mine_map[row][col] = '*';
		}
	}
	int count = MINE_COUNT;//count 为雷的个数
	while (count!=0)
	{
		int row = rand() % 9 + 1;
		int col = rand() % 9 + 1;
		if (mine_map[row][col] == '*')
		{
			mine_map[row][col] = 'o';
			count--;
		}
		else
		{
			continue;
		}

	}
}

//开始游戏,玩家开始扫雷
void Start_Game()
{
	int start_time = (unsigned)time(0);
	FILE * fp = fopen("time.txt", "r");
	int current_time;
	fscanf(fp, "%d", &current_time);
	fclose(fp);
	//printf("您扫雷用时:%d秒\n", current_time);
	int count = 0;
	while (1)
	{
		print(player_map);
		printf("\n");
		printf("请您输入您想要排雷的位置(x y):");
		int row = 0;
		int col = 0;
		scanf("%d %d", &row, &col);
		if (row<1 || row>ROW || col<1 || col>COL)
		{
			printf("您的输入有误请重新输入:\n");
			continue;
		}
		if (player_map[row][col]!='*')
		{
			printf("该位置已经被翻开过,请重新输入:\n");
			continue;
		}
		if (check_mine(mine_map, row, col)) {
			printf("您踩到雷了,请重新开始\n");
			break;
		}
		else {
			//打印出不是雷的数字,用递归进行
			count += exist_mine(mine_map, player_map, row, col);

		}
		if (count == (ROW*COL - MINE_COUNT))
		{
			printf("恭喜您,扫雷成功!\n");
			print(mine_map);
			int end_time = (unsigned)time(0);
			int time = end_time - start_time;
			if (time < current_time)
			{
				printf("恭喜您,您打破了最高纪录,您扫雷用时间是%d秒\n", time);
				fp = fopen("time.txt", "w");
				fprintf(fp, "%d", time);
				fclose(fp);
				break;
			}
			printf("真遗憾!您所用时间是%d秒,未能打破纪录,再接再厉。\n", time);
			break;
		}
	}
}


//打印菜单选项
void menu()
{
	printf("**********************\n");
	printf("1、开始游戏\n");
	printf("2、退出游戏\n");
	printf("**********************\n");
}

int main()
{
	srand((unsigned)time(0));//产生一个随机种子
	while (1)
	{
		menu(); //打印菜单
		int choice = 0;
		scanf("%d", &choice);
		if (choice == 1)//选择开始游戏
		{
			printf("\n"); //为了好看
			Init(player_map, mine_map);//初始化地图
			Start_Game();//开始游戏,玩家输入坐标  
		}
		if (choice == 2)
		{
			printf("游戏结束!\n");
			break;
		}
	}
	system("pause");
	return 0;
}

虽然看起来不是特别难,但当你实际去写的时候会发现各种各样的问题,在我实际去写代码时,其实普通的扫雷问题并不大,但对我来说要加上递归去实现没有雷的地方递归打印,这是一个比较难理解的地方,我也是花了好久才写正确,最后加入文件实现排名并不难,总体来说。这个扫雷小游戏还是挺有意思的,大家不妨可以试着玩下,看看你花了多长时间成功,悄悄地透漏一下,我扫雷花了不到一分钟,哈哈 , 欢迎来战! 运行结果如下图,部分截取。
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值