迷宫游戏_完整版

        之前发了一个迷宫游戏,后面说要继续写,现在来填坑了!

编写说明        

1.利用C语言创建了一个迷宫,实现用栈进行寻路,并打印出来

2.利用打印余清屏实现了简单的走迷宫游戏

算法思想

        在此是说明大体思路,具体细节请看代码,我注释的还是比较详尽的。另外,我自己写的迷宫小游戏在这里不多叙述,有兴趣的话自己看一下。

          (1)利用随机函数,二维数组,与递归思想随机产生一个迷宫

  1. 初始化迷宫,将迷宫中的数据全部赋予WALL(宏定义中有,代表0),并将迷宫最外围赋予ROUTE(宏定义中有,代表1),这样是为了防止将来创建迷宫时把迷宫挖穿。
  2. 创建迷宫,主要思路是:随机向迷宫的四个方向判断,如果是WALL,则将改点设置为ROUTE,否则换一个方向判断。递归调用改函数以生成迷宫。
  3. 利用随机函数随机生成迷宫入口,并利用指针将入口的值返回给主函数的in和out。

        (2)实现栈,并利用栈进行迷宫寻路

  1. 利用结构体实现栈的结点,需要注意的是,该结构体中存储的数据是一个含有两个元素的数组,利用该数组存储迷宫的对应下标,可以以此控制迷宫。
  2. 编写入栈函数与出栈函数,要注意的是,在调用该函数之前,先要编写初始化栈的函数,并将迷宫入口的数据赋予栈的入口
  3. 我是直接利用if else语句对迷宫进行判断,如果是路,则进栈,并将原先的迷宫位置的数据该为WALL,如果四周全是WALL,则退栈。
  4. 这样可以找到迷宫的出口,但是也同样会破坏迷宫的结构,所以我将迷宫复制了一份,待栈走完后,利用栈中存储的迷宫位置的数据将迷宫相应位置的数据进行修改,方便最后打印迷宫
  5. 打印迷宫

运行结果插图:

 

源码如下:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 42		//迷宫区域大小,最外层是保护区
#define WALL 0		//表示该位置是墙 wall
#define ROUTE 1		//表示该位置是路 route
#define END 8		//打印路的标识符
typedef struct Stack{
	int arr[2];//利用下标与迷宫对接,将maze[x][y]中的x,y分别存储在arr[0]与arr[1]中
	struct Stack*next;
}Stack;//结构体,使用、实现栈(其实感觉和单链表差不多)
//函数声明
Stack* InitStack(int in, int(*maze)[N]);
Stack* CreatStack(int(*maze)[N], Stack*Top, int x, int y);
Stack* BackStack(int(*maze)[N], Stack*Top, int x, int y);
void FindMaze(Stack*Top, int(*maze)[N], int out);
void Endprint(int(*maze)[N], Stack*Top);
void CopyMaze(int(*maze1)[N], int(*maze2)[N]);
void InitMaze(int(*maze)[N]);
void CreatMaze(int(*maze)[N], int x, int y);
void print(int(*maze)[N]);
void CreatInAndOut(int(*maze)[N], int*in, int*out);
int Game(int *x, int *y, int(*maze)[N], int out, int direction);
int Decide(int x, int y, int direction, int(*maze)[N]);


