A*寻路算法python版(第二版)

    这一周的工作主要是将上一周改的python版代码调试正常。由于对python语言特定语法结构理解的还是不深,所以的遇到了很多坑,万幸最后还是一一填上了,随着不断的调试对于python的有了进一步的认识。先交代一下最大的坑,就是对于python嵌套列表的深拷贝浅拷贝的不了解和错误使用,导致代码运行时出现了各种诡异的现象。总结如下,共勉!

    首先讲一下在应用嵌套列表时对于深浅拷贝个人理解

    比如:a = [['c','d'],5,4,'g'],列表a是一个内部嵌套了一层列表['c','d']的列表,如果要将a中的数据拷贝到列表b中,以下给出3种操作方式,正确与否会详细说明,仅通过3种方式来交代深拷贝浅拷贝的区别

    1).b = a,这一种方式其实是将b映射到a的存储位置上,不是真正的拷贝,一旦b中的元素被修改,a中的元素也同样会被修改

    2).b = a[:],这一种方式是浅拷贝。其实如果a内部没有嵌套列表,如 ['c','d',5,4,'g'],这种方式是正确的,因为浅拷贝会拷贝到列表a很浅的一部分,即最外层。这样b不会被映射到a的存储位置上,两者存储空间互不干扰。但是现在a内部嵌套了一个列表,再用浅拷贝操作,这样b中的元素会部分映射到a,猜也能猜到就是列表内部嵌套的一层['c','d']会被b与a共享,而列表中剩下的元素是存储在不同的位置,不会被共享。所以这样就会导致诡异的现象:你以为拷贝成功了,但只要修改一个列表中共享位置的元素,之前的副本中的元素全部也被修改,注意浅拷贝的另一种方式是b = copy.copy(a),但是需要在前面import copy工具箱。

    3).b = copy.deepcopy(a),这一种方式是深拷贝需要import copy工具箱,这种方式顾名思义,就是将列表中嵌套的列表也都拷贝到另一个存储位置上,所以要想只将a的元素的值复制一份给b,而不想a与b之间还有任何牵连需要进行深拷贝操作。

    用python编的这套A*算法,基本步骤与c++版本一致,主要是由于python中有列表这种数据结构,所以将c++中结构体和类变量以嵌套列表的方式来表示,现以c++与python对比的方式将一些重要数据结构作出说明:

    以chessboard棋盘这个概念的数据结构为例

    在c++中,我使用的是结构体来定义棋盘,具体如下:

    结构体定义:

struct PARENT_POSITION//父指针
{
	int x;
	int y;
};

struct CHESS_BOARD_UNIT
{
	PARENT_POSITION ParentPosition;
	int g_value;
	int h_value;
	int f_value;
	char flag;//标识此单元是:2起点/3终点/1障碍物/0通路
};

    结构体数组定义:

