最近这一周在自学python,基本语法学的差不多,面向对象学完了,发现真的是节省时间和精力,遂打算用python将c++版本的Astar寻路代码重写一遍,代码量相比于c++确实有了大幅度降低,现在写的这个版本基本上还只是python的外壳,过程还是c,但是代码量已经有了很大的降低,比如python 中最好的就是for的遍历功能。
-------时间线20180325----------------------------
注意:以下贴的代码只是伪代码,可运行版在第二版中贴出
-------时间线20180325----------------------------
如下面的代码:
实际上用python: if CurrentNeibors in Openlist:这一句就完美解决了,它会自动的去openlist中遍历去找是否有CurrentNeibors这个量。
我发现python 的列表功能太强大了,根本就不用再去定义类
就 item = [[0,0],0,0,0,fileLine[j]]这一句代码就顶上了对棋盘类CHESS_BOARD_UNIT的定义
struct CHESS_BOARD_UNIT
{
PARENT_POSITION ParentPosition;
int g_value;
int h_value;
int f_value;
char flag;//标识此单元是:2起点/3终点/1障碍物/0通路
};
好处实在太多,现在还只是学了皮毛,如果深入学一些其他更复杂的函数,代码量应该会更短!
代码粘贴如下(还得继续调试):
#coding=utf-8
#定义棋盘、起点、终点、障碍物
#约定:棋盘外框都视为障碍物
########b###########
########b###########
##s#####b###########
########b########e##
########b###########
########b###########
######b#b###########
######b#bbbbbb######
######b######b######
#########b###b######
#########b###b######
#########b###b#bbb##
#########b##########
####################
####################
####################
####################
####################
####################
####################
chess_size = 20
FILE_STORAGE_WAY = 'd:\\AstarFindWay.txt' #随机数据文件存放路径
Start_x = 0
Start_y = 0
End_x = 0
End_y = 0
OpenListPosition = 0 #指针标记open列表数组当前存放元素个数(position总指向最后一个元素的后一位置)
CloseListPosition = 0 #指针标记Close列表数组当前存放元素个数(position总指向最后一个元素的后一位置)
OpenList = []#open列表(定义成数组形式)
CloseList = []#close列表
def openListIncraseSort():
flag = 0
i = 0
#for (int i = 0; i < OpenListPosition; i++)//冒泡法由大到小排序
while i < OpenListPosition:
#for (int j = 0; j < OpenListPosition - i; j++)
j = 0
while j19 or CurrentNeibors[i][0] < 0 or CurrentNeibors[i][1]>19:
continue #结束判断
'''
#障碍物点
elif 'b' == chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][4]:#flags
if i == 0:
ObstacleEast = 1 #标识当前点东边有障碍物
elif i == 2:
ObstacleSouth = 1 #标识当前点南边有障碍物
elif i == 4:
ObstacleWest = 1 #标识当前点西边有障碍物
elif i == 6:
ObstacleNorth = 1 #标识当前点北边有障碍物
else:
#continue#结束判断
'''
#将该临近点与closelist中的点逐个比较
elif CurrentNeibors[i] in CloseList[j]:#python牛逼!
#continue#结束判断
'''
#将该临近点与openlist中的点逐个比较
elif CurrentNeibors[i] in OpenList[j]:#python牛逼!
if chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] < chessboard[CurrentUnit[0]][CurrentUnit[1]][1] + currenToNeibor:
else#若该临近点的g值大于从起点经由当前结点到该临近结点的g值,将该临近结点的父指针指向当前结点,并更改该临近结点的g值,f值
#将该临近结点的父指针指向当前结点
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][0][0] = CurrentUnit[0]#[0][0]parent.x
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][0][1] = CurrentUnit[1]#[0][1]parent.y
#更改该临近结点的g值,f值
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] = chessboard[CurrentUnit[0]][CurrentUnit[1]][1] + currenToNeibor#g_value+currenToNeibor
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3] = chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] + chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][2]#[1]g[2]h[3]f
#continue #若该临近点的g值小于从起点经由当前结点到该临近结点的g值,不做任何操作
#可作为通路点
elif '#' == chessboard[CurrentNeibors[i].ChessUnit_x][CurrentNeibors[i].ChessUnit_y][4]:
#将邻居结点的指针指向当前结点
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][0][0] = CurrentUnit[0]#[0][0]parent.x
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][0][1] = CurrentUnit[1]#[0][1]parent.y
#计算该临近结点的g值,h值(曼哈顿距离),f值
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] = chessboard[CurrentUnit[0]][CurrentUnit[1]][1] + currenToNeibor
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][2] = 10 * (abs(CurrentNeibors[i][0] - End_x) + abs(CurrentNeibors[i][1] - End_y))
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3] = chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] + chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][2]
#将该临近点存入openlist中
OpenList[OpenListPosition][0] = CurrentNeibors[i][0]
OpenList[OpenListPosition][1] = CurrentNeibors[i][1]
OpenList[OpenListPosition][2] = chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3]#f_value
OpenListPosition+=1
else:
i+=2#循环变量增加2
#if
#while
#对当前方格东南、西南、西北、东北四个方向的临近方格依次检测
i = 1
while i<8:
#当前中间结点到邻近结点的距离。约定:东南西北四个方向距离为10,四个斜方向距离为14
if i%2 == 0:
currenToNeibor = 10
else:
currenToNeibor = 14
if 1 == ObstacleEast and (1 == i or 7 == i): #若东方格是障碍物,则东南、东北都不能通行
continue
if 1 == ObstacleSouth and (1 == i or 3 == i): #若南方格是障碍物,则东南、西南都不能通行
continue
if 1 == ObstacleWest and (3 == i or 5 == i): #若西方格是障碍物,则西南、西北都不能通行
continue
if 1 == ObstacleNorth and (5 == i or 7 == i): #若北方格是障碍物,则西北、东北都不能通行
continue
#终点
if 'e' == chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][4]:#flag
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][0][0] = CurrentUnit[0]#[0][0]parent.x
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][0][1] = CurrentUnit[1]#[0][1]parent.y
return 1
#break;//找到终点,结束循环
'''
#超出边界点
elif CurrentNeibors[i][0] < 0 or CurrentNeibors[i][1]>19 or CurrentNeibors[i][0] < 0 or CurrentNeibors[i][1]>19:
#continue #结束判断
#障碍物点
elif 'b' == chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][4]:#flag
#continue#结束判断
#将该临近点与closelist中的点逐个比较
elif CurrentNeibors[i] in CloseList[j]:#python牛逼!
#continue#结束判断
'''
#将该临近点与openlist中的点逐个比较
elif CurrentNeibors[i] in OpenList[j]:#python牛逼!
if chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] < chessboard[CurrentUnit[0]][CurrentUnit[1]][1] + currenToNeibor:
else#若该临近点的g值大于从起点经由当前结点到该临近结点的g值,将该临近结点的父指针指向当前结点,并更改该临近结点的g值,f值
#将该临近结点的父指针指向当前结点
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][0][0] = CurrentUnit[0]#[0][0]parent.x
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][0][1] = CurrentUnit[1]#[0][1]parent.y
#更改该临近结点的g值,f值
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] = chessboard[CurrentUnit[0]][CurrentUnit[1]][1] + currenToNeibor#g_value+currenToNeibor
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3] = chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] + chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][2]#[1]g[2]h[3]f
#continue #若该临近点的g值小于从起点经由当前结点到该临近结点的g值,不做任何操作
#可作为通路点
elif '#' == chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][4]:#flag
#将邻居结点的指针指向当前结点
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][0][0] = CurrentUnit[0]#[0][0]parent.x
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][0][1] = CurrentUnit[1]#[0][1]parent.y
#计算该临近结点的g值,h值(曼哈顿距离),f值
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] = chessboard[CurrentUnit[0]][CurrentUnit[1]][1] + currenToNeibor
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][2] = 10 * (abs(CurrentNeibors[i][0] - End_x) + abs(CurrentNeibors[i][1] - End_y))
chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3] = chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] + chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][2]
#将该临近点存入openlist中
OpenList[OpenListPosition][0] = CurrentNeibors[i][0]
OpenList[OpenListPosition][1] = CurrentNeibors[i][1]
OpenList[OpenListPosition][2] = chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3]
OpenListPosition+=1
else:
#if
i+=2#循环变量增加2
#while
return 0
def FileReadMatrix(): #将文件中的数据读回至chess_size*chess_size矩阵
global chessboard
i = 0
itemLine = []
fileLine = []
#uint uiTemp; //定义变量存放从文件中读出的数据
ifile = open(FILE_STORAGE_WAY,'r') #作为只读文件打开
#while True:
fileLine = ifile.readline()
while len(fileLine)>0:#只要读取的这一行有值,就处理
j = 0
while j<10:
#将棋盘读入到flag中
if 's' == fileLine[j]: #检测并记录起始点坐标
Start_x = i
Start_y = j
item = [[0,0],0,0,0,fileLine[j]] #结构:A = [[parent.x,parent.y],g_value,h_value,f_value,flag]
itemLine.append(item) #结构:B = [A,A,A,A,A....,A]一行20个
j+=1
chessboard.append(itemLine) #结构:[B,B,B,B,...,B] 20列
fileLine = ifile.readline()#读取下一行数据
i+=1
def printPath():
global chessboard
i = 0 #循环变量
PathUnit = [] #逆序存放单路径结点(终点->起点)
PathUnitList = [] #逆序存放所有路径结点(终点->起点)
#获取终点的坐标
PathUnit = [End_x,End_y];
print('(%d,%d)'%(PathUnit[0],PathUnit[1])) #输出终点坐标
#记录从end起第一个最佳路径结点
PathUnit = [chessboard[End_x][End_y][0][0],chessboard[End_x][End_y][0][1]]
while not(PathUnit[0] == Start_x and PathUnit[1] == Start_y) #记录从终点到起点之间的最佳路径
PathUnitList.append(PathUnit) #将PathUnit结点插入PathUnitList列表中
chessboard[PathUnitList[i][0]][PathUnitList[i][1]][4] = '*' #将最佳路径点用"*"表示
print('(%d,%d)'%(PathUnitList[i][0],PathUnitList[i][1])) #输出最短路径结点坐标
#获取当前结点的父结点坐标
PathUnit = [chessboard[PathUnitList[i].ChessUnit_x][PathUnitList[i].ChessUnit_y][0][0],chessboard[PathUnitList[i].ChessUnit_x][PathUnitList[i].ChessUnit_y][0][1]]
i+=1
print('(%d,%d)'%(Start_x,Start_y)) #输出起点坐标
#打印棋盘及最短路径
i=0
while i < chess_size:
#for (int i = 0; i < chess_size; i++)
j=0
while j < chess_size:
#cout << chessboard[i][j].flag;
chessboardline.append(chessboard[i][j][4])#将一行数据逐个插入到chessboardline中
j+=1
print(chessboardline)#打印一行数据
i+=1
def main():
global OpenListPosition
global CloseListPosition
global OpenList
global CloseList
FileReadMatrix()
item = [Start_x,Start_y,0]#将起始点x坐标,y坐标,f值封装到列表item中
OpenList.append(item)#将item插入到Openlist中
OpenListPosition += 1#将起始结点存入openlist,position标记为1(position总指向最后一个元素的后一位置)
while OpenListPosition > 0: #若openlist不为空
openListIncraseSort() #openlist列表按f值大小降序排序(将最小f值点放在最后,这样只需将position减1就代表移出该点)
#将openlist中f值最小的点移入closelist中
item = [OpenList[OpenListPosition - 1][0],OpenList[OpenListPosition - 1][1]]
CloseList.append(item)
#openlist移出f值最小元素,清除原位置该元素信息
OpenList.pop()#移除openlist中最后的那个元素
OpenListPosition -= 1 #将OpenListPosition减1,表示从openlist中移出最后一点,即f值最小的点
CloseListPosition += 1 #将ClosePosition加1,记录closelist中增加一个元素
#将f最小结点信息插入到CurrentUnit中
CurrentUnit = [CloseList[CloseListPosition - 1][0],CloseList[CloseListPosition - 1][1]]
#判断当前结点周围8个点状态,计算g、h、f值,将周围每个点的父指针指向当前结点
if dealCurrentNeibors(CurrentUnit) == 1:
break
#while
printPath();
#return 0
main()