//初始化栈(顺带创建了第一个栈)
Stack* InitStack(int in, int(*maze)[N]){

	Stack*Top = (Stack*)malloc(sizeof(Stack));//该指针是头结点,即Top->next永远是栈顶
	if (Top == NULL){
		printf("栈初始化函数错误!\n");
		return NULL;
	}
	Top->next = NULL;

	Stack* L = (Stack*)malloc(sizeof(Stack));//重新创建一个指针,将迷宫入口赋予该栈

	L->next = Top->next;
	Top->next = L;
	L->arr[0] = in;
	L->arr[1] = 1;
	*(*(maze + in) + 1) = WALL;//将口封住

	return Top;
}
//头插入法创建栈,返回新的头结点
Stack* CreatStack(int(*maze)[N], Stack*Top, int x, int y) {
	Stack*p = (Stack*)malloc(sizeof(Stack));
	p->arr[0] = x;
	p->arr[1] = y;
	p->next = Top->next;
	Top->next = p;
	*(*(maze + x) + y) = WALL;
	return Top;
}
//退栈,同进栈一样返回新的头结点
Stack* BackStack(int(*maze)[N], Stack*Top, int x, int y){
	Stack*p = (Stack*)malloc(sizeof(Stack));
	p = Top->next;
	Top->next = Top->next->next;
	free(p);
	p = NULL;
	return Top;
}
//迷宫寻路函数(该函数调用入栈与退栈函数)
void FindMaze(Stack*Top, int(*maze)[N], int out){
	//若栈顶元素是迷宫出口,则循环结束
	if ((Top->next)->arr[0] == out && (Top->next)->arr[1] == N - 2){
		return;
	}
	int x = Top->next->arr[0];
	int y = Top->next->arr[1];
	if (*(*(maze + x) + y + 1) == ROUTE) {
		//检测右方是不是路
		FindMaze(CreatStack(maze, Top, x, y + 1) , maze, out);
	}
	else if (*(*(maze + x + 1) +y) == ROUTE) {
		//检测上方是不是路
		
		FindMaze(CreatStack(maze, Top, x + 1, y) , maze, out);
	}
	else if (*(*(maze + x - 1) +y) == ROUTE) {
		//检测下方是不是路
		
		FindMaze(CreatStack(maze, Top, x - 1, y), maze, out);
	}
	else if (*(*(maze + x) + y - 1) == ROUTE) {
		//检测左方是不是路
		
		FindMaze(CreatStack(maze, Top, x, y - 1), maze, out);
	}
	else{
		//死路,退栈
		FindMaze(BackStack(maze, Top, x, y) , maze, out);
	}
}
//打印寻到的路径
void Endprint(int(*maze)[N],Stack*Top){
	Top = Top->next;
	while (Top != NULL){
		int x = Top->arr[0];
		int y = Top->arr[1];
		*(*(maze + x) + y) = END;
		Top = Top->next;
	}
	print(maze);
	
}
//初始化迷宫
void InitMaze(int(*maze)[N]){
	//生成墙体
	for (int i = 0; i < N; ++i){
		for (int j = 0; j < N; ++j){
			*(*(maze + i) + j) = WALL;
		}
	}
	//迷宫外围保护,防止挖穿
	for (int i = 0; i < N; ++i){
		*(*(maze)+i) = ROUTE;
		*(*(maze + N - 1) + i) = ROUTE;
		*(*(maze + i)) = ROUTE;
		*(*(maze + i) + N - 1) = ROUTE;
	}

}
//递归创建迷宫,将其存储在二维数组maze[N][N]中(备注:迷宫创建的算法是参考CSDN上某位大佬的,我把链接放在这 https://blog.csdn.net/jjwwwww/article/details/106586256)
void CreatMaze(int(*maze)[N], int x, int y){
	if (*(*(maze + x) + y) == WALL){//如果该出是墙体,则开始创建迷宫

		//判断迷宫是否会形成环
		if (*(*(maze + x + 1) + y) + *(*(maze + x - 1) + y) + *(*(maze + x) + y + 1) + *(*(maze + x) + y - 1) <= ROUTE) {

			*(*(maze + x) + y) = ROUTE;//调用成功,将该位置设置为:路

			int direction[4] = { 0, 1, 2, 3 };
			for (int i = 4; i > 0; --i){//四个方向都要尝试
				int ret = rand() % i;//随机生成 0 -- i-1 中的数  (0,1,2,3)

				//交换,防止重复
				int tmp = direction[ret];
				direction[ret] = direction[i - 1];
				direction[i - 1] = tmp;


				//由于每次循环i都会变化,故不会出现重复的下标
				switch (direction[i - 1]){
				case 0:CreatMaze(maze, x - 1, y); break;//数组标记上移一位
				case 1:CreatMaze(maze, x + 1, y); break;//数组标记下移一位
				case 2:CreatMaze(maze, x, y - 1); break;//数组标记左移一位
				case 3:CreatMaze(maze, x, y + 1); break;//数组标记右移一位
				default: break;
				}
			}
		}
	}
}
//打印迷宫
void print(int(*maze)[N]){
	for (int i = 0; i < N; ++i){
		for (int j = 0; j < N; ++j){
			if (*(*(maze + i) + j) == END){
				printf("* ");
			}
			else if (*(*(maze + i) + j) == ROUTE){
				printf("  ");
			}
			else printf("国");
		}
		printf("\n");
	}
	printf("\n");
}
//随机生成迷宫的入口与出口,将结果赋予两个指针参数
void CreatInAndOut(int(*maze)[N], int*in, int*out) {
	int a, b;
	int flag_a = 0;
	int flag_b = 0;

	while (1){
		if (flag_a + flag_b == 2) {
			break;
		}

		//产生下标与迷宫最外层相符的随机数,可以排除下标为1和N-2的位置
		a = 2 + rand() % (N - 4);//随机产生 2 -- N-3 之间的数
		b = 2 + rand() % (N - 4);
		//由于传入的是指针,故无需返回值
		if (*(*(maze + a) + 2) == ROUTE && flag_a == 0) {//若条件成立,则使指针in指向入口下标a
			*in = a;
			*(*(maze + a) + 1) = ROUTE;
			flag_a = 1;
		}
		if (*(*(maze + b) + N - 3) == ROUTE && flag_b == 0) {//若条件成立,则使指针out指向入口下标b
			*out = b;
			*(*(maze + b) + N - 2) = ROUTE;
			flag_b = 1;
		}

	}
}
//复制迷宫,防止接下寻路的时候来迷宫被破坏(将maze1的数据拷贝到maze2中)
void CopyMaze(int(*maze1)[N], int(*maze2)[N]) {
	for (int i = 0; i < N; ++i){
		for (int j = 0; j < N; ++j){
			*(*(maze2 + i) + j) = *(*(maze1 + i) + j);
		}
	}
}
//进行迷宫游戏的函数
int Game(int *x, int *y, int(*maze)[N], int out, int direction){//这里要修改 x y 的值,故传入指针

	switch (direction){
	case 1://上移
		*(*(maze + *(x)) + *(y)) = ROUTE;
		*(*(maze + *(x)-1) + *(y)) = END;
		*x = *x - 1;
		break;
	case 2://下移
		*(*(maze + *(x)) + *(y)) = ROUTE;
		*(*(maze + *(x)+1) + *(y)) = END;
		*x = *x + 1;
		break;
	case 3://左移
		*(*(maze + *(x)) + *(y)) = ROUTE;
		*(*(maze + *(x)) + *(y)-1) = END;
		*y = *y - 1;
		break;
	case 4://右移
		*(*(maze + *(x)) + *(y)) = ROUTE;
		*(*(maze + *(x)) + *(y)+1) = END;
		*y = *y + 1;
		break;
	default:{
				printf("数据有误!请重新输入!");
				return 1;
		}	
	}
	if (*x == out&&*y == N - 2){
			return 0;
	}
	else{
		return 1;
	}
}
//传入位置与想要移动的方向,判断移动后位置在迷宫里是否为路,若是返回1否则返回0
int Decide(int x, int y, int direction, int(*maze)[N]){
		//direction的1,2,3,4,分别代表上下左右
		if (direction<1 || direction>4){
			printf("\n\t\t\t方向输入有误!");
			system("pause");
			printf("---------输入回车键继续....");
			return 0;
		}
		//判断在迷宫所在方向是不是路
		if (direction == 1){
			//迷宫中向上移动
			if (*(*(maze + x - 1) + y) == ROUTE){
				return 1;
			}
			else{
				return 0;
			}
		}
		else if (direction == 2){
			//迷宫中向下移动
			if (*(*(maze + x + 1) + y) == ROUTE){
				return 1;
			}
			else{
				return 0;
			}
		}
		else if (direction == 3){
			//迷宫中向左移动
			if (*(*(maze + x) + y - 1) == ROUTE){
				return 1;
			}
			else{
				return 0;
			}
		}
		else{
			//迷宫中向右移动
			if (*(*(maze + x) + y + 1) == ROUTE){
				return 1;
			}
			else{
				return 0;
			}
		}


	}
