A*算法 -- python

#coding=utf-8
import math

#地图
tm = [
	'############################################################',
	'#..........................................................#',
	'#.............................#............................#',
	'#.............................#............................#',
	'#.............................#............................#',
	'#.......S.....................#............................#',
	'#.............................#............................#',
	'#.............................#............................#',
	'#.............................#............................#',
	'#.............................#............................#',
	'#.............................#............................#',
	'#.............................#............................#',
	'#.............................#............................#',
	'#######.#######################################............#',
	'#....#...E....#............................................#',
	'#....#........#............................................#',
	'#....##########............................................#',
	'#..........................................................#',
	'#..........................................................#',
	'#..........................................................#',
	'#..........................................................#',
	'#..........................................................#',
	'#...............................##############.............#',
	'#...............................#............#.............#',
	'#...............................#............#.............#',
	'#...............................#............#.............#',
	'#...............................#............#.............#',
	'#...............................###########..#.............#',
	'#..........................................................#',
	'#..........................................................#',
	'############################################################']

#因为python里string不能直接改变某一元素,所以用test_map来存储搜索时的地图
test_map = []

#########################################################
class Node_Elem:
	"""
开放列表和关闭列表的元素类型,parent用来在成功的时候回溯路径
"""
	def __init__(self, parent, x, y, dist):
		self.parent = parent
		self.x = x
		self.y = y
		self.dist = dist

class A_Star:
	"""
A星算法实现类
"""
	#注意w,h两个参数,如果你修改了地图,需要传入一个正确值或者修改这里的默认参数
	def __init__(self, s_x, s_y, e_x, e_y, w=60, h=30):
		self.s_x = s_x
		self.s_y = s_y
		self.e_x = e_x
		self.e_y = e_y

		self.width = w
		self.height = h

		self.open = []
		self.close = []
		self.path = []

	#查找路径的入口函数
	def find_path(self):
		#构建开始节点
		p = Node_Elem(None, self.s_x, self.s_y, 0.0)
		while True:
			#扩展F值最小的节点
			self.extend_round(p)
			#如果开放列表为空,则不存在路径,返回
			if not self.open:
				return
				#获取F值最小的节点
			idx, p = self.get_best()
			#找到路径,生成路径,返回
			if self.is_target(p):
				self.make_path(p)
				return
				#把此节点压入关闭列表,并从开放列表里删除
			self.close.append(p)
			del self.open[idx]

	def make_path(self,p):
		#从结束点回溯到开始点,开始点的parent == None
		while p:
			self.path.append((p.x, p.y))
			p = p.parent

	def is_target(self, i):
		return i.x == self.e_x and i.y == self.e_y

	def get_best(self):
		best = None
		bv = 1000000 #如果你修改的地图很大,可能需要修改这个值
		bi = -1
		for idx, i in enumerate(self.open):
			value = self.get_dist(i)#获取F值
			if value < bv:#比以前的更好,即F值更小
				best = i
				bv = value
				bi = idx
		return bi, best

	def get_dist(self, i):
		# F = G + H
		# G 为已经走过的路径长度, H为估计还要走多远
		# 这个公式就是A*算法的精华了。
		return i.dist + math.sqrt(
			(self.e_x-i.x)*(self.e_x-i.x)
			+ (self.e_y-i.y)*(self.e_y-i.y))*1.2

	def extend_round(self, p):
		#可以从8个方向走
		xs = (-1, 0, 1, -1, 1, -1, 0, 1)
		ys = (-1,-1,-1,  0, 0,  1, 1, 1)
		#只能走上下左右四个方向
		#        xs = (0, -1, 1, 0)
		#        ys = (-1, 0, 0, 1)
		for x, y in zip(xs, ys):
			new_x, new_y = x + p.x, y + p.y
			#无效或者不可行走区域,则勿略
			if not self.is_valid_coord(new_x, new_y):
				continue
				#构造新的节点
			node = Node_Elem(p, new_x, new_y, p.dist+self.get_cost(
				p.x, p.y, new_x, new_y))
			#新节点在关闭列表,则忽略
			if self.node_in_close(node):
				continue
			i = self.node_in_open(node)
			if i != -1:
				#新节点在开放列表
				if self.open[i].dist > node.dist:
					#现在的路径到比以前到这个节点的路径更好~
					#则使用现在的路径
					self.open[i].parent = p
					self.open[i].dist = node.dist
				continue
			self.open.append(node)

	def get_cost(self, x1, y1, x2, y2):
		"""
上下左右直走,代价为1.0,斜走,代价为1.4
"""
		if x1 == x2 or y1 == y2:
			return 1.0
		return 1.4

	def node_in_close(self, node):
		for i in self.close:
			if node.x == i.x and node.y == i.y:
				return True
		return False

	def node_in_open(self, node):
		for i, n in enumerate(self.open):
			if node.x == n.x and node.y == n.y:
				return i
		return -1

	def is_valid_coord(self, x, y):
		if x < 0 or x >= self.width or y < 0 or y >= self.height:
			return False
		return test_map[y][x] != '#'

	def get_searched(self):
		l = []
		for i in self.open:
			l.append((i.x, i.y))
		for i in self.close:
			l.append((i.x, i.y))
		return l

