递归迷宫求解问题

黑白键的奔腾 2011-05-02 07:43:09
问题描述:
在执行的过程过,i,j的值不断增大,于是不能实现原目的
执行文件图像:
问题三言两语难说清 这个是我生成文件,由于不知道怎么传图片,所以我手打出来如下:
1 1 1 1 1 1 1 1 1 1 1
1 0 0 1 1 1 0 1 0 0 1
1 0 0 0 0 0 1 1 1 1 1
1 1 0 0 1 1 0 0 1 1 1
1 0 1 1 0 0 0 1 1 0 1
1 0 1 0 0 0 0 0 0 0 1
1 1 1 0 0 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1 1
->(2,2)->(2,3)->(3,3)->(3,4)->(3,5)->(3,6)
Failed!
照这个迷宫,是有答案的 但是现在没有,麻烦各位看看,给点意见
问题代码如下

#include"stdio.h"
#include"stdlib.h"
#include"time.h"
const double PE=1.0/4; //设置比例 1所占的比例
#define m 6
#define n 9
int i=1,j=1;
const int M=8;//行数
const int N=8;//列数
struct num
{
int value;
int mark; //标志,是否走过
}maze[m+2][n+2],*p;
void Creat(struct num *p)//初始化迷宫,初始化所有标记均未走过,值为1
{
int i,pf=0;
int x=0,y=0;
for(i=0;i<=n;i++) //设置外围,全为1,不能通行
{
maze[0][i].value=1;
maze[0][i].mark=1;
}
for(i=1;i<=m+1;i++)
{
maze[i][0].value=1;
maze[i][0].mark=1;
}
for(i=1;i<=n+1;i++)
{
maze[m+1][i].value=1;
maze[m+1][i].mark=1;
}
for(i=0;i<=m;i++)
{
maze[i][n+1].value=1;
maze[i][n+1].mark=1;
}
srand(time(NULL));
for(x=1;x<m+1;x++) //随机产生
{
for(y=1;y<n+1;y++)
{
maze[x][y].value=rand()%2;
maze[x][y].mark=1;
}
}
maze[1][1].value=0;//入口
maze[m][n].value=0;//出口
}
void path(struct num *p,int i,int j)//求解过程
{
if(i<m+1&&j<n+1)//递归执行条件
{

if(maze[i][j+1].value==0&&maze[i][j+1].mark==1)//右方
{
maze[i][j+1].mark=0;
printf("->(%d,%d)",i+1,j+1);
if(i==m&&j==n)
{
printf("Success!");
exit(0);
}
path(p,i,j+1);
}
else if(maze[i+1][j].value==0&&maze[i+1][j].mark==1)//下方
{
maze[i+1][j].mark=0;
printf("->(%d,%d)",i+1,j+1);
if(i==m&&j==n)
{
printf("Success!");
exit(0);
}
path(p,i+1,j);
}
else if(maze[i][j-1].value==0&&maze[i][j-1].mark==1)//左方
{
maze[i][j-1].mark=0;
printf("->(%d,%d)",i+1,j+1);
if(i==m&&j==n)
{
printf("Success!");
exit(0);
}
path(p,i,j-1);
}
else if(maze[i-1][j].value==0&&maze[i-1][j].mark==1)//上方
{
maze[i-1][j].mark=0;
printf("->(%d,%d)",i+1,j+1);
if(i==m&&j==n)
{
printf("Success!");
exit(0);
}
path(p,i-1,j);
}
else if(maze[i-1][j-1].value==0&&maze[i-1][j-1].mark==1)//左上
{
maze[i-1][j-1].mark=0;
printf("->(%d,%d)",i+1,j+1);
if(i==m&&j==n)
{
printf("Success!");
exit(0);
}
path(p,i-1,j-1);
}
else if(maze[i-1][j+1].value==0&&maze[i-1][j-1].mark==1)//右上
{
maze[i-1][j+1].mark=0;
printf("->(%d,%d)",i+1,j+1);
if(i==m&&j==n)
{
printf("Success!");
exit(0);
}
path(p,i-1,j+1);
}
else if(maze[i+1][j+1].value==0&&maze[i+1][j+1].mark==1)//右下
{
maze[i+1][j+1].mark=0;
printf("->(%d,%d)",i+1,j+1);
if(i==m&&j==n)
{
printf("Success!");
exit(0);
}
path(p,i+1,j+1);
}
else if(maze[i+1][j-1].value==0&&maze[i+1][j-1].mark==1)//左下
{
maze[i+1][j-1].mark=0;
printf("->(%d,%d)",i+1,j+1);
if(i==m&&j==n)
{
printf("Success!");
exit(0);
}
path(p,i+1,j-1);
}
else
{

printf("\nFailed\n");
}
}
}
void main()
{
Creat(p);
for(int M=0;M<m+2;M++)
{
for(int N=0;N<n+2;N++)
{
printf("%d ",maze[M][N].value);
}
printf("\n");
}
path(p,i,j);
}
...全文
238 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
w5320 2011-05-03
  • 打赏
  • 举报
