84 lines
3.9 KiB
Python
84 lines
3.9 KiB
Python
|
from data_structure import Tree
|
|||
|
|
|||
|
class Ai:
|
|||
|
def __init__(self):
|
|||
|
self.path = []
|
|||
|
|
|||
|
def start(self,snake,apple,settings):
|
|||
|
openlist = []
|
|||
|
closelist = []
|
|||
|
starting_point = snake.coords[0]
|
|||
|
ending_point = apple.coords
|
|||
|
|
|||
|
|
|||
|
def calculate_f():
|
|||
|
"""计算openlist各格子的f值"""
|
|||
|
for cell in openlist:
|
|||
|
g = abs(cell['x'] - starting_point['x']) + abs(cell['y'] - starting_point['y'])
|
|||
|
h = abs(cell['x'] - ending_point['x']) + abs(cell['y'] - ending_point['y'])
|
|||
|
f = g + h
|
|||
|
cell['f'] = f
|
|||
|
|
|||
|
|
|||
|
def is_wall():
|
|||
|
# 碰到左右墙壁
|
|||
|
if (cell['x'] == -1 or cell['x'] == settings.cell_w):
|
|||
|
return True
|
|||
|
# 碰到上下墙壁
|
|||
|
if (cell['y'] == -1 or cell['y'] == settings.cell_h):
|
|||
|
return True
|
|||
|
# 碰到自己
|
|||
|
if (cell in snake.coords[1:]):
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
|
|||
|
#记得做openlist用尽、苹果在蛇里面的解决办法
|
|||
|
while ending_point not in openlist:
|
|||
|
if not openlist:
|
|||
|
openlist.append(starting_point)
|
|||
|
path_tree = Tree(starting_point)
|
|||
|
#查找Openlist中F最小的格子并弹入Closelist
|
|||
|
#《这里也有问题 假设下面出现的列表同步更改的错误解决了》
|
|||
|
#《那么本来就被计算过的格子不需要再次计算 但这里依然算了》
|
|||
|
calculate_f()
|
|||
|
min_f = min(f['f'] for f in openlist)
|
|||
|
for cell in openlist:
|
|||
|
if cell['f'] == min_f:
|
|||
|
closelist.append(cell)
|
|||
|
openlist.remove(cell)
|
|||
|
break
|
|||
|
#《这里有问题 不应该for 应该只检查刚丢进closelist的那一个》
|
|||
|
#《检查过的格子又检查一遍 也是openlist有重复格子的根本原因》
|
|||
|
for close_cell in closelist:
|
|||
|
near_cells = [{'x': close_cell['x'], 'y': close_cell['y'] + 1}, #获取旁边的格子上右下左
|
|||
|
{'x': close_cell['x'] + 1, 'y': close_cell['y']},
|
|||
|
{'x': close_cell['x'], 'y': close_cell['y'] - 1},
|
|||
|
{'x': close_cell['x'] - 1, 'y': close_cell['y']}]
|
|||
|
#不考虑蛇的身体或墙壁
|
|||
|
for cell in near_cells:
|
|||
|
if is_wall():
|
|||
|
near_cells.remove(cell)
|
|||
|
#排除F键值对的影响
|
|||
|
#《?为什么使用切片后copy的更改还是能影响到原openlist?》
|
|||
|
#《搞得我openlist的f值全弹出了》
|
|||
|
openlist_copy = openlist[:]
|
|||
|
for cell_copy in openlist_copy:
|
|||
|
cell_copy.pop('f',None)
|
|||
|
#找出不在openlist的格子并加进openlist
|
|||
|
#《filter疑似用错 没有筛选功能 openlist依然有重复格子》
|
|||
|
not_in_list = filter(lambda x: x != (cell_copy for cell_copy in openlist_copy), near_cells)
|
|||
|
openlist.extend(not_in_list)
|
|||
|
#《这里再用一次filter查教程后是因为filter只能迭代一次》
|
|||
|
#《filter好jb难用 我是因为看它性能消耗少才用的QAQ 换一个吧》
|
|||
|
not_in_list = filter(lambda x: x != (cell_copy for cell_copy in openlist_copy), near_cells)
|
|||
|
|
|||
|
#《这里的添加节点能运行但是加不进去 只有一开始的父节点加得进去》
|
|||
|
for not_in_cell in not_in_list:
|
|||
|
path_tree.add_child(path_tree.find(close_cell),not_in_cell)
|
|||
|
|
|||
|
|
|||
|
ending_nodes = path_tree.find(ending_point)
|
|||
|
for node in ending_nodes.get_ancestors()[::-1]:
|
|||
|
self.path.append(node)
|
|||
|
self.iterator = snake.create_iterator(self.path)
|