在前两个版本的更新后,越来越多内容,操作和运行也不方便,优化第三版本窗口可视化界面
本次版本更新使得可读性和可操作性大幅度增加,前面2版本可分别参考
我不是挂王-用python实现燕双鹰小游戏 和 我不是挂王-用python实现燕双鹰小游戏2
一.燕双鹰窗口可视化(燕双鹰3.0)
'''
新燕双鹰3.0
1.把“状态”与“UI”彻底分离:
燕双鹰 只保留纯逻辑,所有 UI 相关代码放到 GameGUI 里。
2. 用 Enum 把散落各处的字符串常量收拢,杜绝打错字。
3. 把“攻击功法”做成数据表,新增/调整只需改表,不用动业务代码。
4. 增加“战斗日志”控件,玩家随时能看到完整事件流。
5. 增加“进度条”实时显示双方血量。
6. 增加“禁用/启用按钮”机制,防止玩家在网络延迟(或动画)期间狂点。
7. 代码量压缩 30 %,可读性大幅提高。
'''
import random
import tkinter as tk
from enum import Enum, auto
from dataclasses import dataclass# ---------- 游戏常量 ----------
class St(Enum):"""燕双鹰状态"""NORMAL = auto()SPEAKING = auto()ROLLING = auto()SURROUNDED = auto()@dataclass
class Attack:name: strdamage: inthit_rate: float # 0~1ATTACKS = [Attack("普通攻击", 0, 0.0),Attack("初级功法", 5, 0.25),Attack("中级功法", 12, 0.45),Attack("高级功法", 20, 0.65),
]# ---------- 纯逻辑层 ----------
class YanYuanYing:def __init__(self):self.hp = 100self.state = St.NORMALself.has_bullet = Trueself.miss_cnt = 0self.player_hp = 100self.player_attack: Attack = ATTACKS[0]# ---- 事件接口,全部返回 (log:str, game_over:bool) ----def talk(self):self.state = St.SPEAKINGreturn "你举枪对准燕双鹰:‘燕双鹰,插翅难逃!’\n燕双鹰:‘你的枪法不错,但还不够快……’", Falsedef shoot(self):if self.state != St.SPEAKING:self.state = St.ROLLINGreturn "燕双鹰未开口,他开始翻滚躲避,进入无敌状态!", Falseif not self.has_bullet:if random.random() < 0.3:self.player_hp -= 15return "枪里没子弹!燕双鹰趁机反击,你 -15 HP!", self._check_end()return "枪里没子弹,你得想别的办法!", False# 有子弹if random.random() < 0.5: # 50 % 打不中self.has_bullet = Falseself.miss_cnt += 1return "你开枪了……但燕双鹰躲过了!枪已空。", Falseelse:self.has_bullet = Falsedmg = 10self.hp -= dmgreturn f"子弹击中!燕双鹰 -{dmg} HP!", self._check_end()def surround(self):if self.state == St.ROLLING:return "燕双鹰在翻滚,无法包围!", Falseself.state = St.SURROUNDEDself.player_hp -= 20return "你示意手下包围,燕双鹰触发‘后手先发’反击,你 -20 HP!", self._check_end()def loud(self):self.player_hp -= 10return "你大声喊话,燕双鹰掏枪威慑,你 -10 HP!", self._check_end()def player_attack_act(self):atk = self.player_attackif random.random() < atk.hit_rate or self.miss_cnt >= 3:self.miss_cnt = 0self.hp -= atk.damagelog = f"{atk.name}命中!燕双鹰 -{atk.damage} HP!"if random.random() < 0.2: # 20 % 反击counter = int(atk.damage * 0.5)self.player_hp -= counterlog += f"\n燕双鹰反击,你 -{counter} HP!"return log, self._check_end()else:self.miss_cnt += 1return f"{atk.name}未命中!", Falsedef set_attack(self, idx: int):self.player_attack = ATTACKS[idx]def _check_end(self):return self.player_hp <= 0 or self.hp <= 0# ---------- GUI ----------
class GameGUI:def __init__(self):self.logic = YanYuanYing()self.root = tk.Tk()self.root.title("燕双鹰小游戏")self._build_ui()self.refresh_bar()self.log("游戏开始!选择你的行动。")def _build_ui(self):top = tk.Frame(self.root)top.pack(padx=10, pady=10)tk.Label(top, text="你的 HP").grid(row=0, column=0, sticky="w")tk.Label(top, text="燕双鹰 HP").grid(row=1, column=0, sticky="w")self.player_bar = tk.Canvas(top, width=200, height=20, bg="white", relief="sunken")self.yyy_bar = tk.Canvas(top, width=200, height=20, bg="white", relief="sunken")self.player_bar.grid(row=0, column=1, padx=5)self.yyy_bar.grid(row=1, column=1, padx=5)ctrl = tk.Frame(self.root)ctrl.pack(pady=5)self.btns = []actions = [("讲话", self.act_talk), ("开枪", self.act_shoot),("包围", self.act_surround), ("大声说话", self.act_loud)]for i, (txt, cmd) in enumerate(actions):b = tk.Button(ctrl, text=txt, width=12, command=cmd)b.grid(row=0, column=i, padx=3)self.btns.append(b)# 功法下拉tk.Label(ctrl, text="功法").grid(row=1, column=0, sticky="e")self.atk_var = tk.StringVar(value=ATTACKS[0].name)om = tk.OptionMenu(ctrl, self.atk_var, *[a.name for a in ATTACKS],command=self.change_atk)om.grid(row=1, column=1, padx=3)tk.Button(ctrl, text="攻击", command=self.act_attack).grid(row=1, column=2)tk.Button(ctrl, text="退出", command=self.root.destroy).grid(row=1, column=3)# 日志log_frame = tk.Frame(self.root)log_frame.pack(padx=10, pady=10, fill="both", expand=True)sc = tk.Scrollbar(log_frame)sc.pack(side="right", fill="y")self.log_box = tk.Text(log_frame, height=12, yscrollcommand=sc.set)self.log_box.pack(fill="both", expand=True)sc.config(command=self.log_box.yview)def refresh_bar(self):def _draw(bar, val):bar.delete("all")bar.create_rectangle(0, 0, int(val * 2), 20, fill="green" if val > 30 else "red")bar.create_text(100, 10, text=f"{val}/100", fill="white")_draw(self.player_bar, max(0, self.logic.player_hp))_draw(self.yyy_bar, max(0, self.logic.hp))def log(self, txt):self.log_box.insert("end", txt + "\n")self.log_box.see("end")def disable_all(self):for b in self.btns:b.config(state="disabled")def enable_all(self):for b in self.btns:b.config(state="normal")def change_atk(self, _):idx = next(i for i, a in enumerate(ATTACKS) if a.name == self.atk_var.get())self.logic.set_attack(idx)# ---- 各动作 ----def act_talk(self): self._do(*self.logic.talk())def act_shoot(self): self._do(*self.logic.shoot())def act_surround(self): self._do(*self.logic.surround())def act_loud(self): self._do(*self.logic.loud())def act_attack(self): self._do(*self.logic.player_attack_act())def _do(self, txt: str, game_over: bool):self.log(txt)self.refresh_bar()if game_over:self.disable_all()who = "你" if self.logic.player_hp <= 0 else "燕双鹰"self.log(f"{who} 被击败,游戏结束!")def run(self):self.root.mainloop()if __name__ == "__main__":GameGUI().run()
二.燕双鹰的技能多样化(燕双鹰3.1)
燕双鹰依旧超标,差一点被带走,为了公平性和可玩性,加强了一下玩家
'''
新燕双鹰3.1
版本更新,增加游戏公平性和可玩性,使得燕双鹰在非说话状态也能受到伤害
1.添加一个道具系统,例如“破甲弹”,使用后可以无视燕双鹰的状态(包括ROLLING状态)对其造成伤害。
2.在GUI中增加一个道具选择按钮,例如“使用破甲弹”。
3.当玩家使用破甲弹后,下一次攻击(无论是开枪还是功法攻击)将无视燕双鹰的状态,并且可能造成额外伤害。
'''
import random
import tkinter as tk
from enum import Enum, auto
from dataclasses import dataclass# ---------- 游戏常量 ----------
class St(Enum):"""燕双鹰状态"""NORMAL = auto()SPEAKING = auto()ROLLING = auto()SURROUNDED = auto()@dataclass
class Attack:name: strdamage: inthit_rate: float # 0~1ATTACKS = [Attack("普通攻击", 0, 0.0),Attack("初级功法", 5, 0.25),Attack("中级功法", 12, 0.45),Attack("高级功法", 20, 0.65),
]# 新增道具类
@dataclass
class Item:name: streffect: strquantity: int# ---------- 纯逻辑层 ----------
class YanYuanYing:def __init__(self):self.hp = 100self.state = St.NORMALself.has_bullet = Trueself.miss_cnt = 0self.player_hp = 100self.player_attack: Attack = ATTACKS[0]# 新增道具系统self.items = [Item("破甲弹", "无视防御", 3),Item("烟雾弹", "降低回避", 2),Item("医疗包", "恢复生命", 2)]self.active_item = None# ---- 事件接口,全部返回 (log:str, game_over:bool) ----def talk(self):self.state = St.SPEAKINGreturn "你举枪对准燕双鹰:‘燕双鹰,插翅难逃!’\\n燕双鹰:‘你的枪法不错,但还不够快……’", Falsedef shoot(self):# 使用道具效果if self.active_item == "破甲弹":self.active_item = Nonedmg = 15self.hp -= dmgself._use_item("破甲弹")return f"破甲弹穿透防御!燕双鹰 -{dmg} HP!", self._check_end()# 原始逻辑if self.state != St.SPEAKING:self.state = St.ROLLINGreturn "燕双鹰未开口,他开始翻滚躲避,进入无敌状态!", Falseif not self.has_bullet:if random.random() < 0.3:self.player_hp -= 15return "枪里没子弹!燕双鹰趁机反击,你 -15 HP!", self._check_end()return "枪里没子弹,你得想别的办法!", False# 有子弹if random.random() < 0.5: # 50 % 打不中self.has_bullet = Falseself.miss_cnt += 1return "你开枪了……但燕双鹰躲过了!枪已空。", Falseelse:self.has_bullet = Falsedmg = 10self.hp -= dmgreturn f"子弹击中!燕双鹰 -{dmg} HP!", self._check_end()def surround(self):if self.state == St.ROLLING:return "燕双鹰在翻滚,无法包围!", Falseself.state = St.SURROUNDEDself.player_hp -= 20return "你示意手下包围,燕双鹰触发‘后手先发’反击,你 -20 HP!", self._check_end()def loud(self):self.player_hp -= 10return "你大声喊话,燕双鹰掏枪威慑,你 -10 HP!", self._check_end()def player_attack_act(self):atk = self.player_attack# 使用烟雾弹效果if self.active_item == "烟雾弹":self.active_item = Nonehit_chance = min(1.0, atk.hit_rate + 0.35) # 提升35%命中率self._use_item("烟雾弹")else:hit_chance = atk.hit_rateif random.random() < hit_chance or self.miss_cnt >= 3:self.miss_cnt = 0self.hp -= atk.damagelog = f"{atk.name}命中!燕双鹰 -{atk.damage} HP!"if random.random() < 0.2: # 20 % 反击counter = int(atk.damage * 0.5)self.player_hp -= counterlog += f"\\n燕双鹰反击,你 -{counter} HP!"return log, self._check_end()else:self.miss_cnt += 1return f"{atk.name}未命中!", Falsedef set_attack(self, idx: int):self.player_attack = ATTACKS[idx]def _check_end(self):return self.player_hp <= 0 or self.hp <= 0# 新增道具系统方法def use_item(self, item_name):for item in self.items:if item.name == item_name and item.quantity > 0:item.quantity -= 1self.active_item = item_namereturn Truereturn Falsedef _use_item(self, item_name):for item in self.items:if item.name == item_name:item.quantity -= 1return Truereturn Falsedef heal(self):for item in self.items:if item.name == "医疗包" and item.quantity > 0:item.quantity -= 1self.player_hp = min(100, self.player_hp + 30)return "使用医疗包恢复30HP!"return "医疗包不足!"# ---------- GUI ----------
class GameGUI:def __init__(self):self.logic = YanYuanYing()self.root = tk.Tk()self.root.title("燕双鹰小游戏")self._build_ui()self.refresh_bar()self.log("游戏开始!选择你的行动。")def _build_ui(self):top = tk.Frame(self.root)top.pack(padx=10, pady=10)tk.Label(top, text="你的 HP").grid(row=0, column=0, sticky="w")tk.Label(top, text="燕双鹰 HP").grid(row=1, column=0, sticky="w")self.player_bar = tk.Canvas(top, width=200, height=20, bg="white", relief="sunken")self.yyy_bar = tk.Canvas(top, width=200, height=20, bg="white", relief="sunken")self.player_bar.grid(row=0, column=1, padx=5)self.yyy_bar.grid(row=1, column=1, padx=5)ctrl = tk.Frame(self.root)ctrl.pack(pady=5)self.btns = []actions = [("讲话", self.act_talk), ("开枪", self.act_shoot),("包围", self.act_surround), ("大声说话", self.act_loud)]for i, (txt, cmd) in enumerate(actions):b = tk.Button(ctrl, text=txt, width=8, command=cmd)b.grid(row=0, column=i, padx=3)self.btns.append(b)# 功法下拉tk.Label(ctrl, text="功法").grid(row=1, column=0, sticky="e")self.atk_var = tk.StringVar(value=ATTACKS[0].name)om = tk.OptionMenu(ctrl, self.atk_var, *[a.name for a in ATTACKS],command=self.change_atk)om.config(width=8)om.grid(row=1, column=1, padx=3)tk.Button(ctrl, text="攻击", command=self.act_attack, width=8).grid(row=1, column=2, padx=3)# 新增道具按钮item_frame = tk.Frame(ctrl)item_frame.grid(row=1, column=3, padx=10)tk.Button(item_frame, text="道具", command=self.toggle_items, width=8).pack(side="left")self.item_btns = []# 退出按钮tk.Button(ctrl, text="退出", command=self.root.destroy, width=8).grid(row=1, column=4, padx=3)# 新增医疗包按钮tk.Button(ctrl, text="使用医疗包", command=self.use_heal, width=10).grid(row=2, column=0, columnspan=2, pady=5)# 日志log_frame = tk.Frame(self.root)log_frame.pack(padx=10, pady=10, fill="both", expand=True)sc = tk.Scrollbar(log_frame)sc.pack(side="right", fill="y")self.log_box = tk.Text(log_frame, height=12, yscrollcommand=sc.set)self.log_box.pack(fill="both", expand=True)sc.config(command=self.log_box.yview)def toggle_items(self):if hasattr(self, "item_menu") and self.item_menu.winfo_viewable():self.item_menu.destroy()returnself.item_menu = tk.Menu(self.root, tearoff=0)for item in self.logic.items:self.item_menu.add_command(label=f"{item.name}({item.quantity})",command=lambda nm=item.name: self.use_item(nm))self.item_menu.post(self.btns[3].winfo_rootx(), self.btns[3].winfo_rooty() + 30)def use_item(self, item_name):if self.logic.use_item(item_name):self.log(f"已使用{item_name},准备攻击!")else:self.log(f"{item_name}不足!")def use_heal(self):self.log(self.logic.heal())self.refresh_bar()def refresh_bar(self):def _draw(bar, val):bar.delete("all")color = "green" if val > 30 else "red"bar.create_rectangle(0, 0, int(val * 2), 20, fill=color)bar.create_text(100, 10, text=f"{max(0, val)}/100", fill="white")_draw(self.player_bar, max(0, self.logic.player_hp))_draw(self.yyy_bar, max(0, self.logic.hp))def log(self, txt):self.log_box.insert("end", txt + "\n")self.log_box.see("end")def disable_all(self):for b in self.btns:b.config(state="disabled")def enable_all(self):for b in self.btns:b.config(state="normal")def change_atk(self, _):idx = next(i for i, a in enumerate(ATTACKS) if a.name == self.atk_var.get())self.logic.set_attack(idx)# ---- 各动作 ----def act_talk(self):self._do(*self.logic.talk())def act_shoot(self):self._do(*self.logic.shoot())def act_surround(self):self._do(*self.logic.surround())def act_loud(self):self._do(*self.logic.loud())def act_attack(self):self._do(*self.logic.player_attack_act())def _do(self, txt: str, game_over: bool):self.log(txt)self.refresh_bar()if game_over:self.disable_all()who = "你" if self.logic.player_hp <= 0 else "燕双鹰"self.log(f"{who} 被击败,游戏结束!")def run(self):self.root.mainloop()if __name__ == "__main__":GameGUI().run()
要是没有加血差一点 又没了,第二把直接功法装备上露头秒,这样游戏平衡了,但是 玩家好像加强过高了,后面再调整
在前两个版本的更新后,越来越多内容,操作和运行也不方便,优化第三版本窗口可视化界面
本次新3.0版本更新使得可读性和可操作性大幅度增加,前面2版本可分别参考以前博客,
燕双鹰依旧超标,差一点被带走,为了公平性和可玩性,在新3.1版本中加强了一下玩家;
整理不易,诚望各位看官点赞 收藏 评论 予以支持,这将成为我持续更新的动力源泉。若您在阅览时存有异议或建议,敬请留言指正批评,让我们携手共同学习,共同进取,吾辈自当相互勉励!