回复
回来了,把Java那个程序贴出来给你参考参考吧,你把KData那个类定义成一个结构体就行了:

import java.util.*;
import java.util.Scanner;


public class KnightTra {
/*标志点是否走过*/
private boolean IsTra[][]=new boolean[8][8];
/*储存路劲用的栈,储存的元素是一个坐标,在KData定义*/
private Stack<KData> TraWay=new Stack<KData>();
/*备用路径栈*/
Stack<KData> TraWayBU=new Stack<KData>();
/*指示标志,每走过一个点加1,当为64时,则已遍历*/
private int TraNo;

/*给出起始点初始化一个对象*/
KnightTra(KData kd){
/*检查起始点是否合法,不合法,退出程序*/
if(!CheckData(kd.x,kd.y)){
System.out.println("请给出一个棋盘上的点!");
System.exit(1);
}
/*初始化点指示标志,所有都标志为false,即都没走过*/
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
IsTra[i][j]=false;
/*走过起始点*/
IsTra[kd.x][kd.y]=true;
/*起始点入栈*/
TraWay.push(kd);
/*总共走过一个点*/
TraNo=1;

}

/*检查点是否在棋盘上*/
private boolean CheckData(int x,int y){
if(x<0||x>7||y<0||y>7)
return false;
else
return true;
}

/*把路径栈的数据复制到备用数据栈里面*/
private void BUData(){
Stack<KData> Temp=new Stack<KData>();
KData Ktemp;
/*把路径栈的数据转移到Temp*/
while(!TraWay.isEmpty()){
Ktemp=new KData(TraWay.pop());
Temp.push(Ktemp);
}
/*清空备用栈的数据*/
while(!TraWayBU.isEmpty())
TraWayBU.pop();
/*把数据放回原栈和备用栈*/
while(!Temp.isEmpty()){
Ktemp=new KData(Temp.pop());
TraWay.push(Ktemp);
TraWayBU.push(Ktemp);
}
}

/*检查一个点kd的一个方向(用x和y表示八个方向)上的一个点是否走过
* 若没有,则把改点入栈,并标志改点。
*/
private boolean FP(KData kd,int x,int y){
/*检查这个方向是否还可以走*/
if(this.CheckData(kd.x+x, kd.y+y)&&IsTra[kd.x+x][kd.y+y]==false){
IsTra[kd.x+x][kd.y+y]=true;
TraWay.push(new KData(kd.x+x,kd.y+y));
TraNo++;
return true;
}
else
return false;
}

/*从路径栈取出一点,检查它的四周是否有可走的点,有则返回真,没有则返回假*/
private boolean FindPoint(){
KData kd=new KData(TraWay.pop());
/*取出点要回栈*/
TraWay.push(kd);;

/*分别检查八个方向是否可走*/
if(FP(kd,1,2))
return true;

else if(FP(kd,2,1))
return true;

else if(FP(kd,2,-1))
return true;

else if(FP(kd,1,-2))
return true;

else if(FP(kd,-1,-2))
return true;

else if(FP(kd,-2,-1))
return true;

else if(FP(kd,-2,1))
return true;

else if(FP(kd,-1,2))
return true;
else
return false;
}

/*检查一个点的四周是否有可走的点,有则返回真,没有则返回假*/
private boolean FindPoint(KData kd){
if(FP(kd,1,2))
return true;

else if(FP(kd,2,1))
return true;

else if(FP(kd,2,-1))
return true;

else if(FP(kd,1,-2))
return true;

else if(FP(kd,-1,-2))
return true;

else if(FP(kd,-2,-1))
return true;

else if(FP(kd,-2,1))
return true;

else if(FP(kd,-1,2))
return true;

else
return false;
}

public void FindWay(){
KData kd;
/*如果没有走够个点,就一直循环*/
while(this.TraNo<64){
/*检查路径栈最后一个点的四周是否有可走的点*/
while(!this.FindPoint()){
/*路径栈最后一个点的四周找不到可走的点,把数据复制到备用栈*/
this.BUData();
/*在备用栈取出一个点,检查其四周是否有可以走的点,其实就是后退一步找可以走的点*/
kd=new KData(TraWayBU.pop());
/*检查后退一步的点是否有可走的点,没有且没走够个点,继续后退*/
while(!this.FindPoint(kd)&&this.TraNo<64){
kd=new KData(TraWayBU.pop());
/*后退的点也是路径的一部分*/
TraWay.push(kd);
}
if(this.TraNo==64)
break;
}
}

}

/*打印路径*/
public void PrintWay(){
int i=1;
KData Ktemp;
Stack<KData> Temp=new Stack<KData>();

/*因为栈是先进后出的,所以要倒置一下先*/
while(!TraWay.isEmpty()){
Ktemp=new KData(TraWay.pop());
Temp.push(Ktemp);
}

while(!Temp.isEmpty()){
Ktemp=new KData(Temp.pop());
/*打印时不破坏路径栈*/
TraWay.push(Ktemp);
System.out.print("("+Ktemp.x+","+Ktemp.y+")-->");
/*格式控制,每5个点一行*/
i++;
if(i%5==0)
System.out.println();
}
System.out.println("游完了!");

}

public static void main(String args[]){
/*让用户自己输入起始点*/
int x,y;
Scanner reader=new Scanner(System.in);
System.out.println("请输入起始点的横坐标(在0和7之间):");
x=reader.nextInt();
System.out.println("请输入起始点的纵坐标(在0和7之间):");
y=reader.nextInt();
KnightTra kt=new KnightTra(new KData(x,y));
/*找路径和打印路劲*/
kt.FindWay();
System.out.println("其中一条路径如下:");
kt.PrintWay();

}

}//KnightTra Class


