老鼠走迷宫

老鼠走迷宫

程序开始运行时显示一个迷宫地图,迷宫中央有一只老鼠,迷宫的右下方有一个粮仓。游戏的任务是使用键盘上的方向键操纵老鼠在规定的时间内走到粮仓处。
要求:
程序设计任务,所要实现的功能:
1) 老鼠形象可辨认,可用键盘操纵老鼠上下左右移动;
2) 迷宫的墙足够结实,老鼠不能穿墙而过;
3) 正确检测结果,若老鼠在规定时间内走到粮仓处,提示成功,否则提示失败;
4) 添加编辑迷宫功能,可修改当前迷宫,修改内容:墙变路、路变墙;
5) 找出走出迷宫的所有路径,以及最短路径。
6)统计地图共有几条通路
7)从文件夹中获取地图文件,读入程序中
8)新建地图,存入文件中
注意事项:
vs中运行,如果在其他环境运行,需要修改代码scanf_s,_getch,_kbhit等函数,去掉"_"
vs中运行的时候,需要预处理警告,代码文件的属性中添加警告预处理:_CRT_SECURE_NO_WARNINGS
运行前要在代码文件目录下存入一个地图文件,或者先创建一个地图
#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
#include<time.h>

int A = 1;

int m = 0, n = 0;
int p = 0, q = 0;		//老鼠(逻辑)
int x = 0, y = 0;		//粮仓


int maze[9][9];    //地图最大尺寸

struct best                  //用于记录最短路径的结构体
{
	int min;
	int b[9][9];
}Best;

int answer;		//正确路线个数
int g;


//打印地图
print_map(int a)
{
	for (int i = 0; i < A; i++)
	{
		for (int j = 0; j < A; j++)
		{
			if (maze[i][j] == 2)
			{
				printf("■");
			}

			else if (maze[i][j] == 1)
			{
				printf("鼠");
			}
			else if (maze[i][j] == 3)
			{
				printf("粮");
			}
			else
			{
				printf("  ");
			}
		}
		printf("\n");
	}
}

//新建地图,并存入文件的模块--我
void create_plat(int a)   
{
	A = a;
	
	int i, j, s;
cc:	printf("请输入0和2,0代表通路,2代表墙体(数字用空格隔开),输入规格是%dx%d\n", A, A);
	for (i = 1; i <= A; i++)
	{
		printf("第%d行:", i);
		for (j = 1; j <= A; j++)
		{
			scanf_s("%d", &s);
			if (s == 0 || s == 2)
				maze[i-1][j-1] = s;
			else
			{
				system("cls");
				printf("----输入错误请重新输入----\n");
				goto cc;
			}
		}
	}

aa: printf("请设置老鼠的初始位置(x, y)(1-%d,1-%d):\n", A, A);

	//清除来自键盘的30多个缓存字符,防止死循环bug
	for (i = 0; i < 30; i++)
		fflush(stdin);			//flush一下

	scanf_s("%d,%d", &p, &q);
	if (p <= A && q <= A && p > 0 && q > 0)
		maze[p - 1][q - 1] = 1;
	else
	{
		system("cls");
		printf("----输入错误,请重新输入,在%dx%d的范围内----\n", A, A);
		goto aa;
	}

bb: printf("请设置粮仓的位置(x, y):\n");

	//清除来自键盘的30多个缓存字符,防止死循环bug
	for (i = 0; i < 30; i++)
		fflush(stdin);

	scanf_s("%d,%d", &x, &y);
	if (x <= A && y <= A && x > 0 && y > 0 && (x != p || y != q))
		maze[x - 1][y - 1] = 3;
	else
	{
		system("cls");
		printf("----输入错误,请重新输入,在%dx%d的范围内----\n", A, A);
		goto bb;
	}

	//文件保存地图
	FILE *fp;
	fp = fopen("map.txt", "w");		//w只写,会清除再写
	for (i = 0; i < A; i++)
	{
		for (j = 0; j < A; j++) {
			fprintf(fp, "%d\t", maze[i][j]);
		}
		fprintf(fp, "%c", '\n');
	}
	fprintf(fp, "%d\t", p);
	fprintf(fp, "%d\t", q);
	fprintf(fp, "%d\t", x);
	fprintf(fp, "%d\t", y);
	fprintf(fp, "%d\t", A);
	fclose(fp);

	printf("----地图新建完成,并保存成功!!!----\n");
	system("pause");
}

