zoukankan      html  css  js  c++  java
  • Bug迷宫(栈、回溯、DFS)

    编制一个求解迷宫通路的图形界面演示程序。
    问题描述:
    1) 输入一个任意大小的迷宫,任设起点、终点、障碍,用栈求出一条走出迷宫的路径,并显示在屏幕上。
    2) 根据用户界面提示,用键盘输入。Home 键设置迷宫起点,End 键设终点,上下左右箭头键移动,Enter 键添加墙,Del 键删除墙,完成后按 F9键演示,Esc 键退出。
    3)橙色的实心小圆圈表示起点,绿色实心圆圈表示终点,空心圆圈表示足迹,红色方块表示墙。
    4)本程序只求出一条成功的通路,但若对求解函数 MazePath 稍加更改即可求得全部路径。此外,因受图形界面限制,不能保存或载入测试文件(此功能可在 Maze_text 中实现)。
    5)当未输入起点时,消息显示“Error: You must set Startplace.”;
    未输入终点时,显示“Error: You must set Endplace.” 找到路径时,
    屏幕显示足迹,并在消息框出现 Path found,否则消去足迹,显示 Path not found.

    #include<stdio.h>
    #include<malloc.h>
    #include <conio.h>
    #include<time.h>
    #include<Windows.h>
    #include <graphics.h>
    #define size 15
    
    typedef struct {
    	int i;
    	int j;
    	int di;
    }Box;
    
    void mazepath();
    void drawload(Box* st,int top);
    void mademap();
    void create();
    void keyboard();
    void draw_s();
    void del();
    void enter();
    void home();
    void end();
    void f9();
    void init_map();
    void close();
    void error();
    void help();
    void P(int* n);
    
    int w, h, x, y, homenum, endnum,flag_x=0;
    int** map;
    
    int main(){
    	mademap();
    
    	while (1) {
    		keyboard();
    		if (homenum == 1 && endnum == 1)
    			mazepath();
    		if (homenum == 0) {
    			MessageBoxA(GetForegroundWindow(), TEXT("Error: You must set Startplace."), TEXT("错误!"), MB_OK);
    		}
    		if(endnum==0)
    			MessageBoxA(GetForegroundWindow(), TEXT("Error: You must set Endplace."), TEXT("错误!"), MB_OK);
    		for (size_t i = 0; i < h; i++)
    			for (size_t j = 0; j < w; j++)
    				if (map[i][j] == -1)
    					map[i][j] = 0;
    	}
    }
    
    void keyboard() {
    	static char ch = 0;
    
    	while (1)
    	{
    		draw_s();
    		while (!kbhit());
    		ch = _getch();
    		if (ch == -32) {
    			ch = _getch();
    			switch (ch)
    			{
    			case 77:ch = 'd'; break;
    			case 75:ch = 'a'; break;
    			case 80:ch = 's'; break;
    			case 72:ch = 'w'; break;
    			default:
    				break;
    			}
    		}
    		if (ch == 'd' || ch == 'D') {
    			if (x + 3 > w) {
    				x = 1;
    				continue;
    			}
    			x += 1;
    		}
    		if (ch == 'a' || ch == 'A') {
    			if (x - 2 <= -1) {
    				x = w - 2;
    				continue;
    			}
    			x -= 1;
    		}
    		if (ch == 's' || ch == 'S') {
    			if (y + 3 > h) {
    				y = 1;
    				continue;
    			}
    			y += 1;
    		}
    		if (ch == 'w' || ch == 'W') {
    			if (y - 2 <= -1) {
    				y = h - 2;
    				continue;
    			}
    			y -= 1;
    		}
    		if (ch == 'x' || ch == 'X') {
    			flag_x = (flag_x + 1) % 2;
    			MessageBoxA(GetForegroundWindow(), TEXT("模式已更改"), TEXT("提示"), MB_OK);
    		}
    		if (ch == 'H' || ch == 'h')
    			help();
    		if (ch == 71)
    			home();
    		if (ch == 79)
    			end();
    		if (ch == 13)
    			enter();
    		if (ch == 8)
    			del();
    		if (ch == 59)
    			init_map();
    		if (ch == 'u' || ch == 'U')
    			create();
    		if (ch == 67) {
    			f9();
    			return;
    		}
    		if (ch == VK_ESCAPE)
    			exit(0);
    	}
    }
    
    void mademap() {
    	double n;
    
    	system("mode con cols=25 lines=5");
    	help();
    	printf("请输入你要生成的迷宫大小
    (需要算上迷宫周围墙体)
    ");
    	while (1) {
    		printf("宽:");
    		scanf("%lf", &n);
    		w = (int)n;
    		if (w > 4 && w == n)
    		{
    			break;
    		}
    		error();
    	}
    	while (1) {
    		printf("高:");
    		scanf("%lf", &n);
    		h = (int)n;
    		if (h > 4 && h == n)
    		{
    			break;
    		}
    		error();
    	}
    	map = (int**)malloc(sizeof(int*) * h);
    	if (map == NULL) {
    		MessageBoxA(GetForegroundWindow(), TEXT("内存不足!"), TEXT("错误!"), MB_OK);
    		exit(0);
    	}
    	for (size_t i = 0; i < h; i++) {
    		map[i] = (int*)malloc(sizeof(int) * w);
    		if (map[i] == NULL) {
    			MessageBoxA(GetForegroundWindow(), TEXT("内存不足!"), TEXT("错误!"), MB_OK);
    			exit(0);
    		}
    	}
    
    	init_map();
    	x = y = 1;
    }
    
    void del() {
    	map[y][x] = 0;
    }
    
    void enter() {
    	map[y][x] = 1;
    }
    
    void home() {
    	for (size_t i = 0; i < h; i++)
    		for (size_t j = 0; j < w; j++)
    			if (map[i][j] == 8)
    				map[i][j] = 0;
    
    	map[y][x] = 8;
    }
    
    void end() {
    	for (size_t i = 0; i < h; i++)
    		for (size_t j = 0; j < w; j++)
    			if (map[i][j] == -8)
    				map[i][j] = 0;
    
    	map[y][x] = -8;
    }
    
    void f9(){
    	homenum = endnum = 0;
    	for (size_t i = 0; i < h; i++)
    		for (size_t j = 0; j < w; j++) {
    			if (map[i][j] == 8)
    				homenum++;
    			if (map[i][j] == -8)
    				endnum++;
    		}
    }
    
    void draw_s() {
    	static int flag = 0;
    
    	if (flag == 0) {
    		initgraph(w * size + 1, h * size + 1 + 30);
    		settextcolor(WHITE);
    		settextstyle(13, 0, _T("宋体"));
    		outtextxy(0, h * size + 3, "找到路径(条):");
    		flag = 1;
    	}
    
    	for (size_t i = 0; i < h; i++)
    		for (size_t j = 0; j < w; j++)
    		{
    			if (x == j && y == i) {
    				setfillcolor(YELLOW);
    				fillrectangle(j * size, i * size, (j + 1) * size, (i + 1) * size);
    				continue;
    			}
    			if (map[i][j] == 0) {
    				clearrectangle(j * size, i * size, (j + 1) * size, (i + 1) * size);
    			}
    			if (map[i][j] == 1) {
    				setfillcolor(RED);
    				fillrectangle(j * size, i * size, (j + 1) * size, (i + 1) * size);
    			}
    			if (map[i][j] == 8) {
    				setfillcolor(0x0099FF);
    				fillcircle(j * size + (size / 2), i * size + (size / 2), size / 2);
    			}
    			if (map[i][j] == -8) {
    				setfillcolor(GREEN);
    				fillcircle(j * size + (size / 2), i * size + (size / 2), size / 2);
    			}
    		}
    }
    
    void init_map() {
    	for (size_t i = 0; i < h; i++)
    		for (size_t j = 0; j < w; j++) {
    			map[i][j] = 0;
    			if (i == 0 || j == 0||i==h-1||j==w-1) {
    				map[i][j] = 1;
    			}
    		}
    }
    
    void close() {
    	closegraph();
    	for (size_t i = 0; i < h; i++)
    		free(map[i]);
    	free(map);
    	exit(0);
    }
    
    void error() {
    	MessageBoxA(GetForegroundWindow(), TEXT("请规范输入!"), TEXT("错误!"), MB_OK);
    }
    
    void help() {
    	MessageBoxA(GetForegroundWindow(), TEXT("F1重置地图 F9开始寻路 ESC退出程序 Enter设置墙 Delete删除墙 P中止寻路
    X改变寻路模式 Home设置启点 End设置终点 U生成随机地图 H帮助 方向键控制移动"), TEXT("帮助"), MB_OK);
    }
    
    void mazepath(){
    	FILE* f = NULL;
    	Box* st = NULL, * shortload = NULL;
    	int i = 0, j = 0, di = 0, i1 = 0, j1 = 0, top = -1, xe = 0, ye = 0, shorttop = -1, flag_h = 0;
    	long long int x = 0;
    	bool find = 0;
    	char s[10] = { NULL };
    	st = (Box*)malloc(sizeof(Box) * w * h);
    	if (st==NULL)
    	{
    		MessageBoxA(GetForegroundWindow(), TEXT("内存不足!"), TEXT("错误!"), MB_OK);
    		close();
    	}
    	if (flag_x==1)
    	{ 
    		f = fopen("maze_text.txt","w");
    		if (f == NULL) {
    			MessageBoxA(GetForegroundWindow(), TEXT("创建文件失败!"), TEXT("错误!"), MB_OK);
    			free(st);
    			close();
    		}
    		shortload= (Box*)malloc(sizeof(Box) * w * h);
    		if (shortload == NULL)
    		{
    			MessageBoxA(GetForegroundWindow(), TEXT("内存不足!"), TEXT("错误!"), MB_OK);
    			free(st);
    			fclose(f);
    			close();
    		}
    	}
    
    	for (size_t i2 = 0; i2 < h; i2++)
    		for (size_t j2 = 0; j2 < w; j2++) {
    			if (map[i2][j2] == 8) {
    				top++;
    				st[top].i = j2; st[top].j = i2; st[top].di = -1;
    			}
    			if (map[i2][j2] == -8) {
    				xe = j2; ye = i2;
    			}
    		}
    	
    	HANDLE handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)P,&flag_h, 0, 0);flag_h = 1;
    
    		while (top != -1) {
    			i = st[top].i; j = st[top].j; di = st[top].di;
    			if (i == xe && j == ye) {
    				if (flag_x == 0) {
    					x++;
    					sprintf(s, "%d", x);
    					outtextxy(83, h * size + 3, s);
    
    					flag_h = 0;
    					CloseHandle(handle);
    					MessageBoxA(GetForegroundWindow(), TEXT("Path found"), TEXT("提示!"), MB_OK);
    					drawload(st, top);
    					free(st);
    					return;
    				}
    				else {
    					fprintf(f, "路径:");
    					for (size_t n = 0; n <= top; n++)
    						fprintf(f, "(%d,%d)", st[n].i, st[n].j);
    					fprintf(f, "
    ");
    
    					if (x == 0)
    						shorttop = top;
    
    					x++;
    					sprintf(s, "%d", x);
    					outtextxy(83, h * size + 3, s);
    
    					if (top <= shorttop) 
    						for (size_t n = 0; n <= top; n++) {
    							shortload[n].i = st[n].i; shortload[n].j = st[n].j; shortload[n].di = st[n].di;
    							shorttop = top;
    						}
    
    					top--;
    					map[st[top].j][st[top].i] = -1;
    					i = st[top].i; j = st[top].j; di = st[top].di; i1 = j1 = 0;
    					find = 0;
    				}
    			}
    			else
    				find = 0;
    			while (di < 4 && !find) {
    				di++;
    				switch (di) {
    				case 0:i1 = i - 1; j1 = j; break;
    				case 1:i1 = i; j1 = j + 1; break;
    				case 2:i1 = i + 1; j1 = j; break;
    				case 3:i1 = i; j1 = j - 1; break;
    				}
    				if (map[j1][i1] == 0 || map[j1][i1] == -8)find = 1;
    			}
    			if (find) {
    				st[top].di = di;
    				top++;
    				st[top].i = i1; st[top].j = j1; st[top].di = -1;
    				if (map[st[top].j][st[top].i] != 8 && map[st[top].j][st[top].i] != -8)map[j1][i1] = -1;
    			}
    			else {
    				if (map[st[top].j][st[top].i] == 8) top--;
    				else {
    					map[st[top].j][st[top].i] = 0;
    					top--;
    				}
    			}
    			if (flag_h == 0)
    				break;
    		}
    
    		flag_h = 0;
    		free(st);
    		CloseHandle(handle);
    		if (flag_x == 0)
    			MessageBoxA(GetForegroundWindow(), TEXT("Path not found"), TEXT("提示!"), MB_OK);
    		else {
    			fprintf(f, "共%d条路",x);
    			fclose(f);
    			MessageBoxA(GetForegroundWindow(), TEXT("所有路径添加到maze_text"), TEXT("提示!"), MB_OK);
    			MessageBoxA(GetForegroundWindow(), TEXT("即将输出已知最短路径,若无路径将不输出"), TEXT("提示!"), MB_OK);
    			if (x > 0)
    				drawload(shortload, shorttop);
    			free(shortload);
    		}
    }
    
    void create() {
    	init_map();
    	srand(time(NULL));
    	for (size_t i = 1; i < h - 1; i++) 
    		for (size_t j = 1; j < w - 1; j++) {
    			map[i][j] = rand() % 2;
    			if (rand() % 2 == 1)
    				j++;
    		}
    }
    
    void P(int *x) {
    	int i = 4;
    	char ch = 0;
    
    	outtextxy(0, h * size + 17, "正在寻路");
    	setfillcolor(BLUE);
    	while (*x!=0) {
    		if (kbhit()) {
    			ch = getch();
    			if (ch == 'p' || ch == 'P') {
    				*x = 0;
    				MessageBoxA(GetForegroundWindow(), TEXT("寻路中止"), TEXT("提示"), MB_OK);
    			}
    		}
    		fillrectangle(i * size, h * size + 20, (i + 1) * size + 2, h * size + 25);
    		Sleep(300);
    		if (i > w - 3) {
    			clearrectangle(4 * size - 1, h * size + 19, w * size , h * size + 26);
    			i = 3;
    		}
    		i++;
    	}
    	clearrectangle(4 * size - 1, h * size + 19, w * size, h * size + 26);
    	outtextxy(0, h * size + 17, "完成寻路");
    }
    
    void drawload(Box *st,int top) {
    	clearrectangle(x * size, y * size, (x + 1) * size, (y + 1) * size);
    	if (map[y][x]==1)
    	{
    		setfillcolor(RED);
    		fillrectangle(x * size, y * size, (x + 1) * size, (y + 1) * size);
    	}
    	if (map[y][x] == 8) {
    		setfillcolor(0x0099FF);
    		fillcircle(x * size + (size / 2), y * size + (size / 2), size / 2);
    	}
    	if (map[y][x] == -8) {
    		setfillcolor(GREEN);
    		fillcircle(x * size + (size / 2), y * size + (size / 2), size / 2);
    	}
    
    	int i = 1;
    	while (1) {
    		circle(st[i].i * size + (size / 2), st[i].j * size + (size / 2), size / 2);
    		if (i == top)
    			break;
    		i++;
    		Sleep(100);
    	}
    	while (!kbhit());
    	draw_s();
    }
    

    ps:画图机制可改进

  • 相关阅读:
    B. Pasha and Phone
    GCD(关于容斥原理)
    二分乘法
    Lucky7(容斥原理)
    E. Devu and Flowers
    最大公约数最小公倍数
    leetcode每日刷题计划--day55
    Titanic--kaggle竞赛入门-生存预测
    做题记录--day54
    机器学习上机作业1记录 && 相关知识点复习
  • 原文地址:https://www.cnblogs.com/yisicanmeng/p/14179216.html
Copyright © 2011-2022 走看看