Skip to content

Feature reset1 #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,286 changes: 4,286 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
"@rollup/plugin-node-resolve": "10.0.0",
"autoprefixer": "10.0.2",
"inline-critical": "6.0.1",
"postcss": "8.4.31",
"postcss": "^8.4.14",
"postcss-clean": "1.1.0",
"postcss-import": "13.0.0",
"postcss-load-config": "3.0.0",
"postcss-load-config": "^2.1.0",
"reaver": "2.0.0",
"rimraf": "3.0.2",
"rollup": "2.33.3",
Expand Down
2 changes: 1 addition & 1 deletion src/components/Board/Candidates.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

<style>
.candidate-grid {
@apply grid h-full w-full p-1;
@apply bg-yellow-200 grid h-full w-full p-1;
}

.candidate {
Expand Down
4 changes: 3 additions & 1 deletion src/components/Board/Cell.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import { fade } from 'svelte/transition';
import { SUDOKU_SIZE } from '@sudoku/constants';
import { cursor } from '@sudoku/stores/cursor';
import { settings } from '@sudoku/stores/settings';

export let value;
export let cellX;
export let cellY;
export let candidates;
export let candidatesCount;

export let disabled;
export let conflictingNumber;
Expand Down Expand Up @@ -37,7 +39,7 @@
class:conflicting-number={conflictingNumber}>

<button class="cell-btn" on:click={cursor.set(cellX - 1, cellY - 1)}>
{#if candidates}
{#if candidates && candidatesCount <= $settings.hintsStep}
<Candidates {candidates} />
{:else}
<span class="cell-text">{value || ''}</span>
Expand Down
3 changes: 2 additions & 1 deletion src/components/Board/index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { grid, userGrid, invalidCells } from '@sudoku/stores/grid';
import { settings } from '@sudoku/stores/settings';
import { cursor } from '@sudoku/stores/cursor';
import { candidates } from '@sudoku/stores/candidates';
import { candidates, candidatesCnt } from '@sudoku/stores/candidates';
import Cell from './Cell.svelte';

function isSelected(cursorStore, x, y) {
Expand Down Expand Up @@ -43,6 +43,7 @@
cellY={y + 1}
cellX={x + 1}
candidates={$candidates[x + ',' + y]}
candidatesCount = {$candidatesCnt[x + ',' + y]}
disabled={$gamePaused}
selected={isSelected($cursor, x, y)}
userNumber={$grid[y][x] === 0}
Expand Down
51 changes: 40 additions & 11 deletions src/components/Controls/ActionBar/Actions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,64 @@
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;
import { strategyManager } from '@sudoku/sudokuStrategies/StrategyManager'
import { ResetTree } from '@sudoku/Resettree';

function handleHint() {
if (hintsAvailable) {
if ($candidates.hasOwnProperty($cursor.x + ',' + $cursor.y)) {
candidates.clear($cursor);
}
$: hintsAvailable = $hints > 0;

userGrid.applyHint($cursor);
}
function handleHint() {
let candidatesList = strategyManager.applyStrategies($userGrid);
for(let row = 0; row < 9; row++) {
for(let col = 0; col < 9; col++) {
candidates.clear({x: col, y: row});
if($userGrid[row][col] === 0) {
candidatesList[row][col].forEach((num) => {
candidates.add({x: col, y: row}, num);
});
}
}
}
}

function handleUndo() {
console.log("handleUndo");
//StackManager.undo();
ResetTree.undo();
}
function handleRedo() {
console.log("handleRedo");
//StackManager.redo();
ResetTree.redo();
}
function handleReset() {
console.log("handleReset - Reset to branch point");
ResetTree.reset();
}
</script>

<div class="action-buttons space-x-3">

<button class="btn btn-round" disabled={$gamePaused} title="Undo">
<button class="btn btn-round" disabled={$gamePaused} title="Reset" on:click={handleReset}>
<svg class="icon-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
</button>

<button class="btn btn-round" disabled={$gamePaused} title="Undo" on:click={handleUndo}>
<svg class="icon-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6" />
</svg>
</button>

<button class="btn btn-round" disabled={$gamePaused} title="Redo">
<button class="btn btn-round" disabled={$gamePaused} title="Redo" on:click={handleRedo}>
<svg class="icon-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 10h-10a8 8 90 00-8 8v2M21 10l-6 6m6-6l-6-6" />
</svg>
</button>

<button class="btn btn-round btn-badge" disabled={$keyboardDisabled || !hintsAvailable || $userGrid[$cursor.y][$cursor.x] !== 0} on:click={handleHint} title="Hints ({$hints})">
<button class="btn btn-round btn-badge" on:click={handleHint} title="Hints ({$hints})">
<svg class="icon-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
</svg>
Expand Down
249 changes: 249 additions & 0 deletions src/components/Controls/ActionBar/Resetstack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
import { userGrid } from '@sudoku/stores/grid';
import { candidates } from '@sudoku/stores/candidates';
import { SUDOKU_SIZE } from '@sudoku/constants';
import { writable } from 'svelte/store';

// 回溯错误值
export let errorValue = {"number": undefined, "index": {}}; //number: int; index: {"x": 0, "y": 0}

// 命令栈
function createCommandStack() {
const stack = writable([]);

return {
subscribe: stack.subscribe,

canDo() {
let result;
stack.update($stack => {
result = $stack.length != 0;
return $stack;
});
return result;
},

clear() {
stack.update(() => {
return [];
});
},

push(value) {
stack.update($stack => {
$stack.push(value);
return $stack;
});
},

pop() {
let top_command;
stack.update($stack => {
if ($stack.length === 0)
return $stack;

top_command = $stack[$stack.length - 1];
$stack.pop();
return $stack;
});
return top_command;
},

// 有返回值
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;
},
}
}
// 撤销恢复栈管理
function createStackManager() {
let undostack = new createCommandStack();
let redostack = new createCommandStack();

return {

pushCmd(cmd) {
console.log("cmd: ", cmd);
undostack.push(cmd);
redostack.clear();
},

undo() {
if (!undostack.canDo())
return "";

let undo_cmd = undostack.pop();
let res = undo_cmd.undo();
redostack.push(undo_cmd);
console.log("undo done");
return res;
},

redo() {
if (!redostack.canDo())
return "";

let redo_cmd = redostack.pop();
let res = redo_cmd.redo();
undostack.push(redo_cmd);
console.log("redo done");
return res;
},

hasResetPoint() {
// 检查栈中是否有ResetCommand
let hasReset = false;
undostack.subscribe(stack => {
hasReset = stack.some(cmd => cmd.name === "ResetCommand");
});
return hasReset;
}
}
}
export const StackManager = createStackManager();

// "x, y" to {x, y}
function convertCandidateStringToObject(str) {
console.log("str: ", 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 resetUserGrid(grid) {
for (let y = 0; y < SUDOKU_SIZE; y++) {
for (let x = 0; x < SUDOKU_SIZE; x++) {
userGrid.set({y, x}, grid[y][x]);
}
}
}

export function resetCandidates(candidates_bk){
// 清空所有候选值
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(candidates_bk)) {
let pos = convertCandidateStringToObject(key);
candidates.clear(pos);
for (let i of value)
candidates.add(pos, i);
}
}

// 复制当前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] = [];
for (let i = 0; i < value.length; i++) {
newCandidates[key].push(value[i])
}
}
return newCandidates;
}

// 回溯命令
export function ResetCommand(grid_bk, candidates_bk, try_number, cell_index){
this.number = try_number;
this.index = cell_index;
this.grid_bk = grid_bk;
this.candidates_bk = candidates_bk;
this.name = "ResetCommand";

this.undo = function(){
console.log("ResetCommand undo");
resetUserGrid(this.grid_bk);
resetCandidates(this.candidates_bk);

[errorValue["number"], this.number] = [this.number, errorValue["number"]];
[errorValue["index"], this.index] = [this.index, errorValue["index"]];
console.log("errorValue: ", errorValue);

return this.name;
};

this.redo = function() {}
}

// 填写cell数字
export function SetValueCommand(grid_bk, candidates_bk, try_number, cell_index){
this.number = try_number;
this.index = cell_index;
this.grid_bk = grid_bk;
this.candidates_bk = candidates_bk;
this.name = "SetValueCommand";

this.undo = function(){
console.log("SetvalueCommand undo");
resetUserGrid(this.grid_bk);
resetCandidates(this.candidates_bk);
return this.name;
};

this.redo = function(){
console.log("SetvalueCommand redo");
userGrid.set(this.index, this.number);

return this.name;
}
}

// 填写note数字
export function SetNoteCommand(grid_bk, candidates_bk, try_number, cell_index){
this.number = try_number;
this.index = cell_index;
this.grid_bk = grid_bk;
this.candidates_bk = candidates_bk;
this.name = "SetNoteCommand";

this.undo = function(){
console.log("SetNoteCommand undo");
resetUserGrid(this.grid_bk);
resetCandidates(this.candidates_bk);
return this.name;
};

this.redo = function(){
console.log("SetNoteCommand redo");
candidates.add(this.index, this.number)
return this.name;
}
}
// 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);
// }
Loading