//地图获取,读入程序--胡
void get_map(int a)   
{
	A = a;
	int i, j;
	FILE *fp;
	fp = fopen("map.txt", "r");
	if (!fp)
	{
		printf("文件不存在,请重新打开\n");
		system("pause");
	}
	else
	{
		for (i = 0; i < A; i++)
		{
			for (j = 0; j < A; j++)
			{
				fscanf(fp, "%d\t", &maze[i][j]);
			}	
			fscanf(fp, "\n");
		}
		fscanf(fp, "%d\t", &p);
		fscanf(fp, "%d\t", &q);    //读取老鼠的位置
		fscanf(fp, "%d\t", &x);
		fscanf(fp, "%d\t", &y);    //读取粮仓的位置
		fscanf(fp, "%d\t", &A);
		printf("读取成功,请查看新地图!\n");
		print_map(A);
		system("pause");
	}
	fclose(fp);
	
}

//修改地图模块--高
void alter_map()    
{
	int i, j, select, a, b;
	FILE *fp;
	while (1)
	{
		system("cls");

		print_map(A); //显示地图

		printf("  =============----修改地图------===================\n");
		printf(" |请选择:                                          |\n");
		printf(" |              1.修改为墙体;                      |\n");
		printf(" |              2.修改为通路;                      |\n");
		printf(" |              3.保存修改地图;                    |\n");
		printf(" |              0.退出修改功能;                    |\n");
		printf("  ===========(请输入相应数字执行其功能)===========\n");
		fflush(stdin);  //清除键入的缓存
		scanf("%d", &select);

		if (select < 4 && select >= 0)
		{
			switch (select)
			{
			case 1:	printf("围墙内为修改范围,范围是%dx%d\n", A, A);
				printf("请输入坐标(x, y)修改地图:\n");

				//清除来自键盘的30多个缓存字符,防止死循环bug
				for (i = 0; i < 30; i++)
					fflush(stdin);

				scanf("%d,%d", &a, &b);
				if (a <= A && b <= A && a > 0 && b > 0 && maze[a][b] != 1 && maze[a][b] != 3)
					maze[a-1][b-1] = 2;
				else
				{
					printf("输入错误请重新输入,不能在围墙、粮仓和老鼠的位置修改哦(*/ω\*)\n");
					system("pause");
				}
				break;
			case 2:	printf("围墙内为修改范围,范围是%dx%d\n", A, A);
				printf("请输入坐标x,y(行,列)修改地图:\n");
				//清除来自键盘的30多个缓存字符,防止死循环bug
				for (i = 0; i < 30; i++)
					fflush(stdin);

				scanf("%d,%d", &a, &b);
				if (a <= A && b <= A && a > 0 && b > 0 && maze[a][b] != 1 && maze[a][b] != 3)
					maze[a-1][b-1] = 0;
				else
				{
					printf("输入错误请重新输入,不能在围墙、粮仓和老鼠的位置修改哦(*/ω\*)\n");
					system("pause");
				}
				break;
			case 3:
			{			//文件形式保存修改后地图
				fp = fopen("map.txt", "w");
				for (i = 0; i < A; i++)
				{
					for (j = 0; j < A; j++)
						fprintf(fp, "%d\t", maze[i][j]);
					fprintf(fp, "%c", '\n');
				}
				fprintf(fp, "%d\t", p);
				fprintf(fp, "%d\t", q);
				fprintf(fp, "%d\t", x);
				fprintf(fp, "%d\t", y);
				fclose(fp);

				printf("----地图修改完成,并保存成功!!!----\n");
				system("pause");
			}
			break;
			case 0: break;
			}
		}
		else
		{
			printf("----请按规定输入----\n");
			system("pause");
		}

		if (select == 0)
			break;
	}
}

