您的位置:首页 > 汽车 > 时评 > 机器学习与模式识别大作业

机器学习与模式识别大作业

2024/11/16 7:29:15 来源:https://blog.csdn.net/2202_76009199/article/details/139804336  浏览:    关键词:机器学习与模式识别大作业
import plane
# import dense
import numpy as np
from sklearn.cluster import KMeans# 注意行列和xy的转换 应该只用行列 向上为行-1 向左为列-1
# 如果在xy图像里面会上下颠倒,左右不变
# 地图上有三个信息来源,一个是字符地图,一个是带有信息的二维数组,一个是两个基地列表,如果要更新都需要进行修改
# 聚类出来坐标为float64,使用时注意取整
class Data:def __init__(self, filename):#初始化,保存各类信息self.base = []self.basexy = []self.enemybase = []self.enemybasexy = []self.plane = []self.map = []self.mapinfo = []with open(filename, "r") as file:# 第一行保存行列大小信息content = file.readline()sp = content.split()self.row = int(sp[0])self.column = int(sp[1])# 接下来row行保存地图信息for i in range(self.row):self.map.append(file.readline().rstrip("\n"))# 有多少己方基地content = file.readline()self.base_num = int(content)# 己方基地信息for i in range(self.base_num):content = file.readline()sp = content.split()# 分别保存xy坐标self.basexy.append([int(sp[0]), int(sp[1])])content = file.readline()sp = content.split()# 分别保存燃油、导弹、防御、价值self.base.append([int(sp[0]), int(sp[1]), int(sp[2]), int(sp[3])])# 有多少敌方基地content = file.readline()self.enemybase_num = int(content)# 敌方基地信息for i in range(self.enemybase_num):content = file.readline()sp = content.split()# 分别保存xy坐标self.enemybasexy.append([int(sp[0]), int(sp[1])])content = file.readline()sp = content.split()# 分别保存燃油、导弹、防御、价值self.enemybase.append([int(sp[0]), int(sp[1]), int(sp[2]), int(sp[3])])# 有多少架飞机content = file.readline()self.plane_num = int(content)for i in range(self.plane_num):content = file.readline()sp = content.split()# 分别保存xy坐标、油箱容量、最大载弹量self.plane.append([int(sp[0]), int(sp[1]), int(sp[2]), int(sp[3])])#遍历二维数组进行更新操作。hang = 0lie = 0for i in self.map:add = []for j in i:if j == '.':add.append(None)elif j == '*':#己方基地的更新操作for selfbase in range(self.base_num):if self.basexy[selfbase][0] == hang and self.basexy[selfbase][1] == lie:add.append(self.base[selfbase])breakelif j == '#':#地方基地的更新操作for enemybase in range(self.enemybase_num):if self.enemybasexy[enemybase][0] == hang and self.enemybasexy[enemybase][1] == lie:add.append(self.enemybase[enemybase])breaklie += 1lie = 0hang += 1self.mapinfo.append(add)class InstrManager:def __init__(self, filepath):self.filepath = filepathwith open(self.filepath, 'w') as file:  # 清空文件内容file.write("")self.instrs = []# 移动Id飞机,0,1,2,3代表上下左右def move(self, Id, direction):self.instrs.append(" ".join(["move", str(Id), str(direction), "\n"]))# Id飞机攻击方向和次数def attack(self, Id, direction, count):self.instrs.append(" ".join(["attack", str(Id), str(direction), str(count), "\n"]))# Id飞机补充燃油countsdef fuel(self, Id, count):self.instrs.append(" ".join(["fuel", str(Id), str(count), "\n"]))# Id飞机补充导弹countdef missile(self, Id, count):self.instrs.append(" ".join(["missile", str(Id), str(count), "\n"]))def writeinstr(self):with open(self.filepath, 'a') as file:file.writelines(self.instrs)file.write("OK\n")self.instrs = []# 计算聚类中心附近的燃油和导弹储备
def count_resource(data: Data, center, radius):radius = int(radius)fuel_total = 0missile_total = 0# 在半径范围内进行搜索for i in range(max(0, int(center[0]) - radius), min(data.row, int(center[0]) + radius)):for j in range(max(0, int(center[1]) - radius), min(data.column, int(center[1]) + radius)):if abs(i - int(center[0])) + abs(j - int(center[1])) > radius:continue  # 在圆圈范围以外if data.map[i][j] == '*':  # 己方基地fuel_total += data.mapinfo[i][j][0]missile_total += data.mapinfo[i][j][1]return [fuel_total, missile_total]# 进行聚类返回聚类中心以及每架飞机适应的聚类点,想法为聚类中心点的基地更加集中,但还需要各聚类点的燃油和导弹等信息。
#我们使用的是一半燃油。
# 聚类中心油量在减去距离才能得到净油量
def Clustering(data: Data, plane_arr):points = np.array(data.basexy)# 设置聚类的数量# k = data.plane_numk = int(np.log(data.row*data.column))print("分成", k, "类")print("识别距离为:", (data.row+data.column)/k)# 执行k均值聚类kmeans = KMeans(n_clusters=k)kmeans.fit(points)# 获取聚类中心和标签centers = kmeans.cluster_centers_  # 聚类中心点centers = centers.astype(int)labels = kmeans.labels_  # 对应的标签for i in plane_arr:  # 对每架飞机找到最佳加油点和导弹补给点fuel_points = []missile_points = []for j in centers:fuel, missile = count_resource(data, j, (data.row+data.column)/k)fuel -= (abs(j[0]-i.position[0])+abs(j[1]-i.position[1]))fuel_points.append(fuel)missile_points.append(missile)# 为每架飞机找到燃油点和导弹点,注意取整i.fuel_positions = centers[fuel_points.index(max(fuel_points))]i.missile_positions = centers[missile_points.index(max(missile_points))]print("聚类中心:",centers)return centers# 删除无用基地信息
def delete_base(data, position):if data.map[position[0]][position[1]] == '*':  # 己方基地for i in range(data.base_num):  # 遍历己方基地if data.basexy[i][0]==position[0] and data.basexy[i][1]==position[1]:data.basexy.pop(i)data.base.pop(i)data.base_num -= 1breakif data.map[position[0]][position[1]] == '#' or data.map[position[0]][position[1]] == 's':  # 敌方基地for i in range(data.enemybase_num):  # 遍历敌方基地if data.enemybasexy[i][0]==position[0] and data.enemybasexy[i][1]==position[1]:data.enemybasexy.pop(i)data.enemybase.pop(i)data.enemybase_num -= 1breakstr2list = list(data.map[position[0]])str2list[position[1]] = '.'data.map[position[0]] = ''.join(str2list)if __name__ == "__main__":data = Data("data/testcase2.in")sum = 0for i in data.enemybase:sum += i[3]print("总分为:", sum)instr = InstrManager("data/testcase2.out")directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]  # 上下左右# print(data.mapinfo, data.enemybasexy)# 不能飞的飞机can_fly = []# 飞机数组plane_arr = []# 路径数组way = []# 行动数组,0,1,2,3分别为四个方向攻击,4为补给action = []# 记录发射导弹数量missile = []# 记录加燃油和导弹的数量fuel_and_missile = []# 用于删除的临时坐标temp_position = [0, 0]# 删除无用的己方基地和for i in range(data.base_num-1, -1, -1):  # 倒序遍历,防止删除时出现波动if data.base[i][0] == 0 and data.base[i][1] == 0:print("初始删除己方基地:", data.basexy[i])delete_base(data, data.basexy[i])for i in range(data.plane_num):plane_arr.append(plane.plane(data, instr, i))way.append([])action.append([-1])can_fly.append(1)missile.append(0)fuel_and_missile.append([0, 0])fly_index = 0for i in plane_arr:i.add_fuel(min(data.mapinfo[i.position[0]][i.position[1]][0], i.max_fuel))i.add_missile(min(data.mapinfo[i.position[0]][i.position[1]][1], i.max_missile))# print(i.position)# print(i.DFS())nearest_base, base_way, nearest_enemy, enemy_way = i.DFS()if data.mapinfo[nearest_enemy[0]][nearest_enemy[1]][2] > i.missile or 2 * (len(enemy_way) - 1) + len(base_way) > i.fuel:action[fly_index] = 4  # 进行补给way[fly_index] = base_waysupply_fuel = min(data.mapinfo[nearest_base[0]][nearest_base[1]][0], i.max_fuel - i.fuel + len(base_way))supply_missile = min(data.mapinfo[nearest_base[0]][nearest_base[1]][1], i.max_missile - i.missile)fuel_and_missile[fly_index] = [supply_fuel, supply_missile]  # 提前记录补充的燃油和导弹print(f"飞机{i.number}选择补给,寻路:", base_way, "     该基地信息:",data.mapinfo[nearest_base[0]][nearest_base[1]])data.mapinfo[nearest_base[0]][nearest_base[1]][0] -= supply_fueldata.mapinfo[nearest_base[0]][nearest_base[1]][1] -= supply_missileif data.mapinfo[nearest_base[0]][nearest_base[1]][0] == 0 and \data.mapinfo[nearest_base[0]][nearest_base[1]][1] == 0:# 删除己方基地delete_base(data, nearest_base)print("资源耗尽,删除己方基地:", nearest_base)# str_list = list(data.map[nearest_base[0]])  # 字符串不能改,先列表化# str_list[nearest_base[1]] = '.'  # 基地已空# data.map[nearest_base[0]] = ''.join(str_list)  # 修改成功else:  # 能击毁,能回基地action[fly_index] = enemy_way[0]  # 进行攻击# 更新地图,但是要防止寻路出错missile[fly_index] = data.mapinfo[nearest_enemy[0]][nearest_enemy[1]][2]  # 记录需要发射的导弹数str_list = list(data.map[nearest_enemy[0]])  # 字符串不能改,先列表化str_list[nearest_enemy[1]] = 's'  # 防止两个飞机攻击同一目标data.enemybase_num -= 1  # 敌方基地数量减一data.map[nearest_enemy[0]] = ''.join(str_list)  # 修改成功data.mapinfo[nearest_enemy[0]][nearest_enemy[1]] = []  # 击毁,只更新了这两个,别用别的数据del (enemy_way[0])way[fly_index] = enemy_wayprint(f"飞机{i.number}选择攻击,寻路:", enemy_way, f"锁定敌方基地{nearest_enemy}")# print("修改后地图为:")# print(data.map)# print(data.mapinfo)fly_index += 1print("寻路:", way)flag = 1  # 判断是否该结束frame = 1  # 只能15000帧while flag == 1 and frame <= 15000:print("frame====>>>", frame)flag = 0# 对每个飞机执行命令,若没有命令则创造命令for j in range(data.plane_num):if can_fly[j] == 0:continuei = plane_arr[j]if not way[j]:  # 已经到达if action[j] == 4:  # 补给i.add_fuel(fuel_and_missile[j][0])i.add_missile(fuel_and_missile[j][1])flag = 1else:  # 攻击i.attack_missiles(action[j], missile[j])temp_position[0] = i.position[0] + directions[action[j]][0]temp_position[1] = i.position[1] + directions[action[j]][1]delete_base(data, temp_position)# str_list = list(data.map[i.position[0] + directions[action[j]][0]])  # 字符串不能改,先列表化# str_list[i.position[1] + directions[action[j]][1]] = '.'  # 防止两个飞机攻击同一目标# data.map[i.position[0] + directions[action[j]][0]] = ''.join(str_list)  # 基地已经被击毁# print(f"{i.number}飞机位置:{i.position}")# print(f"修改了:{i.position[0]+directions[action[j]][0],i.position[1]+directions[action[j]][1]}")# print("当前地图为:")# print(data.map)# print(data.mapinfo)flag = 1nearest_base, base_way, nearest_enemy, enemy_way = i.DFS()  # 重新检索if nearest_enemy is None or nearest_base is None:print(f"{i.number}飞机已经不能飞了")can_fly[j] = 0continueprint("最近的己方基地:", nearest_base, "                      最近的敌方基地:", nearest_enemy)if data.mapinfo[nearest_enemy[0]][nearest_enemy[1]][2] > i.missile or 2 * (len(enemy_way) - 1) + len(base_way) > i.fuel:action[j] = 4  # 进行补给way[j] = base_waysupply_fuel = min(data.mapinfo[nearest_base[0]][nearest_base[1]][0],i.max_fuel - i.fuel + len(base_way))supply_missile = min(data.mapinfo[nearest_base[0]][nearest_base[1]][1], i.max_missile - i.missile)fuel_and_missile[j] = [supply_fuel, supply_missile]  # 提前记录补充的燃油和导弹print(f"飞机{i.number}选择补给,寻路:", base_way, "     该基地信息:",data.mapinfo[nearest_base[0]][nearest_base[1]])data.mapinfo[nearest_base[0]][nearest_base[1]][0] -= supply_fueldata.mapinfo[nearest_base[0]][nearest_base[1]][1] -= supply_missileif data.mapinfo[nearest_base[0]][nearest_base[1]][0] == 0 and \data.mapinfo[nearest_base[0]][nearest_base[1]][1] == 0:# 删除己方基地delete_base(data, nearest_base)print("资源耗尽,删除己方基地:", nearest_base)# str_list = list(data.map[nearest_base[0]])  # 字符串不能改,先列表化# str_list[nearest_base[1]] = '.'  # 基地已空# data.map[nearest_base[0]] = ''.join(str_list)  # 修改成功else:  # 能击毁,能回基地action[j] = enemy_way[0]  # 进行攻击# 更新地图,但是要防止寻路出错missile[j] = data.mapinfo[nearest_enemy[0]][nearest_enemy[1]][2]  # 记录需要发射的导弹数str_list = list(data.map[nearest_enemy[0]])  # 字符串不能改,先列表化str_list[nearest_enemy[1]] = 's'  # 防止两个飞机攻击同一目标data.enemybase_num -= 1  # 敌方基地数量减一data.map[nearest_enemy[0]] = ''.join(str_list)  # 修改成功data.mapinfo[nearest_enemy[0]][nearest_enemy[1]] = []  # 击毁,只更新了这两个,别用别的数据del (enemy_way[0])way[j] = enemy_wayprint(f"飞机{i.number}选择攻击,寻路:", enemy_way, f"锁定敌方基地{nearest_enemy}")else:i.move(way[j].pop())  # 移动flag = 1instr.writeinstr()frame += 1if frame == 3000:print("3000帧地图为:")for i in range(data.row):print(data.map[i])break

