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

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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/30469.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10 种语言文本准确渲染;Mac无需联网的本地聊天应用;多模态语言模型(MLM)基准测试的引擎;Yolo DotNet版本

✨ 1: Glyph-ByT5 10 种语言文本准确渲染&#xff0c;将文本渲染的准确性从提高到近 90% &#xff0c;同时还能实现段落渲染自动布局 Glyph-ByT5是一种定制的文本编码器&#xff0c;旨在实现准确的文字视觉渲染。其核心思想是通过细致的字形-文本配对数据集的微调&#xff0c…

VBA技术资料MF161:按需要显示特定工作表

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

java spring-data-jpa 使用方法

Spring Data JPA 是 Spring 生态系统的一部分&#xff0c;它提供了对 JPA (Java Persistence API) 的抽象&#xff0c;简化了数据访问层的开发。 以下是使用 Spring Data JPA 的基本步骤和一些核心概念&#xff1a; 1. 添加依赖 在 Maven 项目的 pom.xml 文件中添加 Spring D…

uniapp实现内嵌其他网页的功能

一、用到的知识点 页面跳转页面间跳转&#xff0c;参数传递web-view使用 二、使用navigator 页面跳转。 navigator 组件类似HTML中的<a>组件&#xff0c;但只能跳转本地页面。目标页面必须在pages.json中注册。所以这么写是不行的&#xff1a; <navigator url&quo…

最新AI智能聊天对话问答系统源码(详细图文搭建部署教程)+AI绘画系统(Midjourney),DALL-E3文生图,TTS语音识别输入,文档分析

一、文章前言 随着人工智能技术的持续进步&#xff0c;AI绘画已经发展成为一个日益成熟的领域。越来越多的人开始尝试使用AI绘画软件来创作艺术作品。尽管这些AI绘画软件对绘画领域产生了显著影响&#xff0c;但它们并不会完全取代画师。与传统手绘不同&#xff0c;AI绘画可以…

ELISA Flex: Monkey IFN-γ (HRP)

ELISA Flex: Monkey IFN-γ (HRP)该ELISA试剂盒能够检测溶液样本比如细胞培养上清或者血清/血浆中猴子γ干扰素&#xff08;IFN-γ&#xff09;的含量。 产品组分&#xff1a; 捕获抗体&#xff1a;克隆号MT126L&#xff08;0.5mg/ml&#xff09; 检测抗体&#xff1a;克隆号7…

3d模型有个虚拟外框怎么去除?---模大狮模型网

在3D建模和渲染过程中&#xff0c;虚拟外框(Bounding Box)是一个常见的显示元素&#xff0c;用于表示模型的包围盒或选择状态。尽管虚拟外框在一些情况下有其作用&#xff0c;但在最终渲染或呈现阶段&#xff0c;我们通常希望清除这些辅助显示&#xff0c;以展示纯粹的模型效果…

深入了解 Android 中的 ViewStub

在 Android 开发中&#xff0c;性能优化一直是一个重要的话题。ViewStub 作为一种轻量级视图容器&#xff0c;可以帮助我们在合适的时机延迟加载视图&#xff0c;从而优化应用性能。本文将详细介绍 ViewStub 的概念、使用方法以及在实际开发中的应用场景。 什么是 ViewStub&am…

一个简单、快速用于训练和微调中等规模GPT模型的开源项目

大家好&#xff0c;今天给大家分享的是一个简单、快速用于训练和微调中等规模GPT模型的开源项目&#xff0c;该项目旨在拓宽深度学习领域的应用&#xff0c;特别是为深度学习的入门者提供便利。 Nano GPT是一个基于PyTorch的开源项目&#xff0c;由前特斯拉AI负责人Andrej Ka…

linux搭建sftp服务

1. 添加用户及用户组 使用 groupadd sftpgroup 添加sftpgroup 用户组&#xff1b; 使用useradd -G sftpgroup -s /sbin/nologin cmssftp给sftpgroup 添加cmssftp用户&#xff1b; 使用passwd cmssftp给用户cmssftp进行设置密码(默认为:654321)。具体如下图所示&#xff1a; 2.…

运维篇-配置高级