//开始游戏--杨
void game()  
{
	m = p-1; n = q-1;
	int i, j, v = 0, t = 0;          //t为初始时间
	char str;
	time_t start, end;				//时间类型
	start = time(NULL);

	print_map(A);
	printf("(按w↑s↓a← d→移动)\n----请在15秒内通关----\n"); //初始化地图

	while (1)
	{
		printf("时间:%d\r", t);
		if (_kbhit())				//输入控制,检查键盘有无输入,有非0,无1
		{
			str = _getch();
			if (str == 'w') //上
			{
				if (maze[m - 1][n] == 0)
				{
					maze[m - 1][n] = 1;
					maze[m][n] = 0;
					m = m - 1;
				}
				else if (maze[m - 1][n] == 3)
				{
					maze[m][n] = 0;
					v = 1;
				}
			}
			else if (str == 's')   //下
			{
				if (maze[m + 1][n] == 0)
				{
					maze[m + 1][n] = 1;
					maze[m][n] = 0;
					m = m + 1;
				}
				else if (maze[m + 1][n] == 3)
				{
					maze[m][n] = 0;
					v = 1;
				}
			}
			else if (str == 'a')   //左
			{
				if (maze[m][n - 1] == 0)
				{
					maze[m][n - 1] = 1;
					maze[m][n] = 0;
					n = n - 1;
				}
				else if (maze[m][n - 1] == 3)
				{
					maze[m][n] = 0;
					v = 1;
				}
			}
			else if (str == 'd')  //右
			{
				if (maze[m][n + 1] == 0)
				{
					maze[m][n + 1] = 1;
					maze[m][n] = 0;
					n = n + 1;
				}
				else if (maze[m][n + 1] == 3)
				{
					maze[m][n] = 0;
					v = 1;
				}
			}
			else;

			system("cls");
			printf("显示迷宫:\n");  //显示游戏地图
			print_map(A);
			printf("(按w↑s↓a← d→移动)\n请在15秒内通关☆(-o⌒) \n");
		}
		else;

		if (v == 1)  //判断是否通关
		{
			printf("\n----恭喜通关----\n");
			system("pause");
			break;
		}

		if (t > 15)   //规定时间到后结束游戏
		{
			printf("\n----未在规定时间内通关,游戏失败----\n");
			maze[m][n] = 0;   //清除最后所在位置
			system("pause");
			break;
		}

		end = time(NULL);
		t = difftime(end, start);
	}

}

//统计地图共有几条通路--崔
void path_result(int m, int n)  
{
	//m = p - 1; n = q - 1;
	maze[m][n] = 1;

	//printf("(%d, %d)", p, q);
	//printf("m=%d, n=%d\n", m+1, n+1);


	if (maze[m][n + 1] == 3 || maze[m][n - 1] == 3 || maze[m + 1][n] == 3 || maze[m - 1][n] == 3)   //判断当前位置上下左右是否有粮仓
	{
		++answer;    //统计一个地图的所有可能性的次数
		//printf("已通关%d次\n", answer);
	}
	// 递归部分,即寻找路径的部分
	if (maze[m][n + 1] == 0) path_result(m, n + 1);  //右
	if (maze[m + 1][n] == 0) path_result(m + 1, n);  //下
	if (maze[m][n - 1] == 0) path_result(m, n - 1);  //左
	if (maze[m - 1][n] == 0) path_result(m - 1, n);  //上
	
	maze[m][n] = 0;		//都走完了,变为路
	

}

//显示最优路径的模块--郝
void path_best(int p, int q, int l)     
{
	int i, j, c, k;

	maze[p][q] = 1;

	if (maze[p][q + 1] == 3 || maze[p][q - 1] == 3 || maze[p + 1][q] == 3 || maze[p - 1][q] == 3)   //判断当前位置上下左右是否有粮仓
	{
		if (Best.min > l)
		{
			Best.min = l;
			for (i = 0; i < A; i++)
				for (j = 0; j < A; j++)
					Best.b[i][j] = maze[i][j];
		}
		g++;
		k = ((double)g / answer) / 2 * 100 + 50;  //计算后面一半完成的百分比情况

		printf("已完成%d%%,请继续等待( ̄▽ ̄)/\r", k);

		c = g;

		if (c == answer)               //防止过度循环,比较answer条路径。   191844是检测了我自己建的地图的全部可能路径次数 文件是plat.txt
		{
			printf("已列举最优解!!!比较了前%d个方案中的最优解( ̄︶ ̄)↗\n", answer);
			for (i = 0; i < A; i++)
			{
				for (j = 0; j < A; j++)
					if (Best.b[i][j] == 2)
					{
						printf("■");
					}
					else if (Best.b[i][j] == 1)
						printf("の");
					else if (Best.b[i][j] == 3)
						printf("粮");
					else
						printf("  ");
				printf("\n");
			}
			printf("已显示最优解,方案如上!(〃'▽'〃)\n");
			maze[p][q] = 0;
			return;
			//	exit(0);
		}

	}

	++l;

	if (g != answer)
	{
		if (maze[p][q + 1] == 0) path_best(p, q + 1, l);  //右
		if (maze[p + 1][q] == 0) path_best(p + 1, q, l);  //下
		if (maze[p][q - 1] == 0) path_best(p, q - 1, l);  //左
		if (maze[p - 1][q] == 0) path_best(p - 1, q, l);  //上
	}
	maze[p][q] = 0;
}