CHESS_BOARD_UNIT chessboard[chess_size][chess_size] = { 0 };//chessboard初始化为0

    若操作地图上3行5列点的父指针的横坐标,操作如下:

    chessboard[3][5].ParentPosition.x= 5


    在python中,我使用的是列表来定义棋盘,具体如下:

    这里注意,与c++的区别是python定义列表不用预先分配好这个列表的大小,想用直接往里存就可以了。

    chessboard = [] #用python定义就是如此简单!!!

    而chessboard具体的数据结构必须是在存放完所有元素之后才能确定!实际上chessboard的每一个方格元素的结构是

    A = [[parent.x,parent.y],g_value,h_value,f_value,flag],与c++版本中数据结构得顺序是一致的

    以下将存放元素的具体代码贴出:

	i = 0 
	while i <20:
		j = 0
		while j<20:
			#将棋盘读入到flag中
			if 's' == chessboardTemp[i][j]: #检测并记录起始点坐标
				print('起始点坐标!!![%d,%d]'%(i,j))
				Start_x = i
				Start_y = j
			if 'e' == chessboardTemp[i][j]: #检测并记录终止点坐标
				print('终止点坐标!!![%d,%d]'%(i,j))
				End_x = i
				End_y = j
			if 'b' == chessboardTemp[i][j]: #检测并记录终止点坐标
				print('障碍点坐标!!![%d,%d]'%(i,j))

			item=[[0,0],0,0,0,chessboardTemp[i][j]]#结构:A = [[parent.x,parent.y],g_value,h_value,f_value,flag]
			#print(item[4])
			itemLine.append(copy.deepcopy(item)) #结构:B = [A,A,A,A,A....,A]一行20个,一定要传切片[:]!!!
			print(itemLine[j][4])
			j+=1
		print(fileLine)
		chessboard.append(copy.deepcopy(itemLine)) #结构:[B,B,B,B,...,B] 20列,一定要传切片!!!
		itemLine = []#超级大bug:将itemLine清空(查了一晚上!!!!)
		fileLine = ifile.readline()#读取下一行数据
		i+=1

    说明一下这段代码的简单流程,chessboardTemp是一个列表,列表中的元素是从txt文件中读取的每一行字符串(即每行地图),两层循环的工作就是要将表示地图的每一个字符存放到 A = [[parent.x,parent.y],g_value,h_value,f_value,flag]的flag位置上。

item = [[0,0],0,0,0,chessboardTemp[i][j]]就相当于c++中棋盘中的一个方格的结构体,itemLine.append(copy.deepcopy(item))操作循环20次就是要将一行20个方格排列在一个列表里,构成chessboard的一行itemLine = [item,item,item,item,...,item]。

chessboard.append(copy.deepcopy(itemLine))操作循环20次相当于chessboard = [itemLine,itemLine,itemLine,...,itemLine]

构成了chessboard的20行,即整个chessboard的数据结构就被建立起来了。

    同样,若操作地图上3行5列点的父指针的横坐标,操作如下:

    chessboard[3][5][0][0] = 5 #言简意赅!!!


    现将寻路结果截图:


    下面将python版本的全部代码贴出

    注意:

    1.此版本调试信息我忘了加开关,所以会在控制台打出大量调试信息,下一版再修正!

    2.要预先在.py文件的相同目录下建立地图txt文件(代码中名为‘123.txt’),现将地图贴出:

########b###########
########b###########
##s#####b###########
########b########e##
########b###########
########b###########
######b#b###########
######b#bbbbbb######
######b######b######
#########b###b######
#########b###b######
#########b###b#bbb##
#########b##########
####################
####################
####################
####################
####################
####################
####################

    代码:

#coding=utf-8
import copy
chess_size =  20
FILE_STORAGE_WAY =  '123.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列表

chessboard = []	

def openListIncraseSort():
	global OpenListPosition
	global OpenList
	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 j<OpenListPosition - 1:##############- 1
			if OpenList[j][2] < OpenList[j + 1][2]:#若OpenList[j].f_value < OpenList[j + 1].f_value,交换,从大到小排列
			
				ChessUnit_x = OpenList[j][0]
				ChessUnit_y = OpenList[j][1]
				f_value 	= OpenList[j][2]

				OpenList[j][0]= OpenList[j + 1][0]
				OpenList[j][1]= OpenList[j + 1][1]
				OpenList[j][2]= OpenList[j + 1][2]

				OpenList[j + 1][0] = ChessUnit_x
				OpenList[j + 1][1] = ChessUnit_y
				OpenList[j + 1][2] = f_value

				flag = 1 #将交换标志位置1
			j+=1 #循环变量增加1
			#if
		#while2
		if (0 == flag):
			break #内层循环一次都没交换,说明已经排好序
		flag = 0 #将标志位重新清0
		i+=1 #循环变量增加1
	print('===调试用===openListIncraseSort()')#调试用,输出openListIncraseSort
	print('===调试用===按f_value排序后的OpenList =')
	print(OpenList)