黑马程序员Spring Boot2 文章目录 1、临时属性1.1 命令行中使用临属性1.2 开发环境设定临时属性 2、配置文件分类3、自定义配置文件 1、临时属性 1.1 命令行中使用临属性 使用jar命令启动Sprigboot工程师可以使用临时属性替换配置文件中的属性临时属性添加方式&#xff1a;ja…

vue3 页面左右滑动钩子封装

// useSwiper.js文件 import { ref, onMounted, onUnmounted } from "vue"; export function useSwiper({tabList, //tab数据curTabId,// 当前tab idcurTabIndex,// 当前tab 索引tabChange,// tab改变事件animation,// 动画animationData,// 动画 }) {let minOffset …

俄罗斯跨境电商:四个宝藏平台助你高效开发俄罗斯客户

今年俄罗斯外贸无疑是新风口&#xff0c;然而俄罗斯客户大多不擅长英文&#xff0c;也很少使用Google等搜索引擎&#xff0c;外贸人应该如何开发俄罗斯客户呢&#xff1f;今天就来给大家分享开发俄罗斯客户的宝藏APP。 开发俄罗斯客户宝藏APP 1️⃣ VKontakte (VK) 俄罗斯最大的…

jeecg spring数据源用户名和密码加密 避免明文安全漏洞

1.目的 由于系统部署在互联网&#xff0c;配置文件中的数据库账号密码使用明文&#xff0c;存在安全隐患&#xff0c;做等保测试时要求对其加密。 2.实现方法 Jeecg框架本身有PasswordUtil可以使用PBEWITHMD5andDES进行加密&#xff0c;这里为方便改造&#xff0c;且安全性较…

探索数据分析无限潜能:vividime Desktop助力企业智能决策

在数字化浪潮席卷全球的今天&#xff0c;数据已经成为企业最宝贵的资产之一。通过对海量数据的深度挖掘和分析&#xff0c;企业能够洞察市场趋势、优化运营流程、提升用户体验&#xff0c;从而在激烈的市场竞争中脱颖而出。永洪科技的vividime Desktop作为一款功能强大、操作简…

Scala语言:大数据开发的未来之星 - 零基础到精通入门指南

前言 随着大数据时代的到来&#xff0c;数据量的急剧增长为软件开发带来了新的挑战和机遇。Scala语言因其函数式编程和面向对象的特性&#xff0c;以及与Apache Spark的完美协作&#xff0c;在大数据开发领域迅速崛起&#xff0c;成为该领域的新兴宠儿。本篇将从零基础开始&…

【Java】Object、Objects、包装类、StringBuilder、StringJoiner

目录 1.API2.Object类3.Objects类4.包装类4.1包装类概述4.2包装类的其他常见操作 5.StringBuilder 可变字符串5.1概述5.2StringBuilder案例 6.StringJoiner 1.API API&#xff1a;应用程序编程接口&#xff0c;全称application programing interface&#xff0c;即Java已经写好…

测试用例编写指导

一、背景及目标 测试用例是将产品需求转换为具体可验证的指标&#xff0c;为了防止测试过程中出现遗漏&#xff0c;按照测试用例执行可以提高工作效率&#xff0c;它还可以跟踪整体测试进度&#xff0c;起到指导作用&#xff0c;并可以作为历史参考&#xff0c;因此测试用例的…

从粉丝基础到带货数据:全方位解读TikTok带货达人的选择之道

在如今的数字营销时代&#xff0c;TikTok已成为品牌推广和产品销售的重要平台。通过与合适的TikTok带货达人合作&#xff0c;品牌可以迅速吸引大量的潜在客户&#xff0c;实现销售转化。然而&#xff0c;选择合适的TikTok达人需要慎重考虑多个因素。本文Nox聚星将和大家详细阐述…

Android入门第68天-自动更新/升级怎么做(生产级实例)

开篇 今天我们进入第68讲。 在第60天左右其实很多同学们已经进入了APP应用开发了,因为60天内容足以让大家踏上正实的Android开发生涯。 随着开发的深入,我们发觉日常工作中无非就是一些组件的嵌套、合理应用。当代码迭代、功能迭代越来越频繁后我们面临着另一个问题,即:…