@my-games/sudoku-core 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -6
- package/dist/board.d.ts +63 -0
- package/dist/board.d.ts.map +1 -0
- package/dist/game.d.ts +95 -0
- package/dist/game.d.ts.map +1 -0
- package/dist/generator.d.ts +28 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/index.cjs +821 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.iife.js +821 -14
- package/dist/index.iife.js.map +1 -1
- package/dist/index.js +786 -13
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +821 -14
- package/dist/index.umd.js.map +1 -1
- package/dist/solver.d.ts +13 -0
- package/dist/solver.d.ts.map +1 -0
- package/dist/storage.d.ts +26 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/board.ts +182 -0
- package/src/game.ts +510 -0
- package/src/generator.ts +113 -0
- package/src/index.ts +67 -11
- package/src/solver.ts +95 -0
- package/src/storage.ts +115 -0
- package/src/style.css +366 -8
- package/src/types.ts +146 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sudoku 公共类型定义。
|
|
3
|
+
*
|
|
4
|
+
* 设计要点(对齐合集三层模板):
|
|
5
|
+
* - 棋盘是固定 9×9 的 `Grid`(`Cell[][]`,行优先);`Cell` = `0 | Digit`,`0` 表示空。
|
|
6
|
+
* - `givenMask` 标记题面给定的格(不可改),与 `grid` 分离,UI 据此禁用输入。
|
|
7
|
+
* - 纯逻辑运算(solver / generator / 测试)只用 `Grid`,不带可变的对局态。
|
|
8
|
+
* - `Sudoku` 类持有「当前这局」的完整可序列化快照 `GameState`,供订阅者渲染。
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** 一个可填入的数独数字。 */
|
|
12
|
+
export type Digit = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
|
13
|
+
|
|
14
|
+
/** 单元格值:`0` = 空,`1..9` = 已填。 */
|
|
15
|
+
export type Cell = Digit | 0;
|
|
16
|
+
|
|
17
|
+
/** 9×9 值网格,`grid[row][col]`。 */
|
|
18
|
+
export type Grid = Cell[][];
|
|
19
|
+
|
|
20
|
+
/** 题面难度;对应题面给定数字(clues)的目标区间。 */
|
|
21
|
+
export type Difficulty = 'easy' | 'medium' | 'hard';
|
|
22
|
+
|
|
23
|
+
/** 棋盘上的一个坐标。 */
|
|
24
|
+
export interface Position {
|
|
25
|
+
row: number;
|
|
26
|
+
col: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** 每格铅笔标记(候选笔记);仅在该格为空时有意义。 */
|
|
30
|
+
export type NoteGrid = Digit[][][];
|
|
31
|
+
|
|
32
|
+
/** 每格是否为「题面给定」(不可擦除/改写)。 */
|
|
33
|
+
export type GivenMask = boolean[][];
|
|
34
|
+
|
|
35
|
+
/** 每格当前是否处于冲突态(同行/列/宫有重复)。 */
|
|
36
|
+
export type ConflictMask = boolean[][];
|
|
37
|
+
|
|
38
|
+
export type GameStatus = 'playing' | 'won';
|
|
39
|
+
|
|
40
|
+
/** 订阅者可见的完整快照。字段全部可序列化,便于存档与 UI diff。 */
|
|
41
|
+
export interface GameState {
|
|
42
|
+
difficulty: Difficulty;
|
|
43
|
+
/** 当前值网格(题面 + 玩家填入),`0` 表示空。 */
|
|
44
|
+
grid: Grid;
|
|
45
|
+
/** 题面给定掩码;true 的格禁止改写。 */
|
|
46
|
+
givenMask: GivenMask;
|
|
47
|
+
/** 铅笔笔记:`notes[r][c]` 是该空格的候选数字数组(升序、去重)。 */
|
|
48
|
+
notes: NoteGrid;
|
|
49
|
+
/** 当前选中格;无选中为 null。 */
|
|
50
|
+
selected: Position | null;
|
|
51
|
+
/** 当前与同行/列/宫重复的格标记,供 UI 红框。 */
|
|
52
|
+
conflicts: ConflictMask;
|
|
53
|
+
status: GameStatus;
|
|
54
|
+
/** 已用时(秒,向下取整);`won` 时定格在完成瞬间。 */
|
|
55
|
+
elapsedSeconds: number;
|
|
56
|
+
/** 该难度的历史最佳用时(秒);无则 null。 */
|
|
57
|
+
bestSeconds: number | null;
|
|
58
|
+
/** 本局已用提示次数。 */
|
|
59
|
+
hintCount: number;
|
|
60
|
+
/** 本局已犯错误次数(填了与盘面冲突的值)。 */
|
|
61
|
+
mistakeCount: number;
|
|
62
|
+
/** 本局有效操作数(input/erase/hint 各算一步,撤销不计,切选中不算)。 */
|
|
63
|
+
moveCount: number;
|
|
64
|
+
/** 可撤销栈深度;>0 时 UI 可点亮「撤销」。 */
|
|
65
|
+
historySize: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** 一局的可回退快照(不含派生态与计时,undo 时整体还原)。 */
|
|
69
|
+
export interface Snapshot {
|
|
70
|
+
grid: Grid;
|
|
71
|
+
notes: NoteGrid;
|
|
72
|
+
selected: Position | null;
|
|
73
|
+
status: GameStatus;
|
|
74
|
+
hintCount: number;
|
|
75
|
+
mistakeCount: number;
|
|
76
|
+
moveCount: number;
|
|
77
|
+
/** 该快照生成时刻已累计的用时(ms),用于 undo 后计时口径一致。 */
|
|
78
|
+
elapsedMs: number;
|
|
79
|
+
/** 计表是否已起算(首次填充后置 true);undo 回未起算态则归位 false。 */
|
|
80
|
+
started: boolean;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** 序列化存档;版本化字段演进策略见 storage.ts。 */
|
|
84
|
+
export interface SerializedSave {
|
|
85
|
+
version: 1;
|
|
86
|
+
difficulty: Difficulty;
|
|
87
|
+
/** 题面(含 0),用于校验存档与当前局是否同一道题。 */
|
|
88
|
+
puzzle: Grid;
|
|
89
|
+
/** 完整解,用于提示与 reveal(不入 undo,单独随存档走)。 */
|
|
90
|
+
solution: Grid;
|
|
91
|
+
grid: Grid;
|
|
92
|
+
notes: NoteGrid;
|
|
93
|
+
status: GameStatus;
|
|
94
|
+
hintCount: number;
|
|
95
|
+
mistakeCount: number;
|
|
96
|
+
moveCount: number;
|
|
97
|
+
/** 存档时刻已累计用时(ms),恢复后从此继续走表。 */
|
|
98
|
+
elapsedMs: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** 各难度的历史最佳用时(秒);null = 该难度尚未通关。 */
|
|
102
|
+
export type BestTimes = Record<Difficulty, number | null>;
|
|
103
|
+
|
|
104
|
+
/** 简易 RNG 契约:返回 [0, 1)。注入是为了单测可复现。 */
|
|
105
|
+
export type RandomSource = () => number;
|
|
106
|
+
|
|
107
|
+
/** 简易时钟契约:返回单调毫秒(Date.now 语义)。注入以便测试计时。 */
|
|
108
|
+
export type Clock = () => number;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* `Sudoku` 构造参数。全部可选,缺省即「易难度 + Math.random + Date.now +
|
|
112
|
+
* 尝试接管 globalThis.localStorage」。
|
|
113
|
+
*/
|
|
114
|
+
export interface GameOptions {
|
|
115
|
+
/** 谜题难度,默认 'easy'。newGame 可临时覆盖。 */
|
|
116
|
+
difficulty?: Difficulty;
|
|
117
|
+
/** 随机源([0,1));注入以便生成与单测可复现。 */
|
|
118
|
+
rng?: RandomSource;
|
|
119
|
+
/** 时钟(ms);注入以便测试计时与最佳用时。 */
|
|
120
|
+
clock?: Clock;
|
|
121
|
+
/**
|
|
122
|
+
* 存储后端。`undefined` → 尝试取 globalThis.localStorage;
|
|
123
|
+
* `null` → 明确禁用;也可注入自实现的 SaveStorage mock。
|
|
124
|
+
*/
|
|
125
|
+
storage?: SaveStorage | null;
|
|
126
|
+
saveKey?: string;
|
|
127
|
+
bestKey?: string;
|
|
128
|
+
/** 构造时忽略已有存档,直接开新局。 */
|
|
129
|
+
freshStart?: boolean;
|
|
130
|
+
/** 固定题面(含 0 空格):给定时用它而非现场生成(固定题 / 测试场景)。 */
|
|
131
|
+
puzzle?: Grid;
|
|
132
|
+
/** 配合 puzzle 给出已知解,省去求解;缺省则由 solve 推导。 */
|
|
133
|
+
solution?: Grid;
|
|
134
|
+
/** undo 栈深度上限,默认 50。 */
|
|
135
|
+
undoLimit?: number;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 最小可注入的存储抽象(与 DOM Storage 兼容,允许 Node 环境注入 mock)。
|
|
140
|
+
* `null` 表示禁用持久化。
|
|
141
|
+
*/
|
|
142
|
+
export interface SaveStorage {
|
|
143
|
+
getItem(key: string): string | null;
|
|
144
|
+
setItem(key: string, value: string): void;
|
|
145
|
+
removeItem(key: string): void;
|
|
146
|
+
}
|