def dealCurrentNeibors(CurrentUnit):#判断当前结点周围8个点状态,计算g、h、f值,将周围每个点的父指针指向当前结点
	global OpenListPosition
	global CloseListPosition
	global OpenList
	global CloseList
	global chessboard
	OpenListFlag = 0
	CloseListFlag = 0

	ObstacleEast = 0	#标识当前点东边是否有障碍物
	ObstacleSouth = 0	#标识当前点南边是否有障碍物
	ObstacleWest = 0	#标识当前点西边是否有障碍物
	ObstacleNorth = 0	#标识当前点北边是否有障碍物

	#CloseListUnit EastUnit, SourthEastUnit, SourthUnit, SourthWestUnit, WestUnit, NorthWestUnit, NorthUnit, NorthEastUnit;//东,东南,南,西南,西,西北,北,东北
	CurrentNeibors = []#列表,按顺序存放当前结点的东,东南,南,西南,西,西北,北,东北方向的邻结点
	OpenlistTemp = []#列表,存放openlist【x,y,f_value】中的【x,y】
	for temp in OpenList:
		OpenlistTemp.append([temp[0],temp[1]])
	print('===调试用===dealCurrentNeibors():OpenlistTemp=')#调试用,输出OpenlistTemp
	print(OpenlistTemp)#调试用,输出OpenlistTemp
	#东方y+1
	item = [CurrentUnit[0],CurrentUnit[1] + 1]
	CurrentNeibors.append(item)

	#东南方x+1,y+1
	item = [CurrentUnit[0] + 1,CurrentUnit[1] + 1]
	CurrentNeibors.append(item)

	#南方x+1
	item = [CurrentUnit[0] + 1,CurrentUnit[1]]
	CurrentNeibors.append(item)

	#西南方x+1,y-1
	item = [CurrentUnit[0] + 1,CurrentUnit[1]-1]
	CurrentNeibors.append(item)

	#西方y-1
	item = [CurrentUnit[0],CurrentUnit[1]-1]
	CurrentNeibors.append(item)

	#西北方x-1,y-1
	item = [CurrentUnit[0]-1,CurrentUnit[1]-1]
	CurrentNeibors.append(item)

	#北方x-1
	item = [CurrentUnit[0]-1,CurrentUnit[1]]
	CurrentNeibors.append(item)

	#东北方x-1,y+1
	item = [CurrentUnit[0]-1,CurrentUnit[1]+1]
	CurrentNeibors.append(item)
	print('===调试用===CurrentUnit=(%d,%d)'%(CurrentUnit[0],CurrentUnit[1]))#调试用	
	print(chessboard[6][6][4])
	print(chessboard[6][8][4])

	print('===调试用===dealCurrentNeibors():CurrentNeibors=')#调试用
	print(CurrentNeibors)#调试用
	#对当前方格东、南、西、北四个方向的临近方格依次检测
	i = 0
	while i<8:
		#当前中间结点到邻近结点的距离。约定:东南西北四个方向距离为10,四个斜方向距离为14
		if i%2 == 0:
			currenToNeibor = 10
		else:
			currenToNeibor = 14
		print('===调试用===dealCurrentNeibors():currenToNeibor=[%d]'%currenToNeibor)#调试用
		print('===调试用===dealCurrentNeibors():CurrentUnit[0]=[%d] CurrentUnit[1]=[%d]'%(CurrentUnit[0],CurrentUnit[1]))
		print('===调试用===dealCurrentNeibors():chessboard[CurrentUnit[0]][CurrentUnit[1]][1]=[%d]'%chessboard[CurrentUnit[0]][CurrentUnit[1]][1])			
		#超出边界点
		if CurrentNeibors[i][0] < 0 or CurrentNeibors[i][0]>19 or CurrentNeibors[i][1] < 0 or CurrentNeibors[i][1]>19:
			print('===调试用===dealCurrentNeibors():超出边界点!!!(%d,%d)'%(CurrentNeibors[i][0],CurrentNeibors[i][1]))
			#continue #结束判断
				
		# print('===调试用===dealCurrentNeibors():currenToNeibor=[%d],i=[%d]'%(currenToNeibor,i))#调试用
		# print('===调试用===dealCurrentNeibors():CurrentNeibors[%d][0]=[%d]'%(i,CurrentNeibors[i][0]))#调试用
		# print('===调试用===dealCurrentNeibors():CurrentNeibors[%d][1]=[%d]'%(i,CurrentNeibors[i][1]))#调试用
		# print('===调试用===dealCurrentNeibors():chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][4]=')
		# print(chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][4])

		#终点
		elif '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
			print('===调试用===dealCurrentNeibors():找到终点!!!(%d,%d)'%(CurrentNeibors[i][0],CurrentNeibors[i][1]))#调试用
			return 1

		#障碍物点
		elif 'b' == chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][4]:#flags
			print('===调试用===dealCurrentNeibors():找到障碍物点!!!(%d,%d)'%(CurrentNeibors[i][0],CurrentNeibors[i][1]))#调试用
			if i == 0:
				ObstacleEast = 1 #标识当前点东边有障碍物
				print('===调试用===dealCurrentNeibors():ObstacleEast = %d'%ObstacleEast)
			elif i == 2:
				ObstacleSouth = 1 #标识当前点南边有障碍物
				print('===调试用===dealCurrentNeibors():ObstacleSouth = %d'%ObstacleSouth)
			elif i == 4:
				ObstacleWest = 1 #标识当前点西边有障碍物
				print('===调试用===dealCurrentNeibors():ObstacleWest = %d'%ObstacleWest)
			elif i == 6:
				ObstacleNorth = 1 #标识当前点北边有障碍物
				print('===调试用===dealCurrentNeibors():ObstacleNorth = %d'%ObstacleNorth)				

		#将该临近点与closelist中的点逐个比较
		elif CurrentNeibors[i] in CloseList:#python牛逼!
			print('===调试用===dealCurrentNeibors():CurrentNeibors[%d]是closelist中的点!!!(%d,%d)'%(i,CurrentNeibors[i][0],CurrentNeibors[i][1]))
			print('===调试用===dealCurrentNeibors():CloseList=')
			print(CloseList)
			#continue#结束判断

		#将该临近点与openlist中的点逐个比较
		elif CurrentNeibors[i] in OpenlistTemp:#python牛逼!
			print('===调试用===dealCurrentNeibors():CurrentNeibors[i] in OpenlistTemp:')#调试用
			print('===调试用===dealCurrentNeibors():CurrentNeibors[i]=')
			print(CurrentNeibors[i])
			print('===调试用===dealCurrentNeibors():OpenlistTemp=')
			print(OpenlistTemp)
			#若该临近点的g值大于从起点经由当前结点到该临近结点的g值,将该临近结点的父指针指向当前结点,并更改该临近结点的g值,f值
			if chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] > chessboard[CurrentUnit[0]][CurrentUnit[1]][1] + currenToNeibor:
				#将该临近结点的父指针指向当前结点
				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
				print('===调试用===dealCurrentNeibors():修改(%d,%d)结点的父节点(%d,%d)'%(CurrentNeibors[i][0],CurrentNeibors[i][1],CurrentUnit[0],CurrentUnit[1]))
				#更改该临近结点的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
				counter=0
				while len(OpenList)-counter > 0:#大bug,漏掉了此处,导致openlist中的f_value值没有被更新!!!注意修改list值不能用for
					if CurrentNeibors[i][0] == OpenList[counter][0] and CurrentNeibors[i][1] == OpenList[counter][1]:#找到openlist中要修改f_value的位置
						OpenList[counter][2] = chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3]#更新openlist中的f值
						break
					counter+=1
		#可作为通路点
		elif '#' == chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][4]:
			#将邻居结点的指针指向当前结点
			print('===调试用===dealCurrentNeibors():CurrentUnit[0]=[%d] CurrentUnit[1]=[%d]'%(CurrentUnit[0],CurrentUnit[1]))
			print('===调试用===dealCurrentNeibors():chessboard[CurrentUnit[0]][CurrentUnit[1]][1]=[%d]'%chessboard[CurrentUnit[0]][CurrentUnit[1]][1])			
			
			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
			print('===调试用===dealCurrentNeibors():(%d,%d)结点的父节点为(%d,%d)'%(CurrentNeibors[i][0],CurrentNeibors[i][1],CurrentUnit[0],CurrentUnit[1]))

			#print('===调试用===dealCurrentNeibors():chessboard=')	
			#print(chessboard)	

			#计算该临近结点的g值,h值(曼哈顿距离),f值
			#temptest = chessboard[CurrentUnit[0]][CurrentUnit[1]][1][:] + currenToNeibor
			chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] = chessboard[CurrentUnit[0]][CurrentUnit[1]][1] + currenToNeibor#一条诡异的程序
			print(type(chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1]))
			print(type(chessboard[CurrentUnit[0]][CurrentUnit[1]][1]))
			print(type(currenToNeibor))
		
			print('===调试用===dealCurrentNeibors():CurrentNeibors[i][0]=[%d] CurrentNeibors[i][1]=[%d]'%(CurrentNeibors[i][0],CurrentNeibors[i][1]))
			print('===调试用===dealCurrentNeibors():CurrentUnit[0]=[%d] CurrentUnit[1]=[%d]'%(CurrentUnit[0],CurrentUnit[1]))
			print('===调试用===dealCurrentNeibors():chessboard[CurrentUnit[0]][CurrentUnit[1]][1]=[%d]'%chessboard[CurrentUnit[0]][CurrentUnit[1]][1])			
			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]
			print('===调试用===dealCurrentNeibors():g_value=[%d]'%chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1])
			print('===调试用===dealCurrentNeibors():h_value=[%d]'%chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][2])
			print('===调试用===dealCurrentNeibors():f_value=[%d]'%chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3])

			print('===调试用===dealCurrentNeibors():CurrentUnit[0]=[%d] CurrentUnit[1]=[%d]'%(CurrentUnit[0],CurrentUnit[1]))
			print('===调试用===dealCurrentNeibors():chessboard[CurrentUnit[0]][CurrentUnit[1]][1]=[%d]'%chessboard[CurrentUnit[0]][CurrentUnit[1]][1])			

			#将该临近点存入openlist中
			temp = [CurrentNeibors[i][0],CurrentNeibors[i][1],chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3]]
			OpenList.append(temp) 
			print('===调试用===dealCurrentNeibors():OpenList.append(temp),temp=')
			print(temp)
			print('===调试用===dealCurrentNeibors():OpenList.append(temp),OpenList')
			print(OpenList)
			OpenListPosition+=1
			print('===调试用===dealCurrentNeibors():CurrentUnit[0]=[%d] CurrentUnit[1]=[%d]'%(CurrentUnit[0],CurrentUnit[1]))
			print('===调试用===dealCurrentNeibors():chessboard[CurrentUnit[0]][CurrentUnit[1]][1]=[%d]'%chessboard[CurrentUnit[0]][CurrentUnit[1]][1])			
			#print('===调试用===OpenList.append(temp),OpenListPosition = [%d]',%OpenListPosition)
		i+=2#循环变量增加2

	#对当前方格东南、西南、西北、东北四个方向的临近方格依次检测
	i = 1
	while i < 8 :
		#i+=2#循环变量增加2
		#当前中间结点到邻近结点的距离。约定:东南西北四个方向距离为10,四个斜方向距离为14
		if i%2 == 0:
			currenToNeibor = 10
		else:
			currenToNeibor = 14
		print('===调试用===dealCurrentNeibors():ObstacleEast = %d'%ObstacleEast)
		print('===调试用===dealCurrentNeibors():ObstacleSouth = %d'%ObstacleSouth)
		print('===调试用===dealCurrentNeibors():ObstacleWest = %d'%ObstacleWest)
		print('===调试用===dealCurrentNeibors():ObstacleNorth = %d'%ObstacleNorth)
		#print('===调试用===i=[%d]'%i)#调试用

		print('===调试用===dealCurrentNeibors():currenToNeibor=[%d]'%currenToNeibor)#调试用

		if 1 == ObstacleEast  and (1 == i or 7 == i): #若东方格是障碍物,则东南、东北都不能通行
			print('===调试用===i=[%d]'%i)#调试用
			i+=2
			continue

		if 1 == ObstacleSouth and (1 == i or 3 == i): #若南方格是障碍物,则东南、西南都不能通行
			print('===调试用===i=[%d]'%i)#调试用
			i+=2
			continue

		if 1 == ObstacleWest and (3 == i or 5 == i): #若西方格是障碍物,则西南、西北都不能通行
			print('===调试用===i=[%d]'%i)#调试用
			i+=2
			continue

		if 1 == ObstacleNorth and (5 == i or 7 == i): #若北方格是障碍物,则西北、东北都不能通行
			print('===调试用===i=[%d]'%i)#调试用
			i+=2
			continue

		#超出边界点
		if CurrentNeibors[i][0] < 0 or CurrentNeibors[i][0]>19 or CurrentNeibors[i][1] < 0 or CurrentNeibors[i][1]>19:
			print('===调试用===dealCurrentNeibors():超出边界点!!!(%d,%d)'%(CurrentNeibors[i][0],CurrentNeibors[i][1]))
			#continue #结束判断

		#终点
		elif '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
			print('===调试用===dealCurrentNeibors():找到终点!!![%d][%d]'%(CurrentNeibors[i][0],CurrentNeibors[i][1]))#调试用			
			return 1

		#障碍物点
		elif 'b' == chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][4]:#flags
			print('===调试用===dealCurrentNeibors():找到障碍物点!!![%d][%d]'%(CurrentNeibors[i][0],CurrentNeibors[i][1]))#调试用
			

		#将该临近点与closelist中的点逐个比较
		elif CurrentNeibors[i] in CloseList:#python牛逼!
			print('===调试用===dealCurrentNeibors():CurrentNeibors[%d]是closelist中的点!!!(%d,%d)'%(i,CurrentNeibors[i][0],CurrentNeibors[i][1]))
			#continue#结束判断

		#将该临近点与openlist中的点逐个比较
		elif CurrentNeibors[i] in OpenlistTemp:#python牛逼!
			print('===调试用===dealCurrentNeibors():CurrentNeibors[i] in OpenlistTemp:')#调试用
			print('===调试用===dealCurrentNeibors():CurrentNeibors[i]=')
			print(CurrentNeibors[i])
			print('===调试用===dealCurrentNeibors():OpenlistTemp=')
			print(OpenlistTemp)
			#若该临近点的g值大于从起点经由当前结点到该临近结点的g值,将该临近结点的父指针指向当前结点,并更改该临近结点的g值,f值
			if chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] > chessboard[CurrentUnit[0]][CurrentUnit[1]][1] + currenToNeibor:
				#将该临近结点的父指针指向当前结点
				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
				print('===调试用===dealCurrentNeibors():修改(%d,%d)结点的父节点(%d,%d)'%(CurrentNeibors[i][0],CurrentNeibors[i][1],CurrentUnit[0],CurrentUnit[1]))

				#更改该临近结点的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
				counter=0
				while len(OpenList)-counter > 0:#大bug,漏掉了此处,导致openlist中的f_value值没有被更新!!!注意修改list值不能用for
					if CurrentNeibors[i][0] == OpenList[counter][0] and CurrentNeibors[i][1] == OpenList[counter][1]:#找到openlist中要修改f_value的位置
						OpenList[counter][2] = chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3]#更新openlist中的f值
						break
					counter+=1
		#可作为通路点
		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
			print('===调试用===dealCurrentNeibors():(%d,%d)结点的父节点为(%d,%d)'%(CurrentNeibors[i][0],CurrentNeibors[i][1],CurrentUnit[0],CurrentUnit[1]))

			#计算该临近结点的g值,h值(曼哈顿距离),f值
			chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1] = chessboard[CurrentUnit[0]][CurrentUnit[1]][1] + currenToNeibor
			print('===调试用===dealCurrentNeibors():CurrentUnit[0]=[%d] CurrentUnit[1]=[%d]'%(CurrentUnit[0],CurrentUnit[1]))
			print('===调试用===dealCurrentNeibors():chessboard[CurrentUnit[0]][CurrentUnit[1]][1]=[%d]'%chessboard[CurrentUnit[0]][CurrentUnit[1]][1])			
			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]
			print('===调试用===dealCurrentNeibors():g_value=[%d]'%chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][1])
			print('===调试用===dealCurrentNeibors():h_value=[%d]'%chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][2])
			print('===调试用===dealCurrentNeibors():f_value=[%d]'%chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3])

			#将该临近点存入openlist中
			temp = [CurrentNeibors[i][0],CurrentNeibors[i][1],chessboard[CurrentNeibors[i][0]][CurrentNeibors[i][1]][3]]
			OpenList.append(temp) 
			print('===调试用===dealCurrentNeibors():OpenList.append(temp),temp=')
			print(temp)
			print('===调试用===dealCurrentNeibors():OpenList.append(temp),OpenList')
			print(OpenList)
			OpenListPosition+=1
		#	print('===调试用===OpenList.append(temp),OpenListPosition = [%d]',%OpenListPosition)
		i+=2#循环变量增加2
	return 0

