maze_python/boss_fight.py
2025-06-29 16:42:26 +08:00

137 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*-coding: GBK -*-
import heapq # 导入堆模块,用于实现优先队列
from typing import List, Optional, Tuple # 导入类型提示相关模块
def boss_strategy(coin: int, blood: int) -> Optional[Tuple[List[str], int]]:
# 使用分支限界法寻找最小回合数击败BOSS的技能序列
# 参数:
# coin: 玩家初始金币数
# blood: BOSS初始血量
# 返回:
# 最小回合数的技能序列列表如果无解则返回None
start_coin = coin # 记录初始金币数,用于计算消耗金币
# 初始状态: (回合数, 剩余金币, BOSS血量, 充能, 连续E计数, 技能序列元组)
start_state = (0, coin, blood, 0, 0, ())
# 创建优先队列: 元素为 (优先级, 状态)
# 优先级元组: (回合数, 消耗金币, BOSS血量) - 值越小优先级越高
heap = []
heapq.heappush(heap, ((0, 0, blood), start_state)) # 将初始状态加入优先队列
# 创建访问集合: 用于避免重复状态
# 状态键: (回合数, 剩余金币, BOSS血量, 充能, min(连续E计数,3))
visited = set()
start_ce_compressed = min(0, 3) # 压缩连续E计数状态
visited.add((0, coin, blood, 0, start_ce_compressed)) # 将初始状态加入已访问集合
# 设置最大回合数限制,避免无限循环
max_round = blood * 2 # 每次至少造成1点伤害最多回合数为血量两倍
# 主循环: 处理优先队列中的状态
while heap:
# 从优先队列中取出优先级最高的状态
priority, state = heapq.heappop(heap)
# 解包状态元组
round_cnt, cur_coin, cur_blood, energy, ce, seq_tuple = state
# 检查是否已击败BOSS
if cur_blood <= 0:
return (list(seq_tuple), cur_coin) # 返回技能序列和剩余金币
# 超过最大回合数则跳过当前状态
if round_cnt >= max_round:
continue
# 尝试使用技能A
if cur_coin >= 2: # 检查金币是否足够
new_coin = cur_coin - 2 # 扣除金币
new_blood = cur_blood - 1 # 减少BOSS血量
new_energy = energy + 1 # 增加充能
new_ce = 0 # 使用非E技能重置连续E计数
new_round = round_cnt + 1 # 回合数+1
new_seq = seq_tuple + ('A',) # 添加技能到序列
# 压缩连续E计数状态>=3视为3
ce_compressed = min(new_ce, 3)
# 创建状态键用于去重
state_key = (new_round, new_coin, new_blood, new_energy, ce_compressed)
# 检查是否为新状态
if state_key not in visited:
visited.add(state_key) # 标记为已访问
cost = start_coin - new_coin # 计算已消耗金币
# 创建新状态
new_state = (new_round, new_coin, new_blood, new_energy, new_ce, new_seq)
# 将新状态加入优先队列
heapq.heappush(heap, ((new_round, cost, new_blood), new_state))
# 尝试使用技能E
cost_e = 3 # 默认消耗金币
if ce >= 2: # 检查是否为连续第三次使用E
cost_e = 2 # 第三次消耗2金币
if cur_coin >= cost_e: # 检查金币是否足够
new_coin = cur_coin - cost_e # 扣除金币
new_blood = cur_blood - 3 # 减少BOSS血量
new_energy = energy + 1 # 增加充能
new_ce = ce + 1 # 增加连续E计数
new_round = round_cnt + 1 # 回合数+1
new_seq = seq_tuple + ('E',) # 添加技能到序列
# 压缩连续E计数状态
ce_compressed = min(new_ce, 3)
# 创建状态键用于去重
state_key = (new_round, new_coin, new_blood, new_energy, ce_compressed)
# 检查是否为新状态
if state_key not in visited:
visited.add(state_key) # 标记为已访问
cost = start_coin - new_coin # 计算已消耗金币
# 创建新状态
new_state = (new_round, new_coin, new_blood, new_energy, new_ce, new_seq)
# 将新状态加入优先队列
heapq.heappush(heap, ((new_round, cost, new_blood), new_state))
# 尝试使用技能Q
if energy >= 3 and cur_coin >= 3: # 检查充能和金币是否足够
new_coin = cur_coin - 3 # 扣除金币
new_blood = cur_blood - 8 # 减少BOSS血量
new_energy = energy - 3 # 消耗充能
new_ce = 0 # 使用非E技能重置连续E计数
new_round = round_cnt + 1 # 回合数+1
new_seq = seq_tuple + ('Q',) # 添加技能到序列
# 压缩连续E计数状态
ce_compressed = min(new_ce, 3)
# 创建状态键用于去重
state_key = (new_round, new_coin, new_blood, new_energy, ce_compressed)
# 检查是否为新状态
if state_key not in visited:
visited.add(state_key) # 标记为已访问
cost = start_coin - new_coin # 计算已消耗金币
# 创建新状态
new_state = (new_round, new_coin, new_blood, new_energy, new_ce, new_seq)
# 将新状态加入优先队列
heapq.heappush(heap, ((new_round, cost, new_blood), new_state))
return None # 队列为空,无解
# 主程序入口
if __name__ == "__main__":
# 测试示例: 金币=10, BOSS血量=10
result = boss_strategy(20, 20)
if result is None:
print("无法击败BOSS")
else:
skill_sequence, remaining_coins = result
print("最小回合数技能序列:", skill_sequence) # 预期输出: ['A', 'A', 'A', 'Q']
print("剩余金币:", remaining_coins) # 预期输出: 1