//主函数
int main(){

		printf("\n\t\t-------------------------------------------------------------------------------------------------------------------------------");
		printf("\n\t\t---------------------------声明:此程序在VS2013上编写,在该平台上使用 <.c> 与 <.cpp> 均能运行----------------------------------");
		printf("\n\t\t-------------------------------------------------------------------------------------------------------------------------------");

		while (1){
		
			printf("\n\n\n\n\n\t\t\t\t--------------------------------------------------------------------------\n");
			printf("\t\t\t\t--------------------------------------------------------------------------\n");
			printf("\t\t\t\t--------------------------------------------------------------------------\n");
			printf("\t\t\t\t||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n");
			printf("\t\t\t\t-------------------------     迷宫游戏      ------------------------------\n");
			printf("\t\t\t\t||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n");
			printf("\t\t\t\t--------------------------------------------------------------------------\n");

			printf("\t\t\t\t- 1 ---------------------     迷宫寻路      ----用栈进行迷宫寻路----------\n");
			printf("\t\t\t\t- 2 ---------------------     迷宫游玩      ----自己随便编的--------------\n");
			printf("\t\t\t\t- 0 ---------------------     退出游戏      ------------------------------\n");

			int a;
			printf("请选择:>");
			scanf("%d", &a);
			if (a == 0){
				printf("再会!!");
				return 0;
			}
			else if (a == 1){
				system("cls");
				int maze[N][N];
				int copyMaze[N][N];
				int in = 0;
				int out = 0;
				int *inp = &in;//该指针指向迷宫入口位置,即指向in
				int *outp = &out;//该指针指向迷宫出口位置,即指向out
				srand(time(NULL));

				//迷宫的创建与初始化,打印迷宫
				InitMaze(maze);
				CreatMaze(maze, 14, 14);//从maze[14][14]的位置开始创建迷宫
				CreatInAndOut(maze, inp, outp);//寻找迷宫的入口与出口,将其赋予in和out
				CopyMaze(maze, copyMaze);//将原迷宫复制到copyMaze中
				print(maze);

				printf("\t\t按回车键进行迷宫寻路------------");
				system("pause");
				system("cls");
				//用栈进行寻路,并打印出最终路线
				Stack*Top = InitStack(in, copyMaze);//返回的指针Top->next指向该栈的栈顶
				FindMaze(Top, copyMaze, out);
				Endprint(maze, Top);//打印函数
				system("pause");
			}
			else if (a == 2){
				//1.创建迷宫
				//2.写函数,函数参数应该包括:1.迷宫指定位置,2.迷宫出口位置,3.指向迷宫的指针,4.移动的方向
				//该函数应该对修改后的迷宫进行打印
				//该函数返回一个整数赋予flage,控制该游戏是否继续执行
				//3.不断运行该函数,直到游戏终止

				system("cls");
				int maze[N][N];
				int copyMaze[N][N];
				int in = 0;
				int out = 0;
				int *inp = &in;//该指针指向迷宫入口位置,即指向in
				int *outp = &out;//该指针指向迷宫出口位置,即指向out
				srand(time(NULL));

				//迷宫的创建与初始化,打印迷宫
				InitMaze(maze);
				CreatMaze(maze, 14, 14);//从maze[14][14]的位置开始创建迷宫
				CreatInAndOut(maze, inp, outp);//寻找迷宫的入口与出口,将其赋予in和out

				//以上是迷宫的创建
				//现在我们有了一个随机迷宫,迷宫的出口(out)与入口(in)坐标


				int direction;//控制移动方向
				int flage = 1;//控制游戏是否结束
				//将迷宫的入口位置存入x,y方便使用
				int x = in;
				int y = 1;
				maze[x][y] = END;
				//创建两个指针指向 x y 方便修改
				int *px = &x;
				int *py = &y;
				while (flage){
					system("cls");
					print(maze);
					printf("\n\n\n\t\t请输入想要移动的方向:>");
					printf("\n\t\t\t* 代表目前人物所在位置");
					printf("\n\t\t注:1,2,3,4分别代表上下左右,其它数字均为非法数字!");
					scanf("%d", &direction);
					//先进行位置判断,若要移动的方向在迷宫处显示为路,则移动,否则不移动
					//返回1,则证明方向合法且移动方向是路(可以移动)
					if (Decide(x, y, direction, maze) == 1){
						flage = Game(px, py, maze, out, direction);
					}
					print(maze);
					system("pause");
					printf("\n\t\t-------按回车键继续....");
				}
			}
			else{
				printf("输入数据有误!!");
			}
			system("cls");
		}
		return 0;
	}

ok,拜拜~~~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值