From 2bf298fea00e2d528b56e4db98969e26f7294a03 Mon Sep 17 00:00:00 2001 From: liwaner Date: Sat, 21 Dec 2024 18:43:03 +0800 Subject: [PATCH 01/11] Add Resetstack --- .../Controls/ActionBar/Resetstack.js | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 src/components/Controls/ActionBar/Resetstack.js diff --git a/src/components/Controls/ActionBar/Resetstack.js b/src/components/Controls/ActionBar/Resetstack.js new file mode 100644 index 00000000..f0720ac5 --- /dev/null +++ b/src/components/Controls/ActionBar/Resetstack.js @@ -0,0 +1,114 @@ +import { userGrid } from '@sudoku/stores/grid'; +import { SUDOKU_SIZE } from '@sudoku/constants'; +import { writable } from 'svelte/store'; +import { candidates } from '@sudoku/stores/candidates'; + +// 命令栈 +function createCommandStack() { + const stack = writable([]); + + return { + subscribe: stack.subscribe, + + push(value) { + stack.update($stack => { + $stack.push(value); + return $stack; + }); + }, + + // 有返回值 + popAndUndoIfValid() { + let item_from_undo_return; + stack.update($stack => { + if ($stack.length === 0) + return $stack; + + item_from_undo_return = $stack[$stack.length - 1].undo(); + return $stack; + }); + return item_from_undo_return; + }, + } +} +export const commandStack = new createCommandStack(); + +// 命令基类 +//export function CommandBase() { +// this.undo = function() {} +//}; + +// "x, y" to {x, y} +function convertCandidateStringToObject(str) { + const parts = str.split(','); + if (parts.length !== 2) { + return {}; + } + const x = parseInt(parts[0], 10); + const y = parseInt(parts[1], 10); + return {x, y}; +} + +// 回溯命令 +export function ResetCommand(grid_bk, candidates_bk, try_number, cell_index){ + this.grid_bk = grid_bk; + this.candidates_bk = candidates_bk; + + this.undo = function() { + // 重置网格 + for (let y = 0; y < SUDOKU_SIZE; y++) { + for (let x = 0; x < SUDOKU_SIZE; x++) { + userGrid.set({y, x}, grid_bk[y][x]); + } + } + + // 清空所有候选值 + for (let y = 0; y < SUDOKU_SIZE; y++) { + for (let x = 0; x < SUDOKU_SIZE; x++) { + candidates.clear({y, x}); + } + } + // 重置候选值 + for (let [key, value] of Object.entries(this.candidates_bk)) { + let pos = convertCandidateStringToObject(key); + candidates.clear(pos); + for (let i of value) + candidates.add(pos, i); + } + + // 返回错误数字和cell索引 + return {try_number, cell_index}; + }; +} + +// 复制当前userGrid($userGrid会自动更新,不能用$userGrid传值) +export function copyUserGrid(grid) { + let newGrid = []; + for (let y = 0; y < SUDOKU_SIZE; y++) { + newGrid[y] = []; + for (let x = 0; x < SUDOKU_SIZE; x++) { + newGrid[y][x] = grid[y][x]; + } + } + return newGrid; +} +// 复制当前candidates($candidates会自动更新,不能用$candidates传值) +export function copyCandidates(candidates) { + let newCandidates = {}; + for (let [key, value] of Object.entries(candidates)) { + newCandidates[key] = value; + } + return newCandidates; +} + +// function handleReset() { +// $commandStack.push(new ResetCommand(copyUserGrid(), copyCandidates())); +// +// // set value method +// userGrid.set({x:0, y:1}, 10);// ok +// candidates.add({x:0, y:0}, 1); +// } +// function handleReset1() { +// let i = commandStack.popAndUndoIfValid(); +// console.log("i: ", i); +// } \ No newline at end of file From ad031f82a890101f684d9a7fad777261d3a5ad85 Mon Sep 17 00:00:00 2001 From: liwaner Date: Sat, 21 Dec 2024 18:43:57 +0800 Subject: [PATCH 02/11] New reset command in keyboard input --- src/components/Controls/Keyboard.svelte | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/Controls/Keyboard.svelte b/src/components/Controls/Keyboard.svelte index f0e7a90b..98466265 100644 --- a/src/components/Controls/Keyboard.svelte +++ b/src/components/Controls/Keyboard.svelte @@ -3,6 +3,7 @@ import { cursor } from '@sudoku/stores/cursor'; import { notes } from '@sudoku/stores/notes'; import { candidates } from '@sudoku/stores/candidates'; + import { commandStack, ResetCommand, copyCandidates, copyUserGrid } from './ActionBar/Resetstack' // TODO: Improve keyboardDisabled import { keyboardDisabled } from '@sudoku/stores/keyboard'; @@ -17,6 +18,11 @@ } userGrid.set($cursor, 0); } else { + // 多候选值输入,启用回溯功能 + if ($candidates.hasOwnProperty($cursor.x + ',' + $cursor.y) && $candidates[$cursor.x + ',' + $cursor.y].length > 1) { + $commandStack.push(new ResetCommand(copyUserGrid($userGrid), copyCandidates($candidates), num, {'x': $cursor.x, 'y': $cursor.y})); + } + if ($candidates.hasOwnProperty($cursor.x + ',' + $cursor.y)) { candidates.clear($cursor); } From 20d996472db352fe23991e97b7f7db1d4644d360 Mon Sep 17 00:00:00 2001 From: liwaner Date: Sat, 21 Dec 2024 20:03:45 +0800 Subject: [PATCH 03/11] Add NumberKeyboard --- src/components/Controls/Keyboard.svelte | 51 +++++++++++-------- src/components/Controls/NumberKeyboard.svelte | 41 +++++++++++++++ 2 files changed, 70 insertions(+), 22 deletions(-) create mode 100644 src/components/Controls/NumberKeyboard.svelte diff --git a/src/components/Controls/Keyboard.svelte b/src/components/Controls/Keyboard.svelte index 98466265..c8c06f91 100644 --- a/src/components/Controls/Keyboard.svelte +++ b/src/components/Controls/Keyboard.svelte @@ -7,30 +7,34 @@ // TODO: Improve keyboardDisabled import { keyboardDisabled } from '@sudoku/stores/keyboard'; + import NumberKeyboard from './NumberKeyboard.svelte'; function handleKeyButton(num) { - if (!$keyboardDisabled) { - if ($notes) { - if (num === 0) { - candidates.clear($cursor); - } else { - candidates.add($cursor, num); - } - userGrid.set($cursor, 0); - } else { - // 多候选值输入,启用回溯功能 - if ($candidates.hasOwnProperty($cursor.x + ',' + $cursor.y) && $candidates[$cursor.x + ',' + $cursor.y].length > 1) { - $commandStack.push(new ResetCommand(copyUserGrid($userGrid), copyCandidates($candidates), num, {'x': $cursor.x, 'y': $cursor.y})); - } - - if ($candidates.hasOwnProperty($cursor.x + ',' + $cursor.y)) { - candidates.clear($cursor); - } - - userGrid.set($cursor, num); - } - } + candidates.clear($cursor); } +// function handleKeyButton(num) { +// if (!$keyboardDisabled) { +// if ($notes) { +// if (num === 0) { +// candidates.clear($cursor); +// } else { +// candidates.add($cursor, num); +// } +// userGrid.set($cursor, 0); +// } else { +// // 多候选值输入,启用回溯功能 +// if ($candidates.hasOwnProperty($cursor.x + ',' + $cursor.y) && $candidates[$cursor.x + ',' + $cursor.y].length > 1) { +// $commandStack.push(new ResetCommand(copyUserGrid($userGrid), copyCandidates($candidates), num, {'x': $cursor.x, 'y': $cursor.y})); +// } +// +// if ($candidates.hasOwnProperty($cursor.x + ',' + $cursor.y)) { +// candidates.clear($cursor); +// } +// +// userGrid.set($cursor, num); +// } +// } +// } function handleKey(e) { switch (e.key || e.keyCode) { @@ -92,9 +96,12 @@ {:else} - \ No newline at end of file From b25499f3e143870ea944494354019ddbcd235797 Mon Sep 17 00:00:00 2001 From: liwaner Date: Sat, 4 Jan 2025 13:50:27 +0800 Subject: [PATCH 04/11] Reconstruct StackManager --- .../Controls/ActionBar/Actions.svelte | 24 ++- .../Controls/ActionBar/Resetstack.js | 194 +++++++++++++++--- src/components/Controls/Keyboard.svelte | 1 - src/components/Controls/NumberKeyboard.svelte | 8 +- 4 files changed, 188 insertions(+), 39 deletions(-) diff --git a/src/components/Controls/ActionBar/Actions.svelte b/src/components/Controls/ActionBar/Actions.svelte index 2fdaee54..31b7e2e0 100644 --- a/src/components/Controls/ActionBar/Actions.svelte +++ b/src/components/Controls/ActionBar/Actions.svelte @@ -7,6 +7,7 @@ import { settings } from '@sudoku/stores/settings'; import { keyboardDisabled } from '@sudoku/stores/keyboard'; import { gamePaused } from '@sudoku/stores/game'; + import { StackManager } from './Resetstack' $: hintsAvailable = $hints > 0; @@ -19,17 +20,36 @@ userGrid.applyHint($cursor); } } + function handleUndo() { + console.log("handleUndo"); + StackManager.undo(); + } + function handleRedo() { + console.log("handleRedo"); + StackManager.redo(); + } + function handleReset() { + console.log("handleReset"); + while (["ResetCommand", ""].indexOf(StackManager.undo()) === -1) {} + }
- + + -