From 4ed66377d238c5cde4aa0979f2cd1ba45590ac2b 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:47:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E8=AE=A4=E8=BE=93?= =?UTF-8?q?=E5=92=8C=E4=BF=9D=E5=AD=98=E6=A3=8B=E8=B0=B1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- gui/src/commands.rs | 19 +++++++++++++++++++ gui/src/lib.rs | 2 ++ src/components/game/GameControls.tsx | 28 ++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/gui/src/commands.rs b/gui/src/commands.rs index a666858..6701efe 100644 --- a/gui/src/commands.rs +++ b/gui/src/commands.rs @@ -176,3 +176,22 @@ pub fn get_game_state(state: State) -> Result) -> Result<(), String> { + let player_color = *state.current_color.lock().map_err(|e| e.to_string())?; + // 当前玩家认输,对手获胜 + let winner = player_color.opponent(); + *state.game_over.lock().map_err(|e| e.to_string())? = true; + *state.current_color.lock().map_err(|e| e.to_string())? = winner; + Ok(()) +} + +#[tauri::command] +pub fn save_record(state: State) -> Result { + let board_opt = state.board.lock().map_err(|e| e.to_string())?; + let board = board_opt.as_ref().ok_or("游戏未开始")?; + + let record = gobang_core::record::GameRecord::from_board(board, "玩家", "对手", None); + serde_json::to_string_pretty(&record).map_err(|e| e.to_string()) +} diff --git a/gui/src/lib.rs b/gui/src/lib.rs index 7790b14..a1693b8 100644 --- a/gui/src/lib.rs +++ b/gui/src/lib.rs @@ -15,6 +15,8 @@ pub fn run() { commands::ai_move, commands::get_game_state, + commands::resign, + commands::save_record, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src/components/game/GameControls.tsx b/src/components/game/GameControls.tsx index 8643e35..d427c14 100644 --- a/src/components/game/GameControls.tsx +++ b/src/components/game/GameControls.tsx @@ -1,4 +1,5 @@ import { useTranslation } from 'react-i18next'; +import { invoke } from '@tauri-apps/api/core'; import { useGameStore } from '../../store/gameStore'; interface Props { @@ -9,16 +10,43 @@ export default function GameControls({ onBackToMenu }: Props) { const { t } = useTranslation(); const undo = useGameStore((s) => s.undo); const status = useGameStore((s) => s.status); + const refreshBoard = useGameStore((s) => s.refreshBoard); const handleUndo = () => { undo(1); }; + const handleResign = async () => { + await invoke('resign'); + await refreshBoard(); + }; + + const handleSave = async () => { + try { + const json: string = await invoke('save_record'); + const blob = new Blob([json], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `gobang_${Date.now()}.json`; + a.click(); + URL.revokeObjectURL(url); + } catch (e) { + console.error('保存棋谱失败:', e); + } + }; + return (
+ +
);