def FileReadMatrix():	#将文件中的数据读回至chess_size*chess_size矩阵
	global Start_x
	global Start_y
	global End_x
	global End_y
	
	itemLine = []
	fileLine = []
	chessboardTemp = []
	ifile = open(FILE_STORAGE_WAY,'r')	#作为只读文件打开
	fileLine = ifile.readline()
	while len(fileLine)>0:#将迷宫从txt文件中读入到chessboardTemp列表中
		print(fileLine)
		print(fileLine[0:20])
		chessboardTemp.append(fileLine[0:20])
		fileLine = ifile.readline()
	print(chessboardTemp)
	print(chessboardTemp[2][2])
	i = 0 
	while i <20:
		j = 0
		while j<20:
			#将棋盘读入到flag中
			if 's' == chessboardTemp[i][j]: #检测并记录起始点坐标
				print('起始点坐标!!![%d,%d]'%(i,j))
				Start_x = i
				Start_y = j
			if 'e' == chessboardTemp[i][j]: #检测并记录终止点坐标
				print('终止点坐标!!![%d,%d]'%(i,j))
				End_x = i
				End_y = j
			if 'b' == chessboardTemp[i][j]: #检测并记录终止点坐标
				print('障碍点坐标!!![%d,%d]'%(i,j))

			
			item = [[0,0],0,0,0,chessboardTemp[i][j]]#结构:A = [[parent.x,parent.y],g_value,h_value,f_value,flag]
			#print(item[4])
			itemLine.append(copy.deepcopy(item)) #结构:B = [A,A,A,A,A....,A]一行20个,一定要传切片[:]!!!
			print(itemLine[j][4])
			j+=1
		print(fileLine)
		chessboard.append(copy.deepcopy(itemLine)) #结构:[B,B,B,B,...,B] 20列,一定要传切片!!!
		itemLine = []#超级大bug:将itemLine清空(查了一晚上!!!!)
		fileLine = ifile.readline()#读取下一行数据
		i+=1
	print(chessboard[2][2][4])
	#print(chessboard[6][8][4])
	#print(chessboard)