#########################################################
def print_test_map():
	"""
打印搜索后的地图
"""
	for line in test_map:
		print ''.join(line)

def get_start_XY():
	return get_symbol_XY('S')

def get_end_XY():
	return get_symbol_XY('E')

def get_symbol_XY(s):
	for y, line in enumerate(test_map):
		try:
			x = line.index(s)
		except:
			continue
		else:
			break
	return x, y

#########################################################
def mark_path(l):
	mark_symbol(l, '*')

def mark_searched(l):
	mark_symbol(l, ' ')

def mark_symbol(l, s):
	for x, y in l:
		test_map[y][x] = s

def mark_start_end(s_x, s_y, e_x, e_y):
	test_map[s_y][s_x] = 'S'
	test_map[e_y][e_x] = 'E'

def tm_to_test_map():
	for line in tm:
		test_map.append(list(line))

def find_path():
	s_x, s_y = get_start_XY()
	e_x, e_y = get_end_XY()
	a_star = A_Star(s_x, s_y, e_x, e_y)
	a_star.find_path()
	searched = a_star.get_searched()
	path = a_star.path
	#标记已搜索区域
	mark_searched(searched)
	#标记路径
	mark_path(path)
	print "path length is %d"%(len(path))
	print "searched squares count is %d"%(len(searched))
	#标记开始、结束点
	mark_start_end(s_x, s_y, e_x, e_y)

if __name__ == "__main__":
	#把字符串转成列表
	tm_to_test_map()
	find_path()
	print_test_map()

转载于:https://my.oschina.net/u/659405/blog/94891

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A*算法是一种启发式的搜索算法,用于在图形或网络中找到最短路径。它是基于深度优先算法和广度优先算法的一种融合算法,通过使用启发式函数来评估每个节点的优先级,以确定下一个要扩展的节点。\[2\] 在A*算法中,每个节点都有一个估计的成本,由两部分组成:从起始节点到当前节点的实际成本(g值)和从当前节点到目标节点的估计成本(h值)。通过将这两个成本相加,可以得到一个节点的总成本(f值)。算法会选择具有最低总成本的节点进行扩展,直到找到目标节点或搜索完整个图形。\[1\] A*算法的步骤包括预处理、开始搜索、继续搜索和确定实际路径。在预处理阶段,需要初始化起始节点和目标节点,并计算起始节点的f值。然后,在开始搜索阶段,将起始节点添加到一个优先队列中,并按照f值的顺序进行扩展。在继续搜索阶段,算法会选择具有最低f值的节点进行扩展,并更新其邻居节点的f值。最后,在确定实际路径阶段,可以通过回溯从目标节点到起始节点,以找到最短路径。\[3\] A*算法可以使用Python或C++等编程语言进行实现。在Python中,可以使用优先队列和适当的数据结构来实现A*算法。具体的实现细节可以参考相关的参考资料和代码示例。\[4\] #### 引用[.reference_title] - *1* *2* *3* [【路径规划】全局路径规划算法——A*算法(含python实现 | c++实现)](https://blog.csdn.net/weixin_42301220/article/details/125140910)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值