//寻找通关路径的模块--朱
void path_find(int p, int q)  
{
	int i, j, c;
	maze[p][q] = 1;

	c = g;
	if (c == 15)               //防止过度循环,暂时只能显示15条路径,可调节。
	{
		printf("已列举10种可行方案!!方案太多可能列举不完,所以最多列举15个( ̄︶ ̄)↗\n");
		maze[p][q] = 0;
		return;
		//	exit(0);
	}

	if (maze[p][q + 1] == 3 || maze[p][q - 1] == 3 || maze[p + 1][q] == 3 || maze[p - 1][q] == 3)   //判断当前位置上下左右是否有粮仓
	{
		printf("显示路径: \n");
		print_map(A);
		printf("已显示方案,如上!请稍等。。。\n");
		g++;
	}

	if (g != 15)
	{
		if (maze[p][q + 1] == 0) path_find(p, q + 1);  //右
		if (maze[p + 1][q] == 0) path_find(p + 1, q);  //下
		if (maze[p][q - 1] == 0) path_find(p, q - 1);  //左
		if (maze[p - 1][q] == 0) path_find(p - 1, q);  //上
	}
	maze[p][q] = 0;
}

void main()
{
	int select, k;

	while (1)
	{
		system("cls");
		printf("  =============老鼠走迷宫游戏 n.0===================\n");
		printf(" |请选择:                                          |\n");
		printf(" |              1.获取地图;                        |\n");
		printf(" |              2.新建地图;                        |\n");
		printf(" |              3.查看地图;                        |\n");
		printf(" |              4.修改地图;                        |\n");
		printf(" |              5.显示有几条通关路径;              |\n");
		printf(" |              6.显示最优路径;                    |\n");
		printf(" |              7.显示通关所有路径;                |\n");
		printf(" |              8.开始游戏;                        |\n");
		printf(" |              0.退出系统;                        |\n");
		printf("  ===========(请输入相应数字执行其功能)===========\n");
		for (k = 0; k < 30; k++)
			fflush(stdin);  //清除键盘输入的scanf缓存,防止死循环

		scanf_s("%d", &select);
		if (select >= 0 && select <= 8)    //键盘输入检错
		{
			switch (select)
			{
			case 0:  exit(0);
			case 1:	 system("cls");  //清除菜单 
				get_map(9);        //从文件获取地图到程序
				break;
			case 2:
				system("cls");
				printf("新的地图大小(小于9):", A);
				scanf_s("%d", &A);
				create_plat(A);  //新建地图
				break;
			case 3: 
				system("cls");
				print_map(A);	//显示地图
				system("pause");
				break;
			case 4:   
				alter_map();//修改地图
				break;
			case 5:
				system("cls");
				path_result(p-1, q-1);
				printf("有%d条通路\n", answer);
				answer = 0;
				system("pause");
				break;
			case 6:  
				system("cls");
				g = 0; Best.min = 999;
				path_result(p-1, q-1);    //统计地图所有解的个数
				path_best(p-1, q-1, 1);   //寻找最短的路径
				system("pause");
				break;
			case 7:  
				system("cls");
				g = 0;
				path_find(p-1, q-1);   //寻找所有通关路径
				printf("----已显示所有路径!----\n");
				system("pause");
				break;
			case 8:
				system("cls");
				game();
			default:
				break;
			}
		}
		else
		{
			system("cls");
			printf("----请按规定输入----\n");
			system("pause");
		}
	}
}
/*
void test(int a)
{
	A = a;
}

void main1()
{
	//create_plat(9);
	test(9);
	//get_map();
	path_result(p-1, q-1);
	g = 0; Best.min = 999; 
	path_best(p-1, q-1, 1);
	path_find(p-1, q-1);
	//game();
}
*/

地图文件:
链接: https://pan.baidu.com/s/1eC1N4WD4cS7g5zFo2mc96Q?pwd=1111 提取码: 1111 复制这段内容后打开百度网盘手机App,操作更方便哦

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值