From cd9c3a79ab17dae4a924ad6e3bfac7c3ab11a773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=88=AA=E5=AE=87?= <3364451258@qq.com> Date: Sun, 31 May 2026 13:38:04 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=82=94=E6=A3=8B?= =?UTF-8?q?=E5=A5=87=E6=95=B0=E6=AD=A5=E5=B4=A9=E6=BA=83=E5=8F=8A=E7=A9=BA?= =?UTF-8?q?=E5=8E=86=E5=8F=B2=E9=94=99=E8=AF=AF=E8=AF=AD=E4=B9=89=20(NoHis?= =?UTF-8?q?tory)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- core/src/board.rs | 11 ++++++++--- core/src/types.rs | 2 ++ gui/src/commands.rs | 5 ++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/src/board.rs b/core/src/board.rs index 43f65ef..6c5c238 100644 --- a/core/src/board.rs +++ b/core/src/board.rs @@ -99,7 +99,7 @@ impl Board { /// 悔棋 — 撤销最近一步 pub fn undo(&self) -> Result { if self.history.is_empty() { - return Err(MoveError::GameOver); + return Err(MoveError::NoHistory); } let mut new_board = self.clone(); let last_move = new_board.history.pop().unwrap(); @@ -253,9 +253,14 @@ mod tests { } #[test] - fn test_undo_empty_history() { + fn test_undo_empty_history_returns_no_history_error() { let board = Board::new(15); - assert_eq!(board.undo(), Err(MoveError::GameOver)); + let result = board.undo(); + assert!(result.is_err()); + match result { + Err(MoveError::NoHistory) => {}, + other => panic!("expected NoHistory, got {:?}", other), + } } #[test] diff --git a/core/src/types.rs b/core/src/types.rs index 564ef1f..714d04d 100644 --- a/core/src/types.rs +++ b/core/src/types.rs @@ -68,6 +68,7 @@ pub enum MoveError { Occupied, ForbiddenMove, GameOver, + NoHistory, } impl std::fmt::Display for MoveError { @@ -77,6 +78,7 @@ impl std::fmt::Display for MoveError { MoveError::Occupied => "该位置已有棋子", MoveError::ForbiddenMove => "禁手位置,不能落子", MoveError::GameOver => "游戏已结束", + MoveError::NoHistory => "没有可撤销的棋子", }; write!(f, "{}", msg) } diff --git a/gui/src/commands.rs b/gui/src/commands.rs index 948f77f..df64fce 100644 --- a/gui/src/commands.rs +++ b/gui/src/commands.rs @@ -94,7 +94,10 @@ pub fn undo(steps: u32, state: State) -> Result<(), String> { let mut board_opt = state.board.lock().map_err(|e| e.to_string())?; let mut board = board_opt.clone().ok_or("游戏未开始")?; - for _ in 0..steps * 2 { + let max_undo = board.history().len() as u32; + let actual_steps = (steps * 2).min(max_undo); + + for _ in 0..actual_steps { board = board.undo().map_err(|e| e.to_string())?; }