迷宫算法以及图形化android显示
2015-10-13 10:00
627 查看
迷宫算法确实很给人吸引力,但若是结合图形化的显示,相信形式化思维的你对此会感到顿时脑洞大开,在此希望大家进行评论或者提出意见
//每个迷宫位置的抽象
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;
}
![](https://img-blog.csdn.net/20151013125324216?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
为了进一步认识算法的执行过程,我写了一个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;
}
基于篇幅就不一一列出,有兴趣可以留言或者@我
![](https://img-blog.csdn.net/20151013130951461?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
//每个迷宫位置的抽象
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;
}
基于篇幅就不一一列出,有兴趣可以留言或者@我
相关文章推荐
- Android性能专项测试之GPU Monitor
- Android性能专项测试之Network monitor
- Android性能专项测试之Memory Monitor工具
- Android性能专项测试之Systrace工具
- Android sdk content loader 0%的解决方法
- 给 Android 开发者的 RxJava 详解
- 给 Android 开发者的 RxJava 详解
- Android Studio常见问题总结
- android studio 占用太多内存
- Android小知识——xml、shape知识点记录1
- Android SwipeRefreshLayout
- Android 最火的快速开发框架XUtils
- Android获取通话记录
- android 自定义RatingBar的样式
- Android 之 2048 的游戏逻辑分析
- 设计模式之观察者模式
- Android轻量缓存框架--ASimpleCache
- Android开发总结笔记 Spinner(列表选项框) 1-1-15
- Android版手机斗地主游戏源码
- Android版手机斗地主游戏源码