feat: 优化开始训练指引并修复AI递归问题

- 修复 GameController._trigger_ai 中AI决策递归调用问题,增加 _is_processing 锁
- 修复 TrainingController 未加入场景树导致信号无法触发的问题
- 主菜单添加"游戏说明"按钮和详细指引对话框
- 训练室添加引导提示标签和操作状态反馈
- 优化提示功能显示中文牌型名称(单张、对子、顺子等)
- 优化错误信息显示,提供更具体的失败原因
- 清除调试 print 语句

🤖 Generated with [Qoder][https://qoder.com]
This commit is contained in:
xiaji
2026-06-01 22:55:18 +08:00
parent cef2cba7a5
commit b3fe03f229
5 changed files with 112 additions and 14 deletions

View File

@@ -7,6 +7,7 @@ var controller: TrainingController
@onready var pass_button: Button = $Buttons/PassButton
@onready var hint_button: Button = $Buttons/HintButton
@onready var status_label: Label = $StatusLabel
@onready var guide_label: Label = $GuideLabel
func _ready() -> void:
play_button.pressed.connect(_on_play_pressed)
@@ -16,54 +17,98 @@ func _ready() -> void:
func start_training() -> void:
controller = TrainingController.new()
add_child(controller)
hand_area.training_controller = controller
controller.start_game(Config.rule_config, 0)
controller.turn_ready.connect(_on_turn_ready)
controller.state_changed.connect(_refresh_ui)
controller.game_ended.connect(_on_game_ended)
_update_guide_text()
_refresh_ui()
func _update_guide_text() -> void:
if guide_label:
guide_label.text = "💡 提示:点击手牌选中,然后点击「出牌」或「过牌」。首次出牌建议点击「提示」按钮。"
func _on_turn_ready(player_idx: int, is_human: bool) -> void:
if is_human:
hand_area.enable_input()
if status_label: status_label.text = "你的回合"
if status_label:
status_label.text = "你的回合 - 请出牌或点击过牌"
else:
hand_area.disable_input()
if status_label and controller and controller.game_state:
status_label.text = "%s 思考中..." % controller.game_state.player_names[player_idx]
func _on_play_pressed() -> void:
if not hand_area: return
if not hand_area:
return
var selected := hand_area.selected_cards
if selected.is_empty():
if status_label:
status_label.text = "请先选择要出的牌"
return
var result := controller.handle_human_play(selected)
if not result.ok:
if status_label: status_label.text = "无效出牌"
var error_msg := _get_error_message(result.error_code)
if status_label:
status_label.text = "%s" % error_msg
return
hand_area.clear_selection()
if status_label:
status_label.text = "✓ 出牌成功!"
_refresh_ui()
func _get_error_message(error_code: int) -> String:
match error_code:
1: return "无效的牌型组合"
2: return "不是你的回合"
3: return "不能过牌(你是领出者)"
4: return "牌不在手中"
_: return "出牌失败"
func _on_pass_pressed() -> void:
var result := controller.handle_human_pass()
if not result.ok:
if status_label: status_label.text = "不能过牌"
var error_msg := _get_error_message(result.error_code)
if status_label:
status_label.text = "%s" % error_msg
return
if status_label:
status_label.text = "✓ 已过牌"
_refresh_ui()
func _on_hint_pressed() -> void:
var hint := controller.get_hint()
if hint == null or hint.type == -1:
if status_label: status_label.text = "建议:过牌"
if status_label:
status_label.text = "建议:过牌(当前轮到你领出,但无合适牌型)"
return
if not hand_area:
return
if not hand_area: return
hand_area.clear_selection()
for card in hint.cards:
for cn in hand_area.card_nodes:
if cn.card_data != null and cn.card_data.card_id == card.card_id:
cn.set_selected(true)
hand_area.selected_cards.append(card)
if status_label: status_label.text = "建议牌型: %s (rank=%d)" % [hint.type, hint.primary_rank]
var type_name := _get_type_name(hint.type)
if status_label:
status_label.text = "💡 建议:出 %s%d张,主阶=%d" % [type_name, hint.cards.size(), hint.primary_rank]
func _get_type_name(type_idx: int) -> String:
match type_idx:
0: return "单张"
1: return "对子"
2: return "三张"
3: return "三带二"
4: return "顺子"
5: return "连对"
6: return "钢板"
7: return "同花顺"
8: return "炸弹"
9: return "火箭"
_: return "未知"
func _on_game_ended(winner_team: int, _reason: String) -> void:
if status_label: status_label.text = "游戏结束! 队伍 %d 获胜" % winner_team
@@ -72,7 +117,4 @@ func _on_game_ended(winner_team: int, _reason: String) -> void:
func _refresh_ui() -> void:
if controller and controller.game_state and hand_area:
var hand: Array = controller.game_state.get_hand(0)
print("[DEBUG] _refresh_ui: hand size = ", hand.size())
hand_area.update_hand(hand)
else:
print("[DEBUG] _refresh_ui: controller=", controller, " game_state=", controller.game_state if controller else null, " hand_area=", hand_area)