迷宫算法以及图形化android显示

来源:互联网 发布:淘宝客服模板大小 编辑:程序博客网 时间:2024/05/24 03:03

迷宫算法确实很给人吸引力,但若是结合图形化的显示,相信形式化思维的你对此会感到顿时脑洞大开,在此希望大家进行评论或者提出意见

//每个迷宫位置的抽象

struct Items{
char post_x;//杭位置
char post_y;//列位置
char dir;//方向
};

//基于方向的偏移确定
struct offsets{
char x;//x偏移
char y;//y偏移
};

enum direction{N,NE,E,SE,S,SW,W,NW};//方向表示
struct offsets moves[8];//八个方向的偏移数组

//迷宫模拟,可找算法生成
char maze[MAZE_SIZE-1][MAZE_SIZE+2]={
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1},
{1,1,0,0,0,0,1,0,1,1,1,0,0,1,1,1,1},
{1,0,1,1,0,0,0,0,1,1,1,1,0,0,1,1,1},
{1,1,1,0,1,1,1,1,0,1,1,0,1,1,0,0,1},
{1,1,1,0,1,0,0,1,0,1,1,1,1,1,1,1,1},
{1,0,0,1,1,0,1,1,1,0,1,0,0,1,0,1,1},
{1,0,0,1,1,0,1,1,1,0,1,0,0,1,0,1,1},
{1,0,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1},
{1,0,0,1,1,0,1,1,0,1,1,1,1,1,0,1,1},
{1,1,1,0,0,0,1,1,0,1,1,0,0,0,0,0,1},
{1,0,0,1,1,1,1,1,0,0,0,1,1,1,1,0,1},
{1,0,1,0,0,1,1,1,1,1,0,1,1,1,1,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
};
//迷宫访问位置屏蔽位,默认为0,既没有访问过
char mark[MAZE_SIZE-1][MAZE_SIZE+2]={{0}
};


moves[0].x = -1;moves[0].y =  0;
void main()
{
printf("hello maze\n");



cout<<"init the direction vector"<<endl;

//基于方向偏移的初始化
moves[0].x = -1;moves[0].y =  0;
moves[1].x = -1;moves[1].y =  1;
moves[2].x =  0;moves[2].y =  1;
moves[3].x =  1;moves[3].y =  1;
moves[4].x =  1;moves[4].y =  0;
moves[5].x =  1;moves[5].y = -1;
moves[6].x =  0;moves[6].y = -1;
moves[7].x = -1;moves[7].y = -1;
/*

for(char i=0;i<=MAZE_SIZE+1;i++)
{
maze[0][i] = 1;
maze[MAZE_SIZE+1][i] = 1;
maze[i][0] = 1;
maze[i][MAZE_SIZE+1] = 1;
}
for(char i=0;i<=MAZE_SIZE+1;i++)
{
for(char j=0;j<=MAZE_SIZE+1;j++)
{
//cout<<maze[i][j]<<"  ";
printf("%d  ",maze[i][j]);
}
cout<<endl;
}
*/

//路径查询,参数为结束点的行与列位置
Path(12,15);
cout<<"the path is"<<endl;

//打印访问位置的数组,监视数组访问的路径
    for(char i=0;i<MAZE_SIZE-1;i++)
{
for(char j=0;j<=MAZE_SIZE+1;j++)
{
//cout<<maze[i][j]<<"  ";
printf("%d  ",mark[i][j]);
}
cout<<endl;
}
getchar();
}
void Path(const char m,const char p)
{

//我们规定初始位置为1,1
mark[1][1] = 1;
Stack<Items> stack;
Items temp={1,1,E};
stack.Push(temp);

//创建单元元素,入栈
while(!stack.isEmpty())
{
Items item = stack.Top();
stack.Pop();

//出栈获取当前位置的信息
char i = item.post_x;//x坐标
char j = item.post_y;//y坐标
char dir = item.dir;//方向
while(dir<8)
{
char newX = i +moves[dir].x;
char newY = j +moves[dir].y;

//根据方向向量获取下一步要探索的信息位置
if((newX == m)&&(newY == p))
{

//等于结束点,退出大函数
//success
cout<<i<<" "<<j<<endl;
cout<<m<<" "<<p<<endl;
return;
//exit
}
//position illegal?
if(!mark[newX][newY]&&!maze[newX][newY])
{

//位置合法

//将旧位置信息入栈,为此路不通打下基础,此刻方向信息应更新为下一个方向
mark[newX][newY] = 1;
Items item = {i,j,dir+1};
stack.Push(item);

//更新位置信息,以便进行下一步探索
i = newX;
j = newY;
dir = N;//新方向从0开始
}
else
{
dir++;
}
//yes change dir
//no push
}

}
cout<<"no path in the maze"<<endl;
}