这段代码是初始化的代码,在data类中,主要内容是解析游戏相关配置,从指定文件中读取并解析游戏相关配置信息,包括地图尺寸,地图内容,玩家信息,敌方基地和飞机信息,并将这些信息组织成易于处理的数据结构。

第二个类用于管理飞行器的各种指令操作,并将这些指令写到指定的文件中。

下面是count_resource函数,作用是计算并返回在给定半径范围内所有的己方基地的总燃油量和总导弹量。通过遍历地图信息,累加基地的燃油和导弹资源。

然后是Clustering函数,功能是聚类作用,计算出聚类中心和识别距离。
对己方基地进行聚类是为了确定潜在补给中心点,。对于每架飞机遍历所有聚类点,利用count_resource函数计算出每个中心点周围的资源总量,并减去到达该点的距离成本(直线距离)的一半燃油消耗,以评估收益,收益大的优先。为每架飞机分配最佳的加油点和导弹补给点,即在啊所有聚类中心中选择燃油和导弹资源净收益最大的点。返回聚类中心点列表,同时修改飞机对象的属性(fuel_positions和missile_positions)指定每架飞机的最优补给点。

下面的delete_base函数目的是从给定的游戏数据结构data中删除位于特定position的基地,更新相关数据结构以反映这一变化。
删除无用的己方基地的原则是检查基地的资源是否是0,如果是进行删除,删除无用的敌方基地同理,如果被摧毁,删除敌方基地。

