迷宫
一、简单迷宫
说明:
1. 0:墙 1:路 2:走过的路
2. 探索方向:左->上->右->下
3. 位置用数组下标来表示 (在这里我们初始位置设置为2,5)
4. 将走过的路入栈保存
5. 无路可走就回溯(出栈)
#pragma once
#include "stack.h"
#include <windows.h>
#define ROWS (6)
#define COLS (6)
//1可以走 0不可以走
int IsAccess(int maze[ROWS][COLS],Position pos)
{
//判断是否越界
if (pos.y < 0 || pos.y >= ROWS){
return 0;
}
if (pos.x < 0 || pos.x >= COLS){
return 0;
}
return maze[pos.y][pos.x] == 1 ? 1 : 0;
}
//1是 0不是
int IsExit(Position pos)
{
if (pos.x == COLS - 1)
{
return 1;
}
else{
return 0;
}
}
void PrintfMaze(int maze[ROWS][COLS])
{
int i, j;
for (i = 0; i < ROWS; i++)
{
for (j = 0; j < COLS; j++){
printf("%d ", maze[i][j]);
}
printf("\n");
}
}
void GoMaze(int maze[ROWS][COLS], Position entry)
{
Position pos = entry; //当前所在位置
Position nextPos; //要尝试的位置
Stack stack;
StackInit(&stack);
while (1)
{
maze[pos.y][pos.x] = 2;//表示来过
system("cls");
PrintfMaze(maze);
Sleep(500);
if (IsExit(pos)){
printf(" 你太聪明了~出口就是这儿~\n");
return;
}
//左->上->右->下
nextPos = pos;
nextPos.x -= 1;
if (IsAccess(maze,nextPos)){
StackPush(&stack, pos);
pos = nextPos;
continue;
}
nextPos = pos;
nextPos.y -= 1;
if (IsAccess(maze,nextPos)){
StackPush(&stack, pos);
pos = nextPos;
continue;
}
nextPos = pos;
nextPos.x += 1;
if (IsAccess(maze,nextPos)){
StackPush(&stack, pos);
pos = nextPos;
continue;
}
nextPos = pos;
nextPos.y += 1;
if (IsAccess(maze,nextPos)){
StackPush(&stack, pos);
pos = nextPos;
continue;
}
//回溯
pos = StackTop(&stack);
StackPop(&stack);
maze[pos.y][pos.x] = 3;
system("cls");
PrintfMaze(maze);
Sleep(500);
}
}
void TestMaze1()
{
int maze[ROWS][COLS] = {
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 0 },
{ 0, 0, 1, 0, 1, 1 },
{ 0, 0, 1, 0, 0, 0 },
};
Position enter = { 2, 5 };
GoMaze(maze, enter);
PrintfMaze(maze);
}
二、多通路迷宫(不带环)
和第一个不同的是:在找到第一个出口的时候不要直接退出,应该进行回溯出栈找出第二个..出口,
循环终止条件: 就是当栈为空时,我们就是已经将所有出口找到了。
回溯的条件有两个:一个是找到出口就回溯
一个是无路可走就回溯
void GoMaze(int maze[ROWS][COLS], Position entry)
{
Position pos = entry; //当前所在位置
Position nextPos; //要尝试的位置
Stack stack;
StackInit(&stack);
while (1)
{
maze[pos.y][pos.x] = 2;//表示来过
system("cls");
PrintfMaze(maze);
Sleep(500);
if (IsExit(pos)){
//回溯
pos = StackTop(&stack);
StackPop(&stack);
maze[pos.y][pos.x] = 3;
system("cls");
printf(" 小可爱~找到一个出口啦~\n");
PrintfMaze(maze);
Sleep(2000);
continue;
}
//左->上->右->下
nextPos = pos;
nextPos.x -= 1;
if (IsAccess(maze,nextPos)){
StackPush(&stack, pos);
pos = nextPos;
continue;
}
nextPos = pos;
nextPos.y -= 1;
if (IsAccess(maze,nextPos)){
StackPush(&stack, pos);
pos = nextPos;
continue;
}
nextPos = pos;
nextPos.x += 1;
if (IsAccess(maze,nextPos)){
StackPush(&stack, pos);
pos = nextPos;
continue;
}
nextPos = pos;
nextPos.y += 1;
if (IsAccess(maze,nextPos)){
StackPush(&stack, pos);
pos = nextPos;
continue;
}
//回溯
if (StackIsEmpty(&stack))
{
printf(" 小可爱~你的迷宫探索旅程结束啦~\n");
return;
}
pos = StackTop(&stack);
StackPop(&stack);
maze[pos.y][pos.x] = 3;
system("cls");
PrintfMaze(maze);
Sleep(500);
}
}
void TestMaze1()
{
int maze[ROWS][COLS] = {
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 1 },
{ 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 1 },
{ 0, 0, 1, 0, 0, 0 },
};
Position enter = { 2, 5 };
GoMaze(maze, enter);
PrintfMaze(maze);
}
三、多通路迷宫(带环)
这里我们采用了递归的方式
这里我们要注意:每次出来的时候要将走过的路在设置成1
void GoMazeRecursion(int maze[ROWS][COLS],Position pos)
{
maze[pos.y][pos.x] = 2;//表示来过
system("cls");
PrintfMaze(maze);
Sleep(300);
Position nextPos;
if (IsExit(pos)){
printf(" 小可爱~ 找到一个出口啦\n");
maze[pos.y][pos.x] = 1;
PrintfMaze(maze);
system("pause");
return;
}
nextPos = pos;
nextPos.x -= 1;
if (IsAccess(maze, nextPos)){
GoMazeRecursion(maze,nextPos);
}
nextPos = pos;
nextPos.y -= 1;
if (IsAccess(maze, nextPos)){
GoMazeRecursion(maze, nextPos);
}
nextPos = pos;
nextPos.x += 1;
if (IsAccess(maze, nextPos)){
GoMazeRecursion(maze, nextPos);
}
nextPos = pos;
nextPos.y += 1;
if (IsAccess(maze, nextPos)){
GoMazeRecursion(maze, nextPos);
}
maze[pos.y][pos.x] = 1;
}
void TestMaze1()
{
int maze[ROWS][COLS] = {
{ 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 0, 0 },
{ 0, 1, 0, 1, 0, 0 },
{ 0, 1, 0, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 1 },
{ 0, 1, 0, 0, 0, 0 },
};
Position enter = { 2, 5 };
GoMaze(maze, enter);
PrintfMaze(maze);
}
四、多通路带环迷宫的最短路径
就是将每走的一步都入栈,最后进行比较,短的就为最短路径
void GoMazeRecursion(Stack *pPath,Stack *pShort, int maze[ROWS][COLS],Position pos)
{
maze[pos.y][pos.x] = 2;//表示来过
StackPush(pPath, pos); //每走一步都入栈
system("cls");
PrintfMaze(maze);
Sleep(300);
Position nextPos;
if (IsExit(pos)){
printf(" 小可爱找到出口啦~\n");
maze[pos.y][pos.x] = 1;
StackPop(pPath);
if (StackIsEmpty(pShort) || StackSize(pPath )< StackSize(pShort)) //若最短路径栈为空
//或者path的路径比最短路径小那就更新最短路径
{
//找到新的最短路径
StackCopy(pShort, pPath);
}
PrintfMaze(maze);
system("pause");
return;
}
nextPos = pos;
nextPos.x -= 1;
if (IsAccess(maze, nextPos)){
GoMazeRecursion(pPath,pShort,maze, nextPos);
}
nextPos = pos;
nextPos.y -= 1;
if (IsAccess(maze, nextPos)){
GoMazeRecursion(pPath, pShort,maze, nextPos);
}
nextPos = pos;
nextPos.x += 1;
if (IsAccess(maze, nextPos)){
GoMazeRecursion(pPath, pShort,maze, nextPos);
}
nextPos = pos;
nextPos.y += 1;
if (IsAccess(maze, nextPos)){
GoMazeRecursion(pPath, pShort,maze, nextPos);
}
StackPop(pPath);//无路可走就出栈一次
maze[pos.y][pos.x] = 1;
}
void TestMaze1()
{
Stack pathStack;
Stack shortStack;
int maze[ROWS][COLS] = {
{ 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 0, 0 },
{ 0, 1, 0, 1, 0, 0 },
{ 0, 1, 0, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 1 },
{ 0, 1, 0, 0, 0, 0 },
};
Position enter = { 1, 5 };
StackInit(&pathStack); //初始化
StackInit(&shortStack);
GoMazeRecursion(&pathStack,&shortStack, maze, enter);
while (!StackIsEmpty(&shortStack)) {
Position pos = StackTop(&shortStack);
StackPop(&shortStack);
maze[pos.y][pos.x] = 4; //将最短路径用4表示
}
PrintfMaze(maze);
}
这是在里所用到的栈~
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef struct Position {
int x;
int y;
} Position;
typedef Position SDataType;
#define MAX_SIZE (100)
typedef struct Stack {
SDataType array[MAX_SIZE];
int top; // 含义和顺序表的 size 是一样
// 1. 表示有效数据个数
// 2. top 下标表示当前可用位置
} Stack;
void StackInit(Stack *pS)
{
assert(pS != NULL);
pS->top = 0;
}
void StackPush(Stack *pS, SDataType data)
{
assert(pS != NULL);
assert(pS->top < MAX_SIZE);
pS->array[pS->top++] = data;
}
void StackPop(Stack *pS)
{
assert(pS != NULL);
assert(pS->top > 0);
pS->top--;
}
SDataType StackTop(Stack *pS)
{
assert(pS != NULL);
assert(pS->top > 0);
return pS->array[pS->top - 1];
}
// 判断为空, 1 表示空,0 表示非空
int StackIsEmpty(Stack *pS)
{
return pS->top == 0 ? 1 : 0;
}
int StackSize(Stack *pS)
{
return pS->top;
}
void StackCopy(Stack *pDest, Stack *pSrc)
{
pDest->top = pSrc->top;
memcpy(pDest->array, pSrc->array, sizeof(SDataType)* pSrc->top);
}
void TestStack()
{
Stack stack;
StackInit(&stack);
}