为了进一步认识算法的执行过程,我写了一个android程序来模拟算法的执行过程,这样看起来比较直观、形象

如果大家对这个感兴趣,可以关注我或者评论,我将很乐意与大家分享心得体会

核心代码如下部分:主要是结合surfaceview来进行绘制

@Override
public void run() {
// TODO Auto-generated method stub
boolean firstPop = true;
boolean dirFinshed = false;
Items tempItems;
int i=0,j=0,dir=0;
while(!dirFinshed||threadF&&!stack.isEmpty())
{
long start = System.currentTimeMillis();
if (firstPop) {

//将上面C++语言的函数拆分成单逻辑循环调用

//因为是基于多线程的操作,将逻辑与绘图分开,如下面的函数所表达的

//等价与代码的第一次出栈
tempItems = stack.pop();
i = tempItems.getPos_x();
j = tempItems.getPos_y();
dir = tempItems.getDir();
firstPop = false;
}
Items temdir = logic2(i,j,dir,12,15);//执行一次逻辑函数,返回更新后的位置状态信息的变化
if(canDrawLine)
{
//draw

//基于一次变化的标志进行绘图操作

//包括方块的绘制,与线的绘制
myDraw(i, j, temdir.getPos_x(),temdir.getPos_y());
canDrawLine = false;
}

//更新位置函数,方便进一步路径的探索
i = temdir.getPos_x();
j = temdir.getPos_y();
dir = temdir.getDir();

if(temdir.getDir()>=8)
{

//方向越界,此路不通,弹出上一位位置信息
tempItems = stack.pop();
i = tempItems.getPos_x();
j = tempItems.getPos_y();
dir = tempItems.getDir();
dirFinshed = true;
}
long end = System.currentTimeMillis();
if(end-start<timeSpan )
{

//保持帧率同步
try {
Thread.currentThread().sleep(timeSpan-(end-start));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if(findPath)
{
handler.sendEmptyMessage(SUCCESS);
}
else {
handler.sendEmptyMessage(FAILED);
}
}

//逻辑函数和上面的没有什么太大的区别,只是进行拆分为可以单步执行的逻辑

//这样做的好处是分离绘制逻辑与业务逻辑

private Items logic2(int i,int j,int dir,int m,int p) {
// TODO Auto-generated method stub
int newX = i + moves[dir].getX_offset();
int newY = j + moves[dir].getY_offset();

if(newX == m&&newY==p)
{
//find
threadF = false;
findPath  = true;
//exit
}
//illegal
if((Constant.mark[newX][newY]!=1)&&(Constant.maze[newX][newY]!=1))
{
Constant.mark[newX][newY] = 1;
canDrawLine = true;
dir++;
Items temItems = new Items(i,j,dir);
stack.push(temItems);

i = newX;
j = newY;
dir = Directions.N;
}
else {
dir++;
}
tempItems = new Items(i,j,dir);
return tempItems;
}

基于篇幅就不一一列出,有兴趣可以留言或者@我




0 0
原创粉丝点击