实现过程中,循环创建飞机对象,添加到plane_arr中,并为每架飞机计算最近的己方基地,敌方基地的路径。根据飞机状态决定是攻击敌方基地还是返回己方基地进行补给,并更新相关的变量。

飞机执行行动,对于每一帧都进行状态的更新。同时进行地图的管理,当飞机攻击敌方基地时,更新地图信息表示基地被摧毁,并减少敌方基地总数。
若飞机补给耗尽,同样删除该基地信息。


import numpy as np
import queue
import heapqclass Node:def __init__(self, x, y, g=0, h=0, f=0, com_dir=None, parent=None):self.x = xself.y = yself.g = g  # 从起点到该结点self.h = h  # 从该节点到终点self.f = f  # 总花费self.com_dir = com_dir  # 上一个结点到该结点选择的前进方向self.parent = parent  # 上一个结点def __lt__(self, other):  # 用于最小堆的计算return self.f < other.fdef heuristic(node, end):return abs(node.x - end.x) + abs(node.y - end.y)  # 启发函数计算曼哈顿距离class plane:def __init__(self, Data, InstrManager, number):self.Data = Dataself.number = numberself.InstrManager = InstrManagerself.position = self.Data.plane[number][:2]  # 同样是行列而不是xyself.max_fuel = self.Data.plane[number][2]self.max_missile = self.Data.plane[number][3]self.fuel = 0self.missile = 0self.fuel_positions = None  # 补充燃油地点self.missile_positions = None  # 补充导弹地点self.fuel_base_arr = []  # 记录加油的节点,防止来回跑,传进来己方基地的位置# 广度优先算法,寻找最进敌方基地和己方基地,并返回路径def DFS(self):DFS_map = [[-1 for i in range(self.Data.column)] for i in range(self.Data.row)]open_list = queue.Queue()open_list.put(self.position)direction = [[-1, 0], [1, 0], [0, -1], [0, 1]]  # 上下左右visited = [self.position]DFS_map[self.position[0]][self.position[1]] = -2  # 起点为-2flag = 0nearest_enemy = Noneenemy_way = []nearest_base = Nonebase_way = []while not open_list.empty():node = open_list.get()for i in range(len(direction)):x, y = [node[0] + direction[i][0], node[1] + direction[i][1]]if 0 <= x < self.Data.row and 0 <= y < self.Data.column and [x, y] not in visited:if self.Data.map[x][y] == 's':continueelif self.Data.map[x][y] == '#':if nearest_enemy is None:nearest_enemy = [x, y]flag += 1xx, yy, ii = x, y, iwhile DFS_map[xx][yy] != -2:enemy_way.append(ii)xx = xx - direction[ii][0]yy = yy - direction[ii][1]ii = DFS_map[xx][yy]else:if self.Data.map[x][y] == '*' and nearest_base is None:nearest_base = [x, y]flag += 1xx, yy, ii = x, y, iwhile DFS_map[xx][yy] != -2:base_way.append(ii)xx = xx - direction[ii][0]yy = yy - direction[ii][1]ii = DFS_map[xx][yy]DFS_map[x][y] = ivisited.append([x, y])open_list.put([x, y])if flag == 2:return nearest_base, base_way, nearest_enemy, enemy_wayif nearest_enemy:return None, None, nearest_enemy, enemy_wayelif nearest_base:return nearest_base, base_way, None, Noneelse:return None, None, None, None# 广搜找燃油,返回有到达后有燃油盈余的那个基地,返回最近的基地坐标以及路径def WFS_for_fuel(self):DFS_map = [[-1 for i in range(self.Data.column)] for i in range(self.Data.row)]open_list = queue.Queue()open_list.put(self.position)direction = [[-1, 0], [1, 0], [0, -1], [0, 1]]  # 上下左右visited = [self.position]DFS_map[self.position[0]][self.position[1]] = -2  # 起点为-2base_way = []while not open_list.empty():node = open_list.get()for i in range(len(direction)):x, y = [node[0] + direction[i][0], node[1] + direction[i][1]]if 0 <= x < self.Data.row and 0 <= y < self.Data.column and [x, y] not in visited:if self.Data.map[x][y] == 's' or self.Data.map[x][y] == '#':  # 碰到敌方基地直接跳过continueelif self.Data.map[x][y] == '*' and self.Data.mapinfo[x][y][0] > 0:  # 燃油不为空if self.Data.mapinfo[x][y][0]-abs(x-self.position[0])-abs(y-self.position[1]) > 0:  # 有燃油盈余nearest_base = [x, y]xx, yy, ii = x, y, iwhile DFS_map[xx][yy] != -2:base_way.append(ii)xx = xx - direction[ii][0]yy = yy - direction[ii][1]ii = DFS_map[xx][yy]return nearest_base, base_wayDFS_map[x][y] = ivisited.append([x, y])open_list.put([x, y])return None# 广搜找导弹,返回最近有导弹的那个基地,返回最近的基地坐标以及路径def WFS_for_missile(self):DFS_map = [[-1 for i in range(self.Data.column)] for i in range(self.Data.row)]open_list = queue.Queue()open_list.put(self.position)direction = [[-1, 0], [1, 0], [0, -1], [0, 1]]  # 上下左右visited = [self.position]DFS_map[self.position[0]][self.position[1]] = -2  # 起点为-2base_way = []while not open_list.empty():node = open_list.get()for i in range(len(direction)):x, y = [node[0] + direction[i][0], node[1] + direction[i][1]]if 0 <= x < self.Data.row and 0 <= y < self.Data.column and [x, y] not in visited:if self.Data.map[x][y] == 's' or self.Data.map[x][y] == '#':  # 碰到敌方基地直接跳过continueelif self.Data.map[x][y] == '*' and self.Data.mapinfo[x][y][1] > 0:  # 导弹不为空nearest_base = [x, y]xx, yy, ii = x, y, iwhile DFS_map[xx][yy] != -2:base_way.append(ii)xx = xx - direction[ii][0]yy = yy - direction[ii][1]ii = DFS_map[xx][yy]return nearest_base, base_wayDFS_map[x][y] = ivisited.append([x, y])open_list.put([x, y])return None# A*算法,找到到达目标的最近路径def A_star(self, target):start_node = Node(self.position[0], self.position[1])  # 生成起点和终点end_node = Node(target[0], target[1])direction = [[-1, 0], [1, 0], [0, -1], [0, 1]]  # 上下左右visited = [self.position]  # 元素为二维坐标open_list = []heapq.heappush(open_list, start_node)path = []while open_list:current_node = heapq.heappop(open_list)visited.append([current_node.x, current_node.y])if current_node.x == end_node.x and current_node.y == end_node.y:  # 到达终点while current_node != start_node:  # python中的等号比较的是内存地址path.append(current_node.com_dir)  # 记录路径current_node = current_node.parent  # 到上一个结点return pathelse:  # 未到达终点for i in range(len(direction)):neighbor_x = current_node.x + direction[i][0]neighbor_y = current_node.y + direction[i][1]if 0 <= neighbor_x < self.Data.row and 0 <= neighbor_y < self.Data.column and [neighbor_x, neighbor_y] not in visited and (self.Data.map[neighbor_x][neighbor_y]=='*' or self.Data.map[neighbor_x][neighbor_y]=='.'):neighbor_node = Node(neighbor_x, neighbor_y, g=current_node.g+1, com_dir=i, parent=current_node)neighbor_node.h = heuristic(neighbor_node, end_node)neighbor_node.f = neighbor_node.g+neighbor_node.h  # 计算距离heapq.heappush(open_list, neighbor_node)return None# 返回离position最近的敌方基地的位置以及距离,重载def search_nearest_enemy(self, position):dist = []for i in self.Data.enemybasexy:dist.append(abs(i[0] - position[0]) + abs(i[1] - position[1]))return [self.Data.enemybasexy[np.argmin(dist)], min(dist)]# 返回离position最近的基地的位置以及距离def serch_nearest_base(self, position):dist = []for i in self.Data.basexy:dist.append(abs(i[0] - position[0]) + abs(i[1] - position[1]))return [self.Data.basexy[np.argmin(dist)], min(dist)]# 判断是否可继续飞,若可以则返回加油最多的地方和净加油数def able2fly(self):dist = []index = 0for i in self.Data.basexy:# 计算去基地加油后的燃油余额dist.append(self.Data.base[index] + self.fuel - (i[0] - self.position[0]) + abs(i[1] - self.position[1]))index += 1return [self.Data.basexy[np.argmax(dist)], max(dist)]# 向目标前进一步,优先向上或向下移动,没有进行碰撞检测,没有将飞机变化赋值给Datadef target_one_step(self, position):if self.position[0] > position[0]:# 向上走一步self.InstrManager.move(self.number, 0)self.position[0] = self.position[0] - 1elif self.position[0] < position[0]:# 向下走一步self.InstrManager.move(self.number, 1)self.position[0] = self.position[0] + 1else:if self.position[1] > position[1]:# 向左一步self.InstrManager.move(self.number, 2)self.position[1] = self.position[1] - 1elif self.position[1] < position[1]:# 向右一步self.InstrManager.move(self.number, 3)self.position[1] = self.position[1] + 1self.fuel = self.fuel - 1# 向某个方向移动,燃料减少def move(self, direction):print(self.number, "飞机移动,方向:", direction)self.InstrManager.move(self.number, direction)directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]  # 上下左右self.position[0] += directions[direction][0]self.position[1] += directions[direction][1]self.fuel -= 1# 向某方向发射导弹,在外面进行数量检测,没有更新地图,在外面进行更新def attack_missiles(self, direction, missiles):print(self.number, "飞机发射导弹,方向:", direction, "  导弹数量:", missiles)self.InstrManager.attack(self.number, direction, missiles)self.missile = self.missile - missiles# 补充燃油def add_fuel(self, fuels):print(self.number, "飞机补充燃油", fuels)self.InstrManager.fuel(self.number, fuels)self.fuel = self.fuel + fuels# 补充导弹def add_missile(self, missiles):print(self.number, "飞机补充导弹", missiles)self.InstrManager.missile(self.number, missiles)self.missile = self.missile + missiles# if __name__ == "__main__":
#     data = pythonIn.Data("testcase1.in")
#     instr = pythonIn.InstrManager("testcase1.out")
#     plane_arr = []
#     for i in range(data.plane_num):
#         plane_arr.append(plane(data, instr, i))
#     print("plane[0]的坐标为:", plane_arr[0].position)
#     for i in data.enemybasexy:
#         print("当前敌方基地:", i)
#         print("寻路为:",plane_arr[0].A_star(i))

