1 Star 0 Fork 0

tpig / path-finding

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
map_editor.py 12.28 KB
一键复制 编辑 原始数据 按行查看 历史
tpig 提交于 2023-03-19 23:57 . ..
import copy
import sys
import pickle
from enum import Enum
from queue import Queue, PriorityQueue
import pygame
from setting import *
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
import logging
logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#生成日志句柄
# logger = logging.getLogger("wqbin")
logging.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
sys.setrecursionlimit(15000)
print(sys.getrecursionlimit())
class MapType(Enum):
BLANK = 0
TREE = 1
WALL = 2
GIFT = 3
map_data = []
pen_type = MapType.BLANK
path = []
start_image = pygame.image.load("img/soldier.png")
start_image = pygame.transform.scale(start_image, (GRID_SIZE, GRID_SIZE))
target_image = pygame.image.load("img/star2.png")
target_image = pygame.transform.scale(target_image, (GRID_SIZE, GRID_SIZE))
def init_map_data():
map_data.clear()
row_num = SCREEN_HEIGHT // GRID_SIZE
col_num = SCREEN_WIDTH // GRID_SIZE
for r in range(row_num):
line = []
for c in range(col_num):
line.append(MapType.BLANK.value)
map_data.append(line)
def draw_grid():
for row in range(1, SCREEN_HEIGHT // GRID_SIZE):
pygame.draw.line(screen, "skyblue",
(0, row * GRID_SIZE), (SCREEN_WIDTH, row * GRID_SIZE))
for col in range(1, SCREEN_WIDTH // GRID_SIZE):
pygame.draw.line(screen, "skyblue",
(col * GRID_SIZE, 0), (col * GRID_SIZE, SCREEN_HEIGHT))
def draw_map():
cell_color = "green"
for row_index, row in enumerate(map_data):
for col_index, cell in enumerate(row):
if cell == MapType.TREE.value:
cell_color = "green"
if cell == MapType.WALL.value:
cell_color = "orange"
if cell == MapType.GIFT.value:
cell_color = "purple"
if cell is not MapType.BLANK.value:
pygame.draw.rect(screen, cell_color,
(col_index * GRID_SIZE + 1, row_index * GRID_SIZE + 1, GRID_SIZE - 2, GRID_SIZE - 2))
def draw_icon():
mx, my = pygame.mouse.get_pos()
row = my // GRID_SIZE
col = mx // GRID_SIZE
pen_color = "darkgreen"
pygame.draw.rect(screen, "yellow",
(col * GRID_SIZE, row * GRID_SIZE, GRID_SIZE, GRID_SIZE), 2)
if pen_type is MapType.TREE:
pen_color = "green"
if pen_type is MapType.WALL:
pen_color = "orange"
if pen_type is MapType.GIFT:
pen_color = "purple"
if pen_type is MapType.BLANK:
pen_color = "darkgreen"
pygame.draw.rect(screen, pen_color,
(col * GRID_SIZE + 2, row * GRID_SIZE + 2,
GRID_SIZE - 4, GRID_SIZE - 4))
def draw_start():
screen.blit(start_image, (g_start_pos[1] * GRID_SIZE, g_start_pos[0] * GRID_SIZE))
def draw_target():
screen.blit(target_image, (g_target_pos[1] * GRID_SIZE, g_target_pos[0] * GRID_SIZE))
def draw_path():
for point in path:
pygame.draw.circle(screen, "skyblue",
(point[1] * GRID_SIZE + GRID_SIZE // 2, point[0] * GRID_SIZE + GRID_SIZE // 2),
GRID_SIZE // 7)
# ------------- ---------------------
init_map_data()
map_data[2][5] = MapType.WALL.value
map_data[3][1] = MapType.TREE.value
map_data[4][ 4] = MapType.GIFT.value
print(map_data)
# ------------- FIND PATH ---------------------
def is_right_blank(pos, map):
# logging.info("[->] check right.")
if pos[1] >= SCREEN_WIDTH // GRID_SIZE - 1:
return False
cell = map[pos[0]][pos[1] + 1]
if cell == 0:
return True
else:
return False
def is_up_blank(pos, map):
# logging.info("[^] check up.")
if pos[0] <= 0:
return False
cell = map[pos[0] - 1][pos[1]]
if cell == 0:
return True
else:
return False
def is_left_blank(pos, map):
# logging.info("[<-] check left.")
if pos[1] <= 0:
return False
cell = map[pos[0]][pos[1] - 1]
if cell == 0:
return True
else:
return False
def is_down_blank(pos, map):
# logging.info("[v] check down.")
if pos[0] >= SCREEN_HEIGHT // GRID_SIZE - 1:
return False
cell = map[pos[0] + 1][pos[1]]
if cell == 0:
return True
else:
return False
# 查找邻居
def get_neighbors(pos):
row, col = pos
neighbors = []
if is_right_blank(pos, map_data):
neighbors.append((row, col + 1))
if is_up_blank(pos, map_data):
neighbors.append((row - 1, col))
if is_left_blank(pos, map_data):
neighbors.append((row, col - 1))
if is_down_blank(pos, map_data):
neighbors.append(((row + 1, col)))
return neighbors
# 递归寻路,深度优先
def find_path_recursion(start_pos, target_pos, exp_map, path, dir):
logging.info(f"{start_pos} ...")
find_num = 0
updown = "up" if g_start_pos[0] >= g_target_pos[0] else "down"
print(updown)
# 如果 start_pos == target_pos ,返回
if start_pos[0] == target_pos[0] and start_pos[1] == target_pos[1]:
return True
# 如果上下左右都是障碍,则将 start_pos 标成障碍
#
# 如果右边是空地,将该地加入路径, 向右找路, 将该地从路径删除
if is_right_blank(start_pos, exp_map) and dir != "left":
next_pos = (start_pos[0], start_pos[1] + 1)
path.append(next_pos)
if find_path_recursion(next_pos, target_pos, exp_map, path, "right"):
return True
else:
exp_map[next_pos[0]][next_pos[1]] = -1
path.pop()
find_num += 1
else:
find_num += 1
# 如果上边是空地,将该地加入路径, 向右找路, 将该地从路径删除
if updown == "up":
if is_up_blank(start_pos, exp_map) and dir != "down":
next_pos = (start_pos[0] - 1, start_pos[1])
path.append(next_pos)
if find_path_recursion(next_pos, target_pos, exp_map, path, "up"):
return True
else:
path.pop()
exp_map[next_pos[0]][next_pos[1]] = -1
find_num += 1
else:
find_num += 1
# 如果下边是空地,将该地加入路径, 向下找路, 将该地从路径删除
if updown == "down":
if is_down_blank(start_pos, exp_map) and dir != "up":
next_pos = (start_pos[0] + 1, start_pos[1])
path.append(next_pos)
if find_path_recursion(next_pos, target_pos, exp_map, path, "down"):
return True
else:
exp_map[next_pos[0]][next_pos[1]] = -1
path.pop()
find_num += 1
else:
find_num += 1
# 如果左边是空地,将该地加入路径, 向左找路, 将该地从路径删除
if is_left_blank(start_pos, exp_map) and dir != "right":
next_pos = (start_pos[0], start_pos[1] - 1)
path.append(next_pos)
if find_path_recursion(next_pos, target_pos, exp_map, path, "left"):
return True
else:
exp_map[next_pos[0]][next_pos[1]] = -1
path.pop()
find_num += 1
else:
find_num += 1
# 如果上下左右都没路,将该地标成障碍
logging.info(find_num)
if find_num == 4:
exp_map[start_pos[0]][start_pos[1]] = -1
print(f"{start_pos} set to -1")
return False
# 广度优先算法
def find_path_breadth_first(start_pos, target_pos):
path = []
frontier = Queue()
frontier.put(start_pos)
# reached = set()
# reached.add(start_pos)
came_from = dict()
came_from[start_pos] = None
while not frontier.empty():
current = frontier.get()
# early exit
if current == target_pos:
break
for next in get_neighbors(current):
# if next not in reached:
if next not in came_from:
frontier.put(next)
# reached.add(next)
came_from[next] = current
current = target_pos
while current != start_pos:
path.append(current)
current = came_from.get(current)
if not current:
break
path.append(start_pos)
path.reverse()
return path
# 贪心算法
def heuristic(pos_a, pos_b):
return abs(pos_a[0] - pos_b[0]) + abs(pos_a[1] - pos_b[1])
# return (pos_a[0] - pos_b[0])**2 + (pos_a[1] - pos_b[1])**2
def find_path_greedy_best_first(start_pos, target_pos):
frontier = PriorityQueue()
frontier.put((0, start_pos))
came_from = dict()
came_from[start_pos] = None
while not frontier.empty():
current_with_priority = frontier.get()
current = current_with_priority[1]
print(current)
if current == target_pos:
break
for next in get_neighbors(current):
print(next)
if next not in came_from:
priority = heuristic(target_pos, next)
frontier.put((priority, next))
came_from[next] = current
# path
path = []
current = target_pos
while current != start_pos:
path.append(current)
current = came_from.get(current)
if not current:
break
path.append(start_pos)
path.reverse()
return path
# ------------- START ---------------------
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
pygame.display.set_caption("地图编辑器")
# pygame.mouse.set_visible(False)
running = True
while running:
# event
event_list = pygame.event.get()
for e in event_list:
if e.type == pygame.QUIT:
running = False
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_0 or e.key == pygame.K_KP0:
pen_type = MapType.BLANK
if e.key == pygame.K_1 or e.key == pygame.K_KP1:
pen_type = MapType.TREE
if e.key == pygame.K_2 or e.key == pygame.K_KP2:
pen_type = MapType.WALL
if e.key == pygame.K_3 or e.key == pygame.K_KP3:
pen_type = MapType.GIFT
if e.key == pygame.K_s:
print("save map")
root = tk.Tk()
root.overrideredirect(True)
root.attributes("-alpha", 0)
file_name = asksaveasfilename(
defaultextension="*.dat",
filetypes=[("Map file", "*.dat")])
root.destroy()
with open(file_name, "wb") as f:
pickle.dump(map_data, f)
if e.key == pygame.K_l:
print("load map")
# with open("map.dat", "rb") as f:
# map_data = pickle.load(f)
root = tk.Tk()
root.overrideredirect(True)
root.attributes("-alpha", 0)
file_name = askopenfilename(filetypes=[("Map file", "*.dat")])
root.destroy()
if file_name:
with open(file_name, "rb") as f:
map_data = pickle.load(f)
if e.key == pygame.K_c:
init_map_data()
if e.key == pygame.K_g:
print("go go go ~~")
path.clear()
print(path)
"""调用递归寻路算法"""
# exp_map = copy.deepcopy(map_data)
# exp_map[g_start_pos[0]][g_start_pos[1]] = -1
# find_path_recursion(g_start_pos, g_target_pos, exp_map, path, "begin")
"""调用广度优先算法"""
ps = find_path_breadth_first(g_start_pos, g_target_pos)
"""调用贪婪寻路"""
# ps = find_path_greedy_best_first(g_start_pos, g_target_pos)
for p in ps:
path.append(p)
print("After gone:")
print(path)
# update
if(pygame.mouse.get_pressed(3)[0] == 1):
mx, my = pygame.mouse.get_pos()
row = my // GRID_SIZE
col = mx // GRID_SIZE
map_data[row][col] = pen_type.value
# draw
screen.fill("darkgreen")
draw_grid()
draw_map()
draw_icon()
draw_start()
draw_target()
draw_path()
pygame.display.flip()
# fps
clock.tick(FPS)
pygame.quit()
sys.exit()
Python
1
https://gitee.com/tpig/path-finding.git
git@gitee.com:tpig/path-finding.git
tpig
path-finding
path-finding
First_Step

搜索帮助