def printPath():
	PathUnit = []#逆序存放单路径结点(终点->起点)
	PathUnitList = []#逆序存放所有路径结点(终点->起点)
	#获取终点的坐标								  
	PathUnit = [End_x,End_y]

	#cout << "(" << PathUnit.ChessUnit_x << "," << PathUnit.ChessUnit_y << ")" << endl;//输出终点坐标
	print('(%d,%d)'%(PathUnit[0],PathUnit[1]))	
	#记录从end起第一个最佳路径结点
	PathUnit = [chessboard[End_x][End_y][0][0],chessboard[End_x][End_y][0][1]]
	i = 0 #循环变量
	while not(PathUnit[0] == Start_x and PathUnit[1] == Start_y): #记录从终点到起点之间的最佳路径
		PathUnitList.append(copy.deepcopy(PathUnit))#重大bug!!!必须传拷贝,不然循环插入到会修改上一次PathUnit的值
		chessboard[PathUnitList[i][0]][PathUnitList[i][1]][4] = '*'#将最佳路径点用"*"表示
		#cout << "(" << PathUnitList[i].ChessUnit_x << "," << PathUnitList[i].ChessUnit_y << ")" << endl;//输出路径结点坐标
		#输出路径结点坐标
		print('(%d,%d)'%(PathUnit[0],PathUnit[1]))	
		#获取当前结点的父节点坐标																		
		PathUnit[0] = chessboard[PathUnitList[i][0]][PathUnitList[i][1]][0][0]
		PathUnit[1] = chessboard[PathUnitList[i][0]][PathUnitList[i][1]][0][1]
		i+=1
	#cout << "(" << Start_x << "," << Start_y << ")" << endl;//输出终点坐标
	print('(%d,%d)'%(Start_x,Start_y))	#输出终点坐标
	'''
	for (int i = 0; i < chess_size; i++)
	{
		for (int j = 0; j < chess_size; j++)
		{
			cout << chessboard[i][j].flag;
		}
		cout << endl;
	}
	'''
	
	temp =''
	i=0
	while i<20:
		j=0
		while j<20:
			temp += chessboard[i][j][4]
			j+=1
		print(temp)
		temp =''#清空行输出变量
		i+=1
	

