@@ -557,9 +557,43 @@ export function useGameState(
557557 } )
558558 }
559559
560+ // ---- Premove 状态验证 ----
561+ // AI 走棋后调用:检查玩家正在进行的选中/拖拽/预设走法是否仍然有效
562+ const validatePremoveState = ( ) => {
563+ // 1. 检查拖拽状态:如果正在拖拽的棋子已被吃或位置被占据,取消拖拽
564+ if ( isDragging . value && dragStartSquare . value ) {
565+ const dragPiece = board . value [ dragStartSquare . value . row ] ?. [ dragStartSquare . value . col ]
566+ if ( ! dragPiece || dragPiece . color !== playerColor . value ) {
567+ // 清除拖拽状态
568+ isMouseDown . value = false
569+ isDragging . value = false
570+ dragStartSquare . value = null
571+ selectedSquare . value = null
572+ premove . value = null
573+ // 移除可能残留的事件监听器
574+ window . removeEventListener ( 'mousemove' , handleMouseMove )
575+ window . removeEventListener ( 'mouseup' , handleMouseUp )
576+ }
577+ }
578+
579+ // 2. 检查已选中但尚未设定目标格的棋子是否仍然存在
580+ if ( ! premove . value && selectedSquare . value ) {
581+ const sel = selectedSquare . value
582+ const selPiece = board . value [ sel . row ] ?. [ sel . col ]
583+ if ( ! selPiece || selPiece . color !== playerColor . value ) {
584+ // 棋子被吃或位置被占,取消选中
585+ selectedSquare . value = null
586+ }
587+ // 如果棋子仍然存在,保留选中状态(继续等待玩家选择目标格)
588+ }
589+ }
590+
560591 // ---- Premove 执行逻辑 ----
561592 // 在 AI 走棋后,尝试执行预设的 premove
562593 const tryExecutePremove = ( ) => {
594+ // 先验证当前 premove 状态(处理选中/拖拽被吃等情形)
595+ validatePremoveState ( )
596+
563597 if ( ! premove . value ) return
564598
565599 const { from, to } = premove . value
@@ -1365,7 +1399,23 @@ export function useGameState(
13651399 isAIThinking . value = false
13661400
13671401 if ( e . data . type === 'bestMove' && e . data . move ) {
1402+ // 保存玩家的 premove / 选中 / 拖拽状态
1403+ // (executeAIMoveOnBoard -> executeMove 会清除 selectedSquare,需提前保存)
1404+ const savedSelectedSquare = selectedSquare . value
1405+ const savedPremove = premove . value
1406+ const savedIsDragging = isDragging . value
1407+ const savedDragStartSquare = dragStartSquare . value
1408+ const savedIsMouseDown = isMouseDown . value
1409+
13681410 executeAIMoveOnBoard ( e . data . move )
1411+
1412+ // 恢复玩家状态,后续 tryExecutePremove 会验证是否仍然合法
1413+ selectedSquare . value = savedSelectedSquare
1414+ premove . value = savedPremove
1415+ isDragging . value = savedIsDragging
1416+ dragStartSquare . value = savedDragStartSquare
1417+ isMouseDown . value = savedIsMouseDown
1418+
13691419 // AI 走棋完成后,尝试执行玩家预设的 premove
13701420 if ( ! isGameOver . value && gameMode . value === 'ai' ) {
13711421 void nextTick ( ( ) => {
0 commit comments