/*路径点的数据结构*/
class KData{
int x;
int y;

/*用坐标构建一个点*/
KData(int x,int y){
this.x=x;
this.y=y;
}

/*用已有对象构建一个点*/
KData(KData kd){
this.x=kd.x;
this.y=kd.y;
}

}


程序的算法有点不同,这里是要给出一个任意的点遍历一个8*8的棋盘,也会退,但是不把退得那点Pop出来。这里有检查越界,也有八个方向(虽然是走日字的)。
w5320 2011-05-03
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 happyst1990 的回复:]

我的错误,四周都是1,关于这个问题我偷懒了,我不想去检测在移动的过程中是否越界之类的问题。。 而且我想过用栈,但是假设是maze[X][y].value入栈以后,我就不知道该如何下手了,我不知道完成以后怎么找出栈里边存储的值是哪个坐标上的。。
[/Quote]这不是你懒的问题,迷宫本来就是有围墙的。用栈的话,你可以定义多一个点的结构体,将坐标入栈得了。或者像我一样定义迷宫的数据结构。你这种结构加个点结构行了,我试过你这种结构,也是用栈,不过是骑士游历,和迷宫有点像,不过是java做的……要就留下邮箱……
黑白键的奔腾 2011-05-03
  • 打赏
  • 举报
回复
我的错误,四周都是1,关于这个问题我偷懒了,我不想去检测在移动的过程中是否越界之类的问题。。 而且我想过用栈,但是假设是maze[X][y].value入栈以后,我就不知道该如何下手了,我不知道完成以后怎么找出栈里边存储的值是哪个坐标上的。。
黑白键的奔腾 2011-05-03
  • 打赏
  • 举报
回复
谢了 我会仔细看的。。。
w5320 2011-05-02
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 lhylhy 的回复:]
四周都是1,怎么会有出路?
[/Quote]
2楼没看懂,出口被1包围着,关键是算法错了...
w5320 2011-05-02
  • 打赏
  • 举报
回复
else if(maze[i-1][j-1].value==0&&maze[i-1][j-1].mark==1)//左上
{
maze[i-1][j-1].mark=0;
printf("->(%d,%d)",i+1,j+1);
if(i==m&&j==n)
{
printf("Success!");
exit(0);
}
path(p,i-1,j-1);
}
else if(maze[i-1][j+1].value==0&&maze[i-1][j-1].mark==1)//右上

这里是无关算法的复制代码出错...........
李亚超 2011-05-02
  • 打赏
  • 举报
回复
不论按个位置,先走步,后判断是否合法
lhy 2011-05-02
  • 打赏
  • 举报
回复
四周都是1,怎么会有出路?
w5320 2011-05-02
  • 打赏
  • 举报
回复
很多错误啊,LZ........
1. 上下左右分不清,按楼主的代码看应该是“上右下左.......”。
2. 其实楼主有没有发现.....指针p根本没有啊..........
3. 迷宫要用栈实现的,走到死胡同,要后退的。楼主根本没有后退,找到一步走一步,走到死胡同当然走不下去啦。建议去看看我的博客,几天刚把迷宫发上去。不过我不斜走.....

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