def main():
	global OpenListPosition
	global CloseListPosition
	global OpenList
	global CloseList
	global Start_x
	global Start_y

	FileReadMatrix()
	
	item = [Start_x,Start_y,0]#将起始点x坐标,y坐标,f值封装到列表item中
	print(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)
		# print(CloseList)#调试用
		#openlist移出f值最小元素,清除原位置该元素信息
		OpenList.pop()#移除openlist中最后的那个元素
		print('===调试用===main():移除最小元素之后的openlist=')
		print(OpenList)
		OpenListPosition  -= 1 #将OpenListPosition减1,表示从openlist中移出最后一点,即f值最小的点
		#print(OpenListPosition)
		CloseListPosition += 1 #将ClosePosition加1,记录closelist中增加一个元素
		
		#将f最小结点信息插入到CurrentUnit中
		CurrentUnit = [CloseList[CloseListPosition - 1][0],CloseList[CloseListPosition - 1][1]]
		print('===调试用===main():CloseListPosition=[%d]'%CloseListPosition)
		print('===调试用===main():CloseList=')
		print('===调试用===main():CloseList=')
		print(CloseList)
		#判断当前结点周围8个点状态,计算g、h、f值,将周围每个点的父指针指向当前结点
		if dealCurrentNeibors(CurrentUnit) == 1:
			print('===调试用===main():找到终点,跳出循环')
			print('===调试用===main():找到终点,跳出循环')
			print('===调试用===main():找到终点,跳出循环')
			break
	#dealCurrentNeibors(CurrentUnit)
	print('===调试用===OpenListPosition=[%d]'%OpenListPosition)
	#while
	printPath()

	#return 0

main()


  • 15
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值