A star algorithm to achieve python

  The Code

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

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

  # @Author : Flying Hu ([email protected])

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

  # @Name: A Star algorithm

  # @Version : 0.1

  import os

  import math

  from random import randint

  import time

  # Define global variables

  gz_char = '█' # define default character grid

  fruit_char = '★' # Fruit displaying characters defined

  self_char = '●' # define the display character itself

  wall_char = '◆' # define wall display character

  # Full use of top-down direction as the positive x direction (two-dimensional list row index increased direction)

  # Full use of the left to right direction as the positive y direction (two-dimensional list column index increased direction)

  class Map2D(object):

  '' '2D map class' ''

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

  '''initialization

  Args:

  width wide map

  High height map

  '''

  self.width = width

  self.height = height

  self.char = gz_char # default character map

  # Generate a map

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

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

  # Generate a map surrounding wall

  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):

  '' 'In a manner key value' ''

  return self.map[item]

  def __setitem__(self, key, value):

  '' 'In a key way the value stored in' ''

  self.map[key] = value

  def show(self):

  '' 'Print the map in the console' ''

  for row in self.map:

  for c in row:

  # Using the console color control, distinguish

  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()

  # Reset map after reset will not leave trajectory

  # self.reload()

  def reload(self):

  '' 'Reset map' ''

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

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

  class AStar(object):

  '' 'A Star algorithm to achieve' ''

  class Node(object):

  '' 'Node Class' ''

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

  self.x = x

  self.y = y

  self.parent = parent_node # parent

  # F = G + H

  # G = the cost of moving to the start point A moves from the specified checkered

  # H = estimated cost from the cell to a specified end point B is. Heuristics. As used herein, Manhattan method for estimating H

  self.G = 0

  self.H = 0

  def __init__(self, map2D):

  '''initialization'''

  self.map = map2D

  def MinF(self):

  '' 'Taken from the lowest node F in open_list

  Returns:

  minF Returns the minimum value of the node F in open_list

  '''

  # Assume a first minimum, then the minimum cycle selected node 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):

  '' 'Determines the coordinates are close_list

  Args:

  xx coordinates

  yy coordinates

  Return:

  If the node coordinates close_list, returns the node, otherwise it returns 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):

  '' 'Determines the coordinates are open_list

  Args:

  xx coordinates

  yy coordinates

  Return:

  If the node coordinates open_list, returns the node, otherwise it returns False

  '''

  for node in self.close_list:

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

  return node

  return False

  def search(self, node):

  '' 'Around the path search

  Args:

  node node search

  '''

  # Determines whether the changed node obstacle (obstacle or wall)

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

  # If an obstacle is ignored path

  return

  # Determine whether the close_list

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

  # If you are already close_list in the node is ignored

  return

  G and H # Calculated

  node.G = node.parent.G + 10

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

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

  # Determine whether the open_list

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

  if tmp:

  # In the open_list

  # Compare the current F and F in open_list

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

  If it is judged that the same coordinate # path F value is present in a ratio of open_list smaller value of F

  tmp = node

  else:

  # Open_list not added to the open_list

  self.open_list.append(node)

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

  '' 'A star computing optimal path

  Args:

  current_position current position coordinates

  target_positiion target location coordinates

  obstacles obstacle coordinate list

  Returns:

  path_list If the optimal path exists A star returns to the optimal path, anyway, return None

  '''

  # Target node

  self.target_node = AStar.Node(*target_positiion)

  The current node #

  self.current_node = AStar.Node(*current_position)

  # Open table, add the current node to the open_list

  self.open_list = [self.current_node]

  Close the table #

  self.close_list = []

  # Obstructions set of coordinates (real obstacle + wall)

  self.obstacles = obstacles + self.map.wall

  # A star turn on the calculation cycle

  while True:

  # Determines whether or reaches the end, it is determined whether the target node coordinates in the close_list

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

  if tmp:

  # Return route

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

  Backward Route #

  while tmp.parent:

  tmp = tmp.parent

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

  # Reverse list

  path_list.reverse()

  return path_list

  if not self.open_list:

  # If open_list is blank, no way out

  return None

  F # is selected from the shortest path node in open_list

  minF = self.MinF()

  # Add the currently selected node to close_list in, and removed from the open_list

  self.close_list.append(minF)

  self.open_list.remove(minF)

  # Search path and a search of the current node as a parent node according to a fixed sequence (fixed line, in any order)

  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))

  # When there is a long calculation relatively long empty, print message

  print ( '\ r Diao hair, is planning path ...', end = '')

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

  '' 'Defines a frequency and determining whether there is a road to go' ''

  # Target node

  self.target_node = AStar.Node(*target_positiion)

  The current node #

  self.current_node = AStar.Node(*current_position)

  # Open table, add the current node to the open_list

  self.open_list = [self.current_node]

  Close the table #

  self.close_list = []

  # Obstructions set of coordinates (real obstacle + wall)

  self.obstacles = obstacles + self.map.wall

  # A star turn on the calculation cycle

  for i in range(num):

  # Determines whether or reaches the end, it is determined whether the target node coordinates in the close_list

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

  if tmp:

  # Return route

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

  Backward Route #

  while tmp.parent:

  tmp = tmp.parent

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

  # Reverse list

  path_list.reverse()

  return True

  if not self.open_list:

  # If open_list is blank, no way out

  return False

  F # is selected from the shortest path node in open_list

  minF = self.MinF()

  # Add the currently selected node to close_list in, and removed from the open_list

  self.close_list.append(minF)

  self.open_list.remove(minF)

  # Search path and a search of the current node as a parent node according to a fixed sequence (fixed line, in any order)

  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 class' ''

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

  '''initialization

  Args:

  map2D 2D map

  obs_num initialize the number of obstacles

  '''

  self.map = map2D

  self.height = self.map.height

  self.width = self.map.width

  # Initialize a random direction of movement

  self.direction = randint (0, 3)

  # Calculate the number of obstacles according to the size of the map

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

  self.obs_num obs_num else if obs_num = int (

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

  # Initialize the starting point

  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)))

  ] Zhengzhou gynecological hospital http://www.hnzzkd.com/

  # Fruit generation target

  self.gen_fruit()

  # Generate obstacles

  self.gen_obs()

  def gen_fruit(self):

  '' 'Generates fruit' ''

  while True:

  Fruit # randomly generated coordinate

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

  randint(0, self.width - 1)]

  # Avoid fruit and starting coordinate coincides

  if self.fruit != self.current:

  break

  def gen_obs(self):

  '' 'Generates an obstacle' ''

  self.obs_list = []

  for i in range(self.obs_num):

  while True:

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

  # Avoid obstacles and coincides with the start or fruit

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

  self.obs_list.append(tmp)

  break

  def move(self):

  '' 'Is moved according to the direction of movement

  0, 1, 2, 3 respectively on the left, bottom, right

  '''

  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):

  '' 'Empty console output' ''

  os.system ( 'cis')

  def load(self):

  '' 'Load of fruit and obstacles' ''

  # Load barrier

  for row, col in self.obs_list:

  self.map[row][col] = wall_char

  # Fruit and load current point

  row, col = self.current

  self.map[row][col] = self_char

  row, col = self.fruit

  self.map[row][col] = fruit_char

  def start(self):

  '' 'Start cycle' ''

  # A star turn

  g = self.a_star()

  # Into circulation

  while True:

  # Clear the console output

  self.cls()

  # Load

  self.load()

  # Print display

  self.map.show()

  # Determine whether to eat fruit

  if self.current == self.fruit:

  # Eat fruits

  # Reset map

  self.map.reload()

  # Rebuild fruit, rebuild obstacles

  self.gen_fruit()

  self.gen_obs()

  self.map.reload()

  if next(g) is False:

  # Indicates nowhere

  # Reset map

  self.map.reload()

  continue

  # Mobile

  self.move()

  # Movement speed control

  time.sleep(0.3)

  def a_star(self):

  '' 'A * algorithm access pathfinding

  Use python generator manner in the cycle time and again change direction

  '''

  # Create Object

  a = AStar (self.map)

  while True:

  # Advance to load the map display, you can manually determine in advance whether the display is really nowhere to go

  # Clear the console output

  self.cls()

  # Load

  self.load()

  # Print display

  self.map.show()

  # Reverse first determines whether the number of defined results in no way added to change the policy to some extent reduce the calculation time is long, the forward calculation

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

  # Indicates nowhere

  input ( 'no way, refresh the map Enter')

  self.map.reload()

  self.gen_fruit()

  self.gen_obs()

  # Returned no way signals

  yield False

  continue

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

  if not path_list:

  # Indicates nowhere

  # Advance to load the map display, you can manually determine in advance whether the display is really nowhere to go

  # Clear the console output

  # self.cls()

  # # Load

  # self.load()

  # # Print display

  # self.map.show()

  input ( 'no way, refresh the map Enter')

  self.map.reload()

  self.gen_fruit()

  self.gen_obs()

  # Returned no way signals

  yield False

  continue

  After starting the traversal path # Comparative results running direction

  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__":

  # Initialize console size

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

  # Create a map

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

  # New, designated obstacle

  game = Game(map2D, 150)

  # turn on

  game.start()


Guess you like

Origin blog.51cto.com/14335413/2461204