Node类,一个典型的A*算法。

启发式函数计算曼哈顿距离。

plane类初始化时将信息实例化。
使用深度优先搜索实现寻找最近的地方基地和己方基地,并返回实现这两个目标的路径。

深度优先搜用到的是栈结构。

过程是:从当前飞机位置开始,按照上下左右四个方向递归搜索地图,遇到障碍物(被摧毁的地方基地)跳过,遇到敌方基地或者己方基地记录并构建新的路径。
使用DFS_map记录每个位置的访问顺序,以便回溯生成路径。

当地方基地和己方基地都找到的时候返回结果。如果循环结束或者未找到二者之一,则根据找到的目标返回响应的结果。
说是BFS也没错,因为使用了队列来进行层次遍历。但是回溯更像是DFS。

进行 燃油和导弹搜索同理,以燃油搜索为例,创建一个二维数组DFS_map来记录地图状态,base_way用于存储到达最近基地的路径指示。
当队列非空时,从队列中取出一个节点进行处理,遍历当前节点的四个相邻位置,针对每个相邻位置,进行越界检查,检查是否有充分的燃油供给(计算当前位置到基地的距离,确保基地燃油减去当前位置之后仍然》0)。

进行导弹检查类似,但是可用导弹数量>0即可。满足条件加入访问队列。

A*算法实现路径查找功能,在给定地图上找到从当前位置到目标位置的最短路径。判断当前节点的坐标和目标节点的坐标是否相同,如果相同,通过回溯构建路径path,记录每个结点的移动方向。返回找到的路径path,如果未到达终点,创建一个邻居节点。如果open_list为空,说明已探索所有可能路径但是没有找到目标,返回None。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com