中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

python 實現A星算法

發布時間:2020-03-12 08:40:23 來源:網絡 閱讀:673 作者:nineteens 欄目:編程語言

  上代碼

  # -*- coding: utf-8 -*-

  # @Date : 2019-12-23 20:53:33

  # @Author : Flying Hu (1152598046@qq.com)

  # @Link : http://www.flyinghu.cn

  # @name : A星算法實現

  # @Version : 0.1

  import os

  import math

  from random import randint

  import time

  # 定義全局變量

  gz_char = '█' # 定義默認格子字符

  fruit_char = '★' # 定義果實顯示字符

  self_char = '●' # 定義自身顯示字符

  wall_char = '◆' # 定義墻壁顯示字符

  # 全程使用上往下方向為x正方向 (二維列表行索引增加方向)

  # 全程使用左往右方向為y正方向 (二維列表列索引增加方向)

  class Map2D(object):

  '''2D地圖類'''

  def __init__(self, width=20, height=20):

  '''初始化

  Args:

  width 地圖寬

  height 地圖高

  '''

  self.width = width

  self.height = height

  self.char = gz_char # 地圖默認字符

  # 生成地圖

  self.map = [[self.char for col in range(

  self.width)] for row in range(self.height)]

  # 生成地圖周圍墻

  self.wall = [[i, j] for j in [-1, self.width] for i in range(self.height)] + [

  [j, i] for j in [-1, self.height] for i in range(-1, self.width + 1)]

  def __getitem__(self, item):

  '''以鍵方式取值'''

  return self.map[item]

  def __setitem__(self, key, value):

  '''以鍵方式存值'''

  self.map[key] = value

  def show(self):

  '''在控制臺打印當前地圖'''

  for row in self.map:

  for c in row:

  # 使用控制臺顏色控制, 區分

  if c == self_char:

  print('\033[1;35;44m' + c + '\033[0m', end='')

  elif c == wall_char:

  print('\033[0;36;41m' + c + '\033[0m', end='')

  elif c == fruit_char:

  print('\033[1;33;40m' + c + '\033[0m', end='')

  else:

  print('\033[0;37;41m' + c + '\033[0m', end='')

  print()

  # 重置地圖, 重置后就不會留下運動軌跡

  # self.reload()

  def reload(self):

  '''重置地圖'''

  self.map = [[self.char for col in range(

  self.width)] for row in range(self.height)]

  class AStar(object):

  '''實現A星算法'''

  class Node(object):

  '''節點類'''

  def __init__(self, x, y, parent_node=None):

  self.x = x

  self.y = y

  self.parent = parent_node # 父節點

  # F = G + H

  # G = 從起點 A 移動到指定方格的移動代價

  # H = 從指定的方格移動到終點 B 的估算成本。試探法。 這里使用 Manhattan 方法估算H

  self.G = 0

  self.H = 0

  def __init__(self, map2D):

  '''初始化'''

  self.map = map2D

  def MinF(self):

  '''從open_list中取出F最小的節點

  Returns:

  minF 返回open_list中F值最小的節點

  '''

  # 先假設第一個為最小, 然后循環挑選出F最小的節點

  minF = self.open_list[0]

  for node in self.open_list:

  if (node.G + node.H) <= (minF.G + minF.H):

  minF = node

  return minF

  def in_close_list(self, x, y):

  '''判斷坐標是否在close_list中

  Args:

  x x坐標

  y y坐標

  Return:

  node 如果坐標在close_list中, 返回該節點, 反之返回False

  '''

  for node in self.close_list:

  if node.x == x and node.y == y:

  return node

  return False

  def in_open_list(self, x, y):

  '''判斷坐標是否在open_list中

  Args:

  x x坐標

  y y坐標

  Return:

  node 如果坐標在open_list中, 返回該節點, 反之返回False

  '''

  for node in self.close_list:

  if node.x == x and node.y == y:

  return node

  return False

  def search(self, node):

  '''搜索周圍路徑

  Args:

  node 搜索節點

  '''

  # 判斷改節點是否為障礙物(障礙物或者墻壁)

  if [node.x, node.y] in self.obstacles:

  # 如果為障礙物則忽略該路徑

  return

  # 判斷是否在close_list中

  if self.in_close_list(node.x, node.y):

  # 如果已經在close_list中則忽略該節點

  return

  # 計算G和H

  node.G = node.parent.G + 10

  node.H = abs(self.target_node.x - node.x) + \

  abs(self.target_node.y - node.y) * 10

  # 判斷是否在open_list中

  tmp = self.in_close_list(node.x, node.y)

  if tmp:

  # 在open_list中

  # 比較當前F和open_list中F

  if (node.G + node.H) < (tmp.G + tmp.H):

  # 如果判斷該路徑F值是否比open_list中存在的相同坐標的F值更小

  tmp = node

  else:

  # 不在open_list中, 向open_list中添加

  self.open_list.append(node)

  def start(self, current_position, target_positiion, obstacles):

  '''計算A星最優路徑

  Args:

  current_position 當前位置坐標

  target_positiion 目標位置坐標

  obstacles 障礙物坐標列表

  Returns:

  path_list 如果存在最優路徑返回A星最優路徑, 反正返回None

  '''

  # 目標節點

  self.target_node = AStar.Node(*target_positiion)

  # 當前節點

  self.current_node = AStar.Node(*current_position)

  # 開啟表, 添加當前節點到open_list中

  self.open_list = [self.current_node]

  # 關閉表

  self.close_list = []

  # 障礙物坐標集 (真實障礙物 + 墻壁)

  self.obstacles = obstacles + self.map.wall

  # 開啟A星計算循環

  while True:

  # 判斷是否到達終點, 判斷目標節點坐標是否在close_list中

  tmp = self.in_close_list(self.target_node.x, self.target_node.y)

  if tmp:

  # 返回路線

  path_list = [[tmp.x, tmp.y]]

  # 逆推路線

  while tmp.parent:

  tmp = tmp.parent

  path_list.append([tmp.x, tmp.y])

  # 反轉列表

  path_list.reverse()

  return path_list

  if not self.open_list:

  # 如果open_list為空, 表示無路可走

  return None

  # 從open_list中選出F最小路徑節點

  minF = self.MinF()

  # 將當前選出節點添加到close_list中, 并從open_list中移除

  self.close_list.append(minF)

  self.open_list.remove(minF)

  # 搜索路徑并將當前節點作為父節點 根據固定順序搜索 (固定就行, 順序任意)

  self.search(AStar.Node(minF.x - 1, minF.y, minF))

  self.search(AStar.Node(minF.x, minF.y - 1, minF))

  self.search(AStar.Node(minF.x + 1, minF.y, minF))

  self.search(AStar.Node(minF.x, minF.y + 1, minF))

  # 存在計算時長比較久的清空, 打印提示信息

  print('\r叼毛, 正在規劃路徑...', end='')

  def sub_start(self, current_position, target_positiion, obstacles, num=20):

  '''限定次數判斷是否有路可走'''

  # 目標節點

  self.target_node = AStar.Node(*target_positiion)

  # 當前節點

  self.current_node = AStar.Node(*current_position)

  # 開啟表, 添加當前節點到open_list中

  self.open_list = [self.current_node]

  # 關閉表

  self.close_list = []

  # 障礙物坐標集 (真實障礙物 + 墻壁)

  self.obstacles = obstacles + self.map.wall

  # 開啟A星計算循環

  for i in range(num):

  # 判斷是否到達終點, 判斷目標節點坐標是否在close_list中

  tmp = self.in_close_list(self.target_node.x, self.target_node.y)

  if tmp:

  # 返回路線

  path_list = [[tmp.x, tmp.y]]

  # 逆推路線

  while tmp.parent:

  tmp = tmp.parent

  path_list.append([tmp.x, tmp.y])

  # 反轉列表

  path_list.reverse()

  return True

  if not self.open_list:

  # 如果open_list為空, 表示無路可走

  return False

  # 從open_list中選出F最小路徑節點

  minF = self.MinF()

  # 將當前選出節點添加到close_list中, 并從open_list中移除

  self.close_list.append(minF)

  self.open_list.remove(minF)

  # 搜索路徑并將當前節點作為父節點 根據固定順序搜索 (固定就行, 順序任意)

  self.search(AStar.Node(minF.x - 1, minF.y, minF))

  self.search(AStar.Node(minF.x, minF.y - 1, minF))

  self.search(AStar.Node(minF.x + 1, minF.y, minF))

  self.search(AStar.Node(minF.x, minF.y + 1, minF))

  else:

  return True

  class Game(object):

  '''game類'''

  def __init__(self, map2D, obs_num=None):

  '''初始化

  Args:

  map2D 2D地圖

  obs_num 初始化障礙物數量

  '''

  self.map = map2D

  self.height = self.map.height

  self.width = self.map.width

  # 隨機一個初始化運動方向

  self.direction = randint(0, 3)

  # 根據地圖大小計算障礙物數量

  # self.obs_num = int(math.sqrt(self.height * self.width))

  self.obs_num = obs_num if obs_num else int(

  math.sqrt(self.height * self.width))

  # 初始化起點

  self.current = [

  randint(int(1/4 * (self.height - 1)),

  int(3/4 * (self.height - 1))),

  randint(int(1/4 * (self.width - 1)),

  int(3/4 * (self.width - 1)))

  ]鄭州婦科醫院 http://www.hnzzkd.com/

  # 生成果實目標

  self.gen_fruit()

  # 生成障礙物

  self.gen_obs()

  def gen_fruit(self):

  '''生成果實'''

  while True:

  # 隨機生成果實坐標

  self.fruit = [randint(0, self.height - 1),

  randint(0, self.width - 1)]

  # 避免果實和起點坐標重合

  if self.fruit != self.current:

  break

  def gen_obs(self):

  '''生成障礙物'''

  self.obs_list = []

  for i in range(self.obs_num):

  while True:

  tmp = [randint(0, self.height - 1), randint(0, self.width - 1)]

  # 避免障礙物和起點或者果實重合

  if tmp != self.current and tmp != self.fruit:

  self.obs_list.append(tmp)

  break

  def move(self):

  '''根據移動方向移動

  0, 1, 2, 3分別對應上, 左, 下, 右

  '''

  if self.direction == 0:

  self.current = [self.current[0] - 1, self.current[1]]

  elif self.direction == 1:

  self.current = [self.current[0], self.current[1] - 1]

  elif self.direction == 2:

  self.current = [self.current[0] + 1, self.current[1]]

  else:

  self.current = [self.current[0], self.current[1] + 1]

  def cls(self):

  '''清空控制臺輸出'''

  os.system('cls')

  def load(self):

  '''加載果實和障礙物'''

  # 加載障礙物

  for row, col in self.obs_list:

  self.map[row][col] = wall_char

  # 加載果實和當前點

  row, col = self.current

  self.map[row][col] = self_char

  row, col = self.fruit

  self.map[row][col] = fruit_char

  def start(self):

  '''開始循環'''

  # 開啟A星

  g = self.a_star()

  # 進入循環

  while True:

  # 清空控制臺輸出

  self.cls()

  # 加載

  self.load()

  # 打印顯示

  self.map.show()

  # 判斷是否吃到果實

  if self.current == self.fruit:

  # 吃到果實

  # 重置地圖

  self.map.reload()

  # 重新生成果實, 重新生成障礙物

  self.gen_fruit()

  self.gen_obs()

  self.map.reload()

  if next(g) is False:

  # 表示無路可走

  # 重置地圖

  self.map.reload()

  continue

  # 移動

  self.move()

  # 控制移動速度

  time.sleep(0.3)

  def a_star(self):

  '''接入A*算法尋路

  使用python生成器方式實現在循環中一次一次改變方向

  '''

  # 創建對象

  a = AStar(self.map)

  while True:

  # 提前加載顯示地圖, 提前顯示可以人工判斷是否真的無路可走

  # 清空控制臺輸出

  self.cls()

  # 加載

  self.load()

  # 打印顯示

  self.map.show()

  # 先反向判斷, 在限定次數中是否得出無路可走, 添加改策略一定程度減少計算時間很長的正向計算

  if a.sub_start(self.fruit, self.current, self.obs_list, 30) is False:

  # 表示無路可走

  input('無路可走, 回車刷新地圖')

  self.map.reload()

  self.gen_fruit()

  self.gen_obs()

  # 返回無路可走信號

  yield False

  continue

  path_list = a.start(self.current, self.fruit, self.obs_list)

  if not path_list:

  # 表示無路可走

  # 提前加載顯示地圖, 提前顯示可以人工判斷是否真的無路可走

  # 清空控制臺輸出

  # self.cls()

  # # 加載

  # self.load()

  # # 打印顯示

  # self.map.show()

  input('無路可走, 回車刷新地圖')

  self.map.reload()

  self.gen_fruit()

  self.gen_obs()

  # 返回無路可走信號

  yield False

  continue

  # 遍歷啟動后路徑, 對比得出行走方向

  for path in path_list[1:]:

  if path[0] > self.current[0]:

  self.direction = 2

  elif path[0] < self.current[0]:

  self.direction = 0

  elif path[1] > self.current[1]:

  self.direction = 3

  else:

  self.direction = 1

  yield

  if __name__ == "__main__":

  # 初始化控制臺大小

  os.system("mode con cols=80 lines=80")

  # 創建地圖

  map2D = Map2D(width=20, height=20)

  # 新建, 指定障礙物

  game = Game(map2D, 150)

  # 打開

  game.start()


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

金寨县| 蛟河市| 清河县| 台山市| 集安市| 屯门区| 玉树县| 邯郸市| 互助| 叶城县| 读书| 吴江市| 广灵县| 留坝县| 利川市| 历史| 察雅县| 滨海县| 玉门市| 玉环县| 镇康县| 峨边| 颍上县| 丹棱县| 乌什县| 南涧| 焉耆| 崇仁县| 郯城县| 商城县| 南昌县| 垫江县| 确山县| 曲阳县| 连山| 甘泉县| 花垣县| 上高县| 报价| 天等县| 平泉县|