@@ -737,25 +737,40 @@ export function usePuzzleGame({ userId, preloadedGameState }: UsePuzzleGameProps
737737 newAnswerGrid [ lastMove . toSlot ] = null ;
738738 }
739739 }
740+
741+ // 更新拼图块状态,将其移回原位置
740742 updatedPieces = updatedPieces . map ( piece =>
741743 piece . id === lastMove . pieceId
742744 ? { ...piece , currentSlot : lastMove . fromSlot || null }
743745 : piece
744746 ) ;
745- // 如果从其他槽位移动,需要恢复原槽位
747+
748+ // 如果从其他槽位移动,需要恢复原槽位的状态
746749 if ( lastMove . fromSlot !== null && lastMove . fromSlot !== undefined ) {
747750 const originalPiece = updatedPieces . find ( p => p . id === lastMove . pieceId ) ;
748751 if ( originalPiece ) {
749752 const fromSlot = lastMove . fromSlot as number ;
750- if ( prev . config . pieceShape === 'tetris' && originalPiece . correctSlots ) {
751- // 俄罗斯方块恢复到所有原始槽位
752- originalPiece . correctSlots . forEach ( slotIndex => {
753- if ( slotIndex === fromSlot ) {
754- newAnswerGrid [ slotIndex ] = { ...originalPiece , currentSlot : fromSlot } ;
755- } else {
753+
754+ if ( prev . config . pieceShape === 'tetris' && originalPiece . occupiedPositions ) {
755+ // 俄罗斯方块:计算原位置占据的所有槽位
756+ const gridCols = prev . config . gridSize . cols ;
757+ const fromRow = Math . floor ( fromSlot / gridCols ) ;
758+ const fromCol = fromSlot % gridCols ;
759+
760+ // 计算相对位置偏移
761+ const minRow = Math . min ( ...originalPiece . occupiedPositions . map ( pos => pos [ 0 ] ) ) ;
762+ const minCol = Math . min ( ...originalPiece . occupiedPositions . map ( pos => pos [ 1 ] ) ) ;
763+
764+ // 计算并恢复所有原始槽位
765+ for ( const [ relRow , relCol ] of originalPiece . occupiedPositions ) {
766+ const slotRow = fromRow + ( relRow - minRow ) ;
767+ const slotCol = fromCol + ( relCol - minCol ) ;
768+ const slotIndex = slotRow * gridCols + slotCol ;
769+
770+ if ( slotIndex >= 0 && slotIndex < newAnswerGrid . length ) {
756771 newAnswerGrid [ slotIndex ] = { ...originalPiece , currentSlot : fromSlot } ;
757772 }
758- } ) ;
773+ }
759774 } else {
760775 // 普通拼图块恢复到单个槽位
761776 newAnswerGrid [ fromSlot ] = { ...originalPiece , currentSlot : fromSlot } ;
@@ -770,11 +785,27 @@ export function usePuzzleGame({ userId, preloadedGameState }: UsePuzzleGameProps
770785 if ( piece ) {
771786 const fromSlot = lastMove . fromSlot as number ;
772787
773- if ( prev . config . pieceShape === 'tetris' && piece . correctSlots ) {
774- // 俄罗斯方块:恢复到所有占据的槽位
775- piece . correctSlots . forEach ( slotIndex => {
776- newAnswerGrid [ slotIndex ] = { ...piece , currentSlot : fromSlot } ;
777- } ) ;
788+ if ( prev . config . pieceShape === 'tetris' && piece . occupiedPositions ) {
789+ // 俄罗斯方块:计算并恢复到所有占据的槽位
790+ const gridCols = prev . config . gridSize . cols ;
791+ const fromRow = Math . floor ( fromSlot / gridCols ) ;
792+ const fromCol = fromSlot % gridCols ;
793+
794+ // 计算相对位置偏移
795+ const minRow = Math . min ( ...piece . occupiedPositions . map ( pos => pos [ 0 ] ) ) ;
796+ const minCol = Math . min ( ...piece . occupiedPositions . map ( pos => pos [ 1 ] ) ) ;
797+
798+ // 计算并恢复所有槽位
799+ for ( const [ relRow , relCol ] of piece . occupiedPositions ) {
800+ const slotRow = fromRow + ( relRow - minRow ) ;
801+ const slotCol = fromCol + ( relCol - minCol ) ;
802+ const slotIndex = slotRow * gridCols + slotCol ;
803+
804+ if ( slotIndex >= 0 && slotIndex < newAnswerGrid . length ) {
805+ newAnswerGrid [ slotIndex ] = { ...piece , currentSlot : fromSlot } ;
806+ }
807+ }
808+
778809 updatedPieces = updatedPieces . map ( p =>
779810 p . id === lastMove . pieceId ? { ...p , currentSlot : fromSlot } : p
780811 ) ;
@@ -820,15 +851,31 @@ export function usePuzzleGame({ userId, preloadedGameState }: UsePuzzleGameProps
820851 if ( lastMove . replacedPieceId ) {
821852 const replacedPiece = updatedPieces . find ( p => p . id === lastMove . replacedPieceId ) ;
822853 if ( replacedPiece ) {
823- if ( prev . config . pieceShape === 'tetris' && replacedPiece . correctSlots ) {
824- // 俄罗斯方块:恢复到所有原始槽位
825- replacedPiece . correctSlots . forEach ( slotIndex => {
826- newAnswerGrid [ slotIndex ] = { ...replacedPiece , currentSlot : toSlot } ;
827- } ) ;
854+ if ( prev . config . pieceShape === 'tetris' && replacedPiece . occupiedPositions ) {
855+ // 俄罗斯方块:计算并恢复到所有槽位
856+ const gridCols = prev . config . gridSize . cols ;
857+ const toRow = Math . floor ( toSlot / gridCols ) ;
858+ const toCol = toSlot % gridCols ;
859+
860+ // 计算相对位置偏移
861+ const minRow = Math . min ( ...replacedPiece . occupiedPositions . map ( pos => pos [ 0 ] ) ) ;
862+ const minCol = Math . min ( ...replacedPiece . occupiedPositions . map ( pos => pos [ 1 ] ) ) ;
863+
864+ // 计算并恢复所有槽位
865+ for ( const [ relRow , relCol ] of replacedPiece . occupiedPositions ) {
866+ const slotRow = toRow + ( relRow - minRow ) ;
867+ const slotCol = toCol + ( relCol - minCol ) ;
868+ const slotIndex = slotRow * gridCols + slotCol ;
869+
870+ if ( slotIndex >= 0 && slotIndex < newAnswerGrid . length ) {
871+ newAnswerGrid [ slotIndex ] = { ...replacedPiece , currentSlot : toSlot } ;
872+ }
873+ }
828874 } else {
829875 // 普通拼图块:恢复到单个槽位
830876 newAnswerGrid [ toSlot ] = { ...replacedPiece , currentSlot : toSlot } ;
831877 }
878+
832879 updatedPieces = updatedPieces . map ( p =>
833880 p . id === lastMove . replacedPieceId ? { ...p , currentSlot : toSlot } : p
834881 ) ;
@@ -847,11 +894,27 @@ export function usePuzzleGame({ userId, preloadedGameState }: UsePuzzleGameProps
847894 const originalPiece = updatedPieces . find ( p => p . id === lastMove . pieceId ) ;
848895 if ( originalPiece ) {
849896 const fromSlot = lastMove . fromSlot as number ;
850- if ( prev . config . pieceShape === 'tetris' && originalPiece . correctSlots ) {
851- // 俄罗斯方块:恢复到所有原始槽位
852- originalPiece . correctSlots . forEach ( slotIndex => {
853- newAnswerGrid [ slotIndex ] = { ...originalPiece , currentSlot : fromSlot } ;
854- } ) ;
897+
898+ if ( prev . config . pieceShape === 'tetris' && originalPiece . occupiedPositions ) {
899+ // 俄罗斯方块:计算并恢复到所有原始槽位
900+ const gridCols = prev . config . gridSize . cols ;
901+ const fromRow = Math . floor ( fromSlot / gridCols ) ;
902+ const fromCol = fromSlot % gridCols ;
903+
904+ // 计算相对位置偏移
905+ const minRow = Math . min ( ...originalPiece . occupiedPositions . map ( pos => pos [ 0 ] ) ) ;
906+ const minCol = Math . min ( ...originalPiece . occupiedPositions . map ( pos => pos [ 1 ] ) ) ;
907+
908+ // 计算并恢复所有原始槽位
909+ for ( const [ relRow , relCol ] of originalPiece . occupiedPositions ) {
910+ const slotRow = fromRow + ( relRow - minRow ) ;
911+ const slotCol = fromCol + ( relCol - minCol ) ;
912+ const slotIndex = slotRow * gridCols + slotCol ;
913+
914+ if ( slotIndex >= 0 && slotIndex < newAnswerGrid . length ) {
915+ newAnswerGrid [ slotIndex ] = { ...originalPiece , currentSlot : fromSlot } ;
916+ }
917+ }
855918 } else {
856919 // 普通拼图块:恢复到单个槽位
857920 newAnswerGrid [ fromSlot ] = { ...originalPiece , currentSlot : fromSlot } ;
@@ -902,11 +965,26 @@ export function usePuzzleGame({ userId, preloadedGameState }: UsePuzzleGameProps
902965 if ( piece ) {
903966 const toSlot = moveToRedo . toSlot as number ;
904967
905- if ( prev . config . pieceShape === 'tetris' && piece . correctSlots ) {
906- // 俄罗斯方块:放置到所有槽位
907- piece . correctSlots . forEach ( slotIndex => {
908- newAnswerGrid [ slotIndex ] = { ...piece , currentSlot : toSlot } ;
909- } ) ;
968+ if ( prev . config . pieceShape === 'tetris' && piece . occupiedPositions ) {
969+ // 俄罗斯方块:计算并放置到所有槽位
970+ const gridCols = prev . config . gridSize . cols ;
971+ const toRow = Math . floor ( toSlot / gridCols ) ;
972+ const toCol = toSlot % gridCols ;
973+
974+ // 计算相对位置偏移
975+ const minRow = Math . min ( ...piece . occupiedPositions . map ( pos => pos [ 0 ] ) ) ;
976+ const minCol = Math . min ( ...piece . occupiedPositions . map ( pos => pos [ 1 ] ) ) ;
977+
978+ // 计算并放置到所有槽位
979+ for ( const [ relRow , relCol ] of piece . occupiedPositions ) {
980+ const slotRow = toRow + ( relRow - minRow ) ;
981+ const slotCol = toCol + ( relCol - minCol ) ;
982+ const slotIndex = slotRow * gridCols + slotCol ;
983+
984+ if ( slotIndex >= 0 && slotIndex < newAnswerGrid . length ) {
985+ newAnswerGrid [ slotIndex ] = { ...piece , currentSlot : toSlot } ;
986+ }
987+ }
910988 } else {
911989 // 普通拼图块:放置到单个槽位
912990 newAnswerGrid [ toSlot ] = { ...piece , currentSlot : toSlot } ;
@@ -917,13 +995,51 @@ export function usePuzzleGame({ userId, preloadedGameState }: UsePuzzleGameProps
917995 ) ;
918996 }
919997 }
998+
920999 // 如果从其他槽位移动,清空原槽位
9211000 if ( moveToRedo . fromSlot !== null && moveToRedo . fromSlot !== undefined ) {
922- if ( prev . config . pieceShape === 'tetris' ) {
923- // 俄罗斯方块:清空所有原始槽位
924- for ( let i = 0 ; i < newAnswerGrid . length ; i ++ ) {
925- if ( newAnswerGrid [ i ] ?. id === moveToRedo . pieceId && i !== moveToRedo . toSlot ) {
926- newAnswerGrid [ i ] = null ;
1001+ const piece = updatedPieces . find ( p => p . id === moveToRedo . pieceId ) ;
1002+ if ( piece && prev . config . pieceShape === 'tetris' && piece . occupiedPositions ) {
1003+ // 俄罗斯方块:清空所有原始槽位(但保留目标槽位)
1004+ const gridCols = prev . config . gridSize . cols ;
1005+ const fromRow = Math . floor ( moveToRedo . fromSlot / gridCols ) ;
1006+ const fromCol = moveToRedo . fromSlot % gridCols ;
1007+
1008+ // 计算相对位置偏移
1009+ const minRow = Math . min ( ...piece . occupiedPositions . map ( pos => pos [ 0 ] ) ) ;
1010+ const minCol = Math . min ( ...piece . occupiedPositions . map ( pos => pos [ 1 ] ) ) ;
1011+
1012+ // 清空原始位置的所有槽位
1013+ for ( const [ relRow , relCol ] of piece . occupiedPositions ) {
1014+ const slotRow = fromRow + ( relRow - minRow ) ;
1015+ const slotCol = fromCol + ( relCol - minCol ) ;
1016+ const slotIndex = slotRow * gridCols + slotCol ;
1017+
1018+ // 只有当槽位不是目标槽位的一部分时才清空
1019+ if ( slotIndex >= 0 && slotIndex < newAnswerGrid . length &&
1020+ slotIndex !== moveToRedo . toSlot &&
1021+ newAnswerGrid [ slotIndex ] ?. id === moveToRedo . pieceId ) {
1022+
1023+ // 检查该槽位是否也是目标位置的一部分
1024+ const toSlot = moveToRedo . toSlot as number ;
1025+ const toRow = Math . floor ( toSlot / gridCols ) ;
1026+ const toCol = toSlot % gridCols ;
1027+ let isTargetSlot = false ;
1028+
1029+ for ( const [ targetRelRow , targetRelCol ] of piece . occupiedPositions ) {
1030+ const targetSlotRow = toRow + ( targetRelRow - minRow ) ;
1031+ const targetSlotCol = toCol + ( targetRelCol - minCol ) ;
1032+ const targetSlotIndex = targetSlotRow * gridCols + targetSlotCol ;
1033+
1034+ if ( slotIndex === targetSlotIndex ) {
1035+ isTargetSlot = true ;
1036+ break ;
1037+ }
1038+ }
1039+
1040+ if ( ! isTargetSlot ) {
1041+ newAnswerGrid [ slotIndex ] = null ;
1042+ }
9271043 }
9281044 }
9291045 } else {
@@ -989,11 +1105,26 @@ export function usePuzzleGame({ userId, preloadedGameState }: UsePuzzleGameProps
9891105 }
9901106
9911107 // 放置新拼图块
992- if ( prev . config . pieceShape === 'tetris' && piece . correctSlots ) {
993- // 俄罗斯方块:放置到所有槽位
994- piece . correctSlots . forEach ( slotIndex => {
995- newAnswerGrid [ slotIndex ] = { ...piece , currentSlot : toSlot } ;
996- } ) ;
1108+ if ( prev . config . pieceShape === 'tetris' && piece . occupiedPositions ) {
1109+ // 俄罗斯方块:计算并放置到所有槽位
1110+ const gridCols = prev . config . gridSize . cols ;
1111+ const toRow = Math . floor ( toSlot / gridCols ) ;
1112+ const toCol = toSlot % gridCols ;
1113+
1114+ // 计算相对位置偏移
1115+ const minRow = Math . min ( ...piece . occupiedPositions . map ( pos => pos [ 0 ] ) ) ;
1116+ const minCol = Math . min ( ...piece . occupiedPositions . map ( pos => pos [ 1 ] ) ) ;
1117+
1118+ // 计算并放置到所有槽位
1119+ for ( const [ relRow , relCol ] of piece . occupiedPositions ) {
1120+ const slotRow = toRow + ( relRow - minRow ) ;
1121+ const slotCol = toCol + ( relCol - minCol ) ;
1122+ const slotIndex = slotRow * gridCols + slotCol ;
1123+
1124+ if ( slotIndex >= 0 && slotIndex < newAnswerGrid . length ) {
1125+ newAnswerGrid [ slotIndex ] = { ...piece , currentSlot : toSlot } ;
1126+ }
1127+ }
9971128 } else {
9981129 // 普通拼图块:放置到单个槽位
9991130 newAnswerGrid [ toSlot ] = { ...piece , currentSlot : toSlot } ;
@@ -1005,17 +1136,52 @@ export function usePuzzleGame({ userId, preloadedGameState }: UsePuzzleGameProps
10051136
10061137 // 如果从其他槽位移动,清空原槽位
10071138 if ( moveToRedo . fromSlot !== null && moveToRedo . fromSlot !== undefined ) {
1008- if ( prev . config . pieceShape === 'tetris' ) {
1009- // 俄罗斯方块:确保不清空目标槽位
1010- for ( let i = 0 ; i < newAnswerGrid . length ; i ++ ) {
1011- if ( newAnswerGrid [ i ] ?. id === moveToRedo . pieceId &&
1012- ! piece . correctSlots ?. includes ( i ) ) {
1013- newAnswerGrid [ i ] = null ;
1139+ const fromSlot = moveToRedo . fromSlot as number ;
1140+
1141+ if ( prev . config . pieceShape === 'tetris' && piece . occupiedPositions ) {
1142+ // 俄罗斯方块:清空原始位置的所有槽位(但保留目标槽位)
1143+ const gridCols = prev . config . gridSize . cols ;
1144+ const fromRow = Math . floor ( fromSlot / gridCols ) ;
1145+ const fromCol = fromSlot % gridCols ;
1146+
1147+ // 计算相对位置偏移
1148+ const minRow = Math . min ( ...piece . occupiedPositions . map ( pos => pos [ 0 ] ) ) ;
1149+ const minCol = Math . min ( ...piece . occupiedPositions . map ( pos => pos [ 1 ] ) ) ;
1150+
1151+ // 清空原始位置的所有槽位
1152+ for ( const [ relRow , relCol ] of piece . occupiedPositions ) {
1153+ const slotRow = fromRow + ( relRow - minRow ) ;
1154+ const slotCol = fromCol + ( relCol - minCol ) ;
1155+ const slotIndex = slotRow * gridCols + slotCol ;
1156+
1157+ // 只有当槽位不是目标槽位的一部分时才清空
1158+ if ( slotIndex >= 0 && slotIndex < newAnswerGrid . length &&
1159+ newAnswerGrid [ slotIndex ] ?. id === moveToRedo . pieceId ) {
1160+
1161+ // 检查该槽位是否也是目标位置的一部分
1162+ const toRow = Math . floor ( toSlot / gridCols ) ;
1163+ const toCol = toSlot % gridCols ;
1164+ let isTargetSlot = false ;
1165+
1166+ for ( const [ targetRelRow , targetRelCol ] of piece . occupiedPositions ) {
1167+ const targetSlotRow = toRow + ( targetRelRow - minRow ) ;
1168+ const targetSlotCol = toCol + ( targetRelCol - minCol ) ;
1169+ const targetSlotIndex = targetSlotRow * gridCols + targetSlotCol ;
1170+
1171+ if ( slotIndex === targetSlotIndex ) {
1172+ isTargetSlot = true ;
1173+ break ;
1174+ }
1175+ }
1176+
1177+ if ( ! isTargetSlot ) {
1178+ newAnswerGrid [ slotIndex ] = null ;
1179+ }
10141180 }
10151181 }
10161182 } else {
10171183 // 普通拼图块:清空原始槽位
1018- newAnswerGrid [ moveToRedo . fromSlot ] = null ;
1184+ newAnswerGrid [ fromSlot ] = null ;
10191185 }
10201186 }
10211187 }
0 commit comments