@my-games/2048-vue 0.1.0 → 0.2.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/dist/index.js CHANGED
@@ -1,251 +1,333 @@
1
- import { shallowRef as ae, onBeforeUnmount as O, defineComponent as le, ref as h, onMounted as ie, watch as N, computed as m, openBlock as l, createElementBlock as i, createElementVNode as a, toDisplayString as f, unref as u, createCommentVNode as c, createTextVNode as R, withModifiers as ue, normalizeStyle as U, Fragment as W, renderList as Y, mergeProps as re, normalizeClass as ce } from "vue";
2
- import { Game2048 as de, bestMove as F } from "@my-games/2048-core";
3
- function ve(d = {}) {
4
- const { aiDepth: w = 3, ..._ } = d, n = new de(_), v = ae(n.getState()), s = n.subscribe((r) => {
5
- v.value = r;
6
- });
7
- return O(s), {
8
- state: v,
9
- raw: n,
10
- move: (r) => n.move(r),
11
- newGame: () => n.newGame(),
12
- undo: () => n.undo(),
13
- continuePlaying: () => n.continuePlaying(),
14
- canUndo: () => n.canUndo(),
15
- suggestMove: () => F(n.getGridValues(), { depth: w }),
16
- aiMove: () => {
17
- const r = F(n.getGridValues(), { depth: w });
18
- return r && n.move(r), r;
19
- }
20
- };
1
+ import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, mergeProps, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, shallowRef, toDisplayString, unref, watch, withModifiers } from "vue";
2
+ import { Game2048, bestMove } from "@my-games/2048-core";
3
+ // src/useGame.ts
4
+ function useGame(options = {}) {
5
+ const { aiDepth = 3, ...engineOptions } = options;
6
+ const game = new Game2048(engineOptions);
7
+ const state = shallowRef(game.getState());
8
+ const unsubscribe = game.subscribe((s) => {
9
+ state.value = s;
10
+ });
11
+ onBeforeUnmount(unsubscribe);
12
+ return {
13
+ state,
14
+ raw: game,
15
+ move: (dir) => game.move(dir),
16
+ newGame: () => game.newGame(),
17
+ undo: () => game.undo(),
18
+ continuePlaying: () => game.continuePlaying(),
19
+ canUndo: () => game.canUndo(),
20
+ suggestMove: () => bestMove(game.getGridValues(), { depth: aiDepth }),
21
+ aiMove: () => {
22
+ const dir = bestMove(game.getGridValues(), { depth: aiDepth });
23
+ if (dir) game.move(dir);
24
+ return dir;
25
+ }
26
+ };
21
27
  }
22
- const me = { class: "game-2048" }, fe = {
23
- key: 0,
24
- class: "game-2048-header"
25
- }, be = { class: "game-2048-title" }, ge = { class: "game-2048-scores" }, ye = { class: "game-2048-score-box" }, pe = { class: "value" }, he = { class: "game-2048-score-box" }, we = { class: "value" }, ke = { class: "game-2048-toolbar" }, _e = { class: "game-2048-actions" }, Se = ["disabled"], Ae = ["disabled"], xe = ["disabled"], De = ["aria-label"], Te = { class: "game-2048-tile-layer" }, ze = ["data-value"], Ce = {
26
- key: 0,
27
- class: "game-2048-ai-indicator",
28
- style: { position: "absolute", top: "8px", left: "8px", "z-index": "3" }
29
- }, Me = { key: 0 }, Ee = { key: 1 }, Ge = { class: "row" }, Ke = /* @__PURE__ */ le({
30
- __name: "Game2048",
31
- props: {
32
- size: { default: 4 },
33
- storage: { default: void 0 },
34
- saveKey: { default: void 0 },
35
- bestKey: { default: void 0 },
36
- freshStart: { type: Boolean, default: !1 },
37
- autofocus: { type: Boolean, default: !0 },
38
- enableAI: { type: Boolean, default: !1 },
39
- aiDepth: { default: 3 },
40
- title: { default: "2048" }
41
- },
42
- emits: ["move", "won", "lost"],
43
- setup(d, { expose: w, emit: _ }) {
44
- const n = d, v = _, { state: s, move: r, newGame: S, undo: A, continuePlaying: T, suggestMove: z, aiMove: C } = ve({
45
- size: n.size,
46
- storage: n.storage,
47
- saveKey: n.saveKey,
48
- bestKey: n.bestKey,
49
- freshStart: n.freshStart,
50
- aiDepth: n.aiDepth
51
- }), k = h(null), b = h(null), g = h(null), M = h(s.value.score), E = h(s.value.status);
52
- let y;
53
- const X = {
54
- ArrowUp: "up",
55
- ArrowDown: "down",
56
- ArrowLeft: "left",
57
- ArrowRight: "right",
58
- w: "up",
59
- a: "left",
60
- s: "down",
61
- d: "right",
62
- W: "up",
63
- A: "left",
64
- S: "down",
65
- D: "right"
66
- };
67
- function H() {
68
- return typeof document > "u" ? !1 : document.activeElement === k.value;
69
- }
70
- function G(t) {
71
- const e = X[t.key];
72
- e && H() && (t.preventDefault(), I(e));
73
- }
74
- function I(t) {
75
- const e = s.value.score;
76
- r(t) && (v("move", t, s.value.score - e), n.enableAI && (g.value = null));
77
- }
78
- let x = null;
79
- function j(t) {
80
- var o;
81
- if (t.touches.length !== 1) return;
82
- const e = t.touches[0];
83
- e && (x = { x: e.clientX, y: e.clientY }, (o = k.value) == null || o.focus({ preventScroll: !0 }));
84
- }
85
- function q(t) {
86
- const e = x;
87
- if (x = null, !e) return;
88
- const o = t.changedTouches[0];
89
- if (!o) return;
90
- const V = o.clientX - e.x, $ = o.clientY - e.y, P = Math.abs(V), L = Math.abs($);
91
- if (Math.max(P, L) < 24) return;
92
- const ne = P > L ? V > 0 ? "right" : "left" : $ > 0 ? "down" : "up";
93
- I(ne);
94
- }
95
- ie(() => {
96
- var t;
97
- n.autofocus && ((t = k.value) == null || t.focus({ preventScroll: !0 })), window.addEventListener("keydown", G, { passive: !1 });
98
- }), O(() => {
99
- window.removeEventListener("keydown", G), y && window.clearTimeout(y);
100
- }), N(
101
- () => s.value.score,
102
- (t, e) => {
103
- const o = t - (e ?? M.value);
104
- o > 0 && (b.value = { amount: o, key: Date.now() + Math.random() }, y && window.clearTimeout(y), y = window.setTimeout(() => b.value = null, 700)), M.value = t;
105
- }
106
- ), N(
107
- () => s.value.status,
108
- (t) => {
109
- t !== E.value && (t === "won" ? v("won") : t === "lost" && v("lost"), E.value = t);
110
- }
111
- );
112
- const J = m(() => ({
113
- gridTemplateColumns: `repeat(${s.value.size}, 1fr)`,
114
- gridTemplateRows: `repeat(${s.value.size}, 1fr)`
115
- })), Q = m(() => ({ "--cols": String(s.value.size) }));
116
- function Z(t, e) {
117
- return { "--row": String(t), "--col": String(e) };
118
- }
119
- function ee(t) {
120
- return {
121
- "is-new": t.isNew,
122
- "is-merged": t.merged,
123
- "is-super": t.value > 2048
124
- };
125
- }
126
- function te(t) {
127
- return t.value > 2048 ? { "data-super": "1" } : {};
128
- }
129
- const B = m(() => s.value.status !== "playing"), D = m(() => s.value.status === "won"), p = m(() => s.value.status === "lost"), K = m(() => s.value.historySize === 0);
130
- function oe() {
131
- g.value = z();
132
- }
133
- function se() {
134
- const t = s.value.score, e = C();
135
- e && (v("move", e, s.value.score - t), g.value = null);
136
- }
137
- return w({ suggestMove: z, aiMove: C, newGame: S, undo: A, move: r, continuePlaying: T }), (t, e) => (l(), i("div", me, [
138
- d.title ? (l(), i("header", fe, [
139
- a("h1", be, f(d.title), 1),
140
- a("div", ge, [
141
- a("div", ye, [
142
- e[5] || (e[5] = a("span", { class: "label" }, "Score", -1)),
143
- a("span", pe, f(u(s).score), 1),
144
- b.value ? (l(), i("span", {
145
- key: b.value.key,
146
- class: "delta"
147
- }, "+" + f(b.value.amount), 1)) : c("", !0)
148
- ]),
149
- a("div", he, [
150
- e[6] || (e[6] = a("span", { class: "label" }, "Best", -1)),
151
- a("span", we, f(u(s).bestScore), 1)
152
- ])
153
- ])
154
- ])) : c("", !0),
155
- a("div", ke, [
156
- e[7] || (e[7] = a("p", { class: "game-2048-desc" }, [
157
- R(" 合并相同数字,冲过 "),
158
- a("b", null, "2048"),
159
- R("。方向键 / WASD / 触屏滑动。 ")
160
- ], -1)),
161
- a("div", _e, [
162
- d.enableAI ? (l(), i("button", {
163
- key: 0,
164
- class: "game-2048-button",
165
- type: "button",
166
- disabled: p.value,
167
- onClick: oe
168
- }, " 提示 ", 8, Se)) : c("", !0),
169
- d.enableAI ? (l(), i("button", {
170
- key: 1,
171
- class: "game-2048-button",
172
- type: "button",
173
- disabled: p.value,
174
- onClick: se
175
- }, " AI 帮走 ", 8, Ae)) : c("", !0),
176
- a("button", {
177
- class: "game-2048-button",
178
- type: "button",
179
- disabled: K.value,
180
- onClick: e[0] || (e[0] = (o) => u(A)())
181
- }, " 撤销 ", 8, xe),
182
- a("button", {
183
- class: "game-2048-button is-primary",
184
- type: "button",
185
- onClick: e[1] || (e[1] = (o) => u(S)())
186
- }, " 新游戏 ")
187
- ])
188
- ]),
189
- a("div", {
190
- ref_key: "boardEl",
191
- ref: k,
192
- class: "game-2048-board",
193
- style: U(Q.value),
194
- tabindex: "0",
195
- role: "application",
196
- "aria-label": `2048 游戏板 ${u(s).status}`,
197
- onTouchstartPassive: j,
198
- onTouchend: ue(q, ["prevent"])
199
- }, [
200
- a("div", {
201
- class: "game-2048-grid",
202
- style: U(J.value)
203
- }, [
204
- (l(!0), i(W, null, Y(u(s).size * u(s).size, (o) => (l(), i("div", {
205
- key: o,
206
- class: "game-2048-cell"
207
- }))), 128))
208
- ], 4),
209
- a("div", Te, [
210
- (l(!0), i(W, null, Y(u(s).tiles, (o) => (l(), i("div", re({
211
- key: o.id,
212
- class: ["game-2048-tile", ee(o)],
213
- style: Z(o.row, o.col),
214
- "data-value": o.value
215
- }, { ref_for: !0 }, te(o)), f(o.value), 17, ze))), 128))
216
- ]),
217
- d.enableAI && g.value ? (l(), i("div", Ce, " 推荐:" + f(g.value), 1)) : c("", !0),
218
- a("div", {
219
- class: ce(["game-2048-overlay", { "is-visible": B.value, "is-won": D.value, "is-lost": p.value }])
220
- }, [
221
- D.value ? (l(), i("h2", Me, "你赢了!")) : p.value ? (l(), i("h2", Ee, "游戏结束")) : c("", !0),
222
- a("div", Ge, [
223
- D.value ? (l(), i("button", {
224
- key: 0,
225
- class: "game-2048-button",
226
- type: "button",
227
- onClick: e[2] || (e[2] = (o) => u(T)())
228
- }, " 继续游戏 ")) : c("", !0),
229
- p.value && !K.value ? (l(), i("button", {
230
- key: 1,
231
- class: "game-2048-button",
232
- type: "button",
233
- onClick: e[3] || (e[3] = (o) => u(A)())
234
- }, " 悔一步 ")) : c("", !0),
235
- B.value ? (l(), i("button", {
236
- key: 2,
237
- class: "game-2048-button is-primary",
238
- type: "button",
239
- onClick: e[4] || (e[4] = (o) => u(S)())
240
- }, " 再来一局 ")) : c("", !0)
241
- ])
242
- ], 2)
243
- ], 44, De)
244
- ]));
245
- }
246
- });
247
- export {
248
- Ke as Game2048,
249
- ve as useGame
28
+ // src/Game2048.vue?vue&type=script&setup=true&lang.ts
29
+ var _hoisted_1 = { class: "game-2048" };
30
+ var _hoisted_2 = {
31
+ key: 0,
32
+ class: "game-2048-header"
33
+ };
34
+ var _hoisted_3 = { class: "game-2048-title" };
35
+ var _hoisted_4 = { class: "game-2048-scores" };
36
+ var _hoisted_5 = { class: "game-2048-score-box" };
37
+ var _hoisted_6 = { class: "value" };
38
+ var _hoisted_7 = { class: "game-2048-score-box" };
39
+ var _hoisted_8 = { class: "value" };
40
+ var _hoisted_9 = { class: "game-2048-toolbar" };
41
+ var _hoisted_10 = { class: "game-2048-actions" };
42
+ var _hoisted_11 = ["disabled"];
43
+ var _hoisted_12 = ["disabled"];
44
+ var _hoisted_13 = ["disabled"];
45
+ var _hoisted_14 = ["aria-label"];
46
+ var _hoisted_15 = { class: "game-2048-tile-layer" };
47
+ var _hoisted_16 = ["data-value"];
48
+ var _hoisted_17 = {
49
+ key: 0,
50
+ class: "game-2048-ai-indicator",
51
+ style: {
52
+ "position": "absolute",
53
+ "top": "8px",
54
+ "left": "8px",
55
+ "z-index": "3"
56
+ }
250
57
  };
251
- //# sourceMappingURL=index.js.map
58
+ var _hoisted_18 = { key: 0 };
59
+ var _hoisted_19 = { key: 1 };
60
+ var _hoisted_20 = { class: "row" };
61
+ // src/Game2048.vue
62
+ var Game2048_default = /* @__PURE__ */ defineComponent({
63
+ __name: "Game2048",
64
+ props: {
65
+ size: { default: 4 },
66
+ storage: { default: void 0 },
67
+ saveKey: { default: void 0 },
68
+ bestKey: { default: void 0 },
69
+ freshStart: {
70
+ type: Boolean,
71
+ default: false
72
+ },
73
+ autofocus: {
74
+ type: Boolean,
75
+ default: true
76
+ },
77
+ enableAI: {
78
+ type: Boolean,
79
+ default: false
80
+ },
81
+ aiDepth: { default: 3 },
82
+ title: { default: "2048" }
83
+ },
84
+ emits: [
85
+ "move",
86
+ "won",
87
+ "lost"
88
+ ],
89
+ setup(__props, { expose: __expose, emit: __emit }) {
90
+ const props = __props;
91
+ const emit = __emit;
92
+ const { state, move, newGame, undo, continuePlaying, suggestMove, aiMove } = useGame({
93
+ size: props.size,
94
+ storage: props.storage,
95
+ saveKey: props.saveKey,
96
+ bestKey: props.bestKey,
97
+ freshStart: props.freshStart,
98
+ aiDepth: props.aiDepth
99
+ });
100
+ const boardEl = ref(null);
101
+ const scoreDelta = ref(null);
102
+ const aiHint = ref(null);
103
+ const lastScore = ref(state.value.score);
104
+ const lastStatus = ref(state.value.status);
105
+ let deltaTimer;
106
+ const KEY_TO_DIR = {
107
+ ArrowUp: "up",
108
+ ArrowDown: "down",
109
+ ArrowLeft: "left",
110
+ ArrowRight: "right",
111
+ w: "up",
112
+ a: "left",
113
+ s: "down",
114
+ d: "right",
115
+ W: "up",
116
+ A: "left",
117
+ S: "down",
118
+ D: "right"
119
+ };
120
+ function isBoardFocused() {
121
+ if (typeof document === "undefined") return false;
122
+ return document.activeElement === boardEl.value;
123
+ }
124
+ function onKey(ev) {
125
+ const dir = KEY_TO_DIR[ev.key];
126
+ if (!dir) return;
127
+ if (!isBoardFocused()) return;
128
+ ev.preventDefault();
129
+ performMove(dir);
130
+ }
131
+ function performMove(dir) {
132
+ const before = state.value.score;
133
+ if (move(dir)) {
134
+ emit("move", dir, state.value.score - before);
135
+ if (props.enableAI) aiHint.value = null;
136
+ }
137
+ }
138
+ let touchStartPoint = null;
139
+ function onTouchStart(ev) {
140
+ if (ev.touches.length !== 1) return;
141
+ const t = ev.touches[0];
142
+ if (!t) return;
143
+ touchStartPoint = {
144
+ x: t.clientX,
145
+ y: t.clientY
146
+ };
147
+ boardEl.value?.focus({ preventScroll: true });
148
+ }
149
+ function onTouchEnd(ev) {
150
+ const start = touchStartPoint;
151
+ touchStartPoint = null;
152
+ if (!start) return;
153
+ const t = ev.changedTouches[0];
154
+ if (!t) return;
155
+ const dx = t.clientX - start.x;
156
+ const dy = t.clientY - start.y;
157
+ const adx = Math.abs(dx);
158
+ const ady = Math.abs(dy);
159
+ if (Math.max(adx, ady) < 24) return;
160
+ performMove(adx > ady ? dx > 0 ? "right" : "left" : dy > 0 ? "down" : "up");
161
+ }
162
+ onMounted(() => {
163
+ if (props.autofocus) boardEl.value?.focus({ preventScroll: true });
164
+ window.addEventListener("keydown", onKey, { passive: false });
165
+ });
166
+ onBeforeUnmount(() => {
167
+ window.removeEventListener("keydown", onKey);
168
+ if (deltaTimer) window.clearTimeout(deltaTimer);
169
+ });
170
+ watch(() => state.value.score, (now, prev) => {
171
+ const gained = now - (prev ?? lastScore.value);
172
+ if (gained > 0) {
173
+ scoreDelta.value = {
174
+ amount: gained,
175
+ key: Date.now() + Math.random()
176
+ };
177
+ if (deltaTimer) window.clearTimeout(deltaTimer);
178
+ deltaTimer = window.setTimeout(() => scoreDelta.value = null, 700);
179
+ }
180
+ lastScore.value = now;
181
+ });
182
+ watch(() => state.value.status, (s) => {
183
+ if (s === lastStatus.value) return;
184
+ if (s === "won") emit("won");
185
+ else if (s === "lost") emit("lost");
186
+ lastStatus.value = s;
187
+ });
188
+ const gridStyle = computed(() => ({
189
+ gridTemplateColumns: `repeat(${state.value.size}, 1fr)`,
190
+ gridTemplateRows: `repeat(${state.value.size}, 1fr)`
191
+ }));
192
+ const boardVars = computed(() => ({ "--cols": String(state.value.size) }));
193
+ function tileVars(row, col) {
194
+ return {
195
+ "--row": String(row),
196
+ "--col": String(col)
197
+ };
198
+ }
199
+ function tileClass(t) {
200
+ return {
201
+ "is-new": t.isNew,
202
+ "is-merged": t.merged,
203
+ "is-super": t.value > 2048
204
+ };
205
+ }
206
+ function tileAttrs(t) {
207
+ return t.value > 2048 ? { "data-super": "1" } : {};
208
+ }
209
+ const overlayVisible = computed(() => state.value.status !== "playing");
210
+ const isWon = computed(() => state.value.status === "won");
211
+ const isLost = computed(() => state.value.status === "lost");
212
+ const undoDisabled = computed(() => state.value.historySize === 0);
213
+ function onAskAI() {
214
+ aiHint.value = suggestMove();
215
+ }
216
+ function onDoAI() {
217
+ const before = state.value.score;
218
+ const dir = aiMove();
219
+ if (dir) {
220
+ emit("move", dir, state.value.score - before);
221
+ aiHint.value = null;
222
+ }
223
+ }
224
+ __expose({
225
+ suggestMove,
226
+ aiMove,
227
+ newGame,
228
+ undo,
229
+ move,
230
+ continuePlaying
231
+ });
232
+ return (_ctx, _cache) => {
233
+ return openBlock(), createElementBlock("div", _hoisted_1, [
234
+ __props.title ? (openBlock(), createElementBlock("header", _hoisted_2, [createElementVNode("h1", _hoisted_3, toDisplayString(__props.title), 1), createElementVNode("div", _hoisted_4, [createElementVNode("div", _hoisted_5, [
235
+ _cache[5] || (_cache[5] = createElementVNode("span", { class: "label" }, "Score", -1)),
236
+ createElementVNode("span", _hoisted_6, toDisplayString(unref(state).score), 1),
237
+ scoreDelta.value ? (openBlock(), createElementBlock("span", {
238
+ key: scoreDelta.value.key,
239
+ class: "delta"
240
+ }, "+" + toDisplayString(scoreDelta.value.amount), 1)) : createCommentVNode("", true)
241
+ ]), createElementVNode("div", _hoisted_7, [_cache[6] || (_cache[6] = createElementVNode("span", { class: "label" }, "Best", -1)), createElementVNode("span", _hoisted_8, toDisplayString(unref(state).bestScore), 1)])])])) : createCommentVNode("", true),
242
+ createElementVNode("div", _hoisted_9, [_cache[7] || (_cache[7] = createElementVNode("p", { class: "game-2048-desc" }, [
243
+ createTextVNode(" 合并相同数字,冲过 "),
244
+ createElementVNode("b", null, "2048"),
245
+ createTextVNode("。方向键 / WASD / 触屏滑动。 ")
246
+ ], -1)), createElementVNode("div", _hoisted_10, [
247
+ __props.enableAI ? (openBlock(), createElementBlock("button", {
248
+ key: 0,
249
+ class: "game-2048-button",
250
+ type: "button",
251
+ disabled: isLost.value,
252
+ onClick: onAskAI
253
+ }, " 提示 ", 8, _hoisted_11)) : createCommentVNode("", true),
254
+ __props.enableAI ? (openBlock(), createElementBlock("button", {
255
+ key: 1,
256
+ class: "game-2048-button",
257
+ type: "button",
258
+ disabled: isLost.value,
259
+ onClick: onDoAI
260
+ }, " AI 帮走 ", 8, _hoisted_12)) : createCommentVNode("", true),
261
+ createElementVNode("button", {
262
+ class: "game-2048-button",
263
+ type: "button",
264
+ disabled: undoDisabled.value,
265
+ onClick: _cache[0] || (_cache[0] = ($event) => unref(undo)())
266
+ }, " 撤销 ", 8, _hoisted_13),
267
+ createElementVNode("button", {
268
+ class: "game-2048-button is-primary",
269
+ type: "button",
270
+ onClick: _cache[1] || (_cache[1] = ($event) => unref(newGame)())
271
+ }, " 新游戏 ")
272
+ ])]),
273
+ createElementVNode("div", {
274
+ ref_key: "boardEl",
275
+ ref: boardEl,
276
+ class: "game-2048-board",
277
+ style: normalizeStyle(boardVars.value),
278
+ tabindex: "0",
279
+ role: "application",
280
+ "aria-label": `2048 游戏板 ${unref(state).status}`,
281
+ onTouchstartPassive: onTouchStart,
282
+ onTouchend: withModifiers(onTouchEnd, ["prevent"])
283
+ }, [
284
+ createElementVNode("div", {
285
+ class: "game-2048-grid",
286
+ style: normalizeStyle(gridStyle.value)
287
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(state).size * unref(state).size, (i) => {
288
+ return openBlock(), createElementBlock("div", {
289
+ key: i,
290
+ class: "game-2048-cell"
291
+ });
292
+ }), 128))], 4),
293
+ createElementVNode("div", _hoisted_15, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(state).tiles, (t) => {
294
+ return openBlock(), createElementBlock("div", mergeProps({
295
+ key: t.id,
296
+ class: ["game-2048-tile", tileClass(t)],
297
+ style: tileVars(t.row, t.col),
298
+ "data-value": t.value
299
+ }, { ref_for: true }, tileAttrs(t)), toDisplayString(t.value), 17, _hoisted_16);
300
+ }), 128))]),
301
+ __props.enableAI && aiHint.value ? (openBlock(), createElementBlock("div", _hoisted_17, " 推荐:" + toDisplayString(aiHint.value), 1)) : createCommentVNode("", true),
302
+ createElementVNode("div", { class: normalizeClass(["game-2048-overlay", {
303
+ "is-visible": overlayVisible.value,
304
+ "is-won": isWon.value,
305
+ "is-lost": isLost.value
306
+ }]) }, [isWon.value ? (openBlock(), createElementBlock("h2", _hoisted_18, "你赢了!")) : isLost.value ? (openBlock(), createElementBlock("h2", _hoisted_19, "游戏结束")) : createCommentVNode("", true), createElementVNode("div", _hoisted_20, [
307
+ isWon.value ? (openBlock(), createElementBlock("button", {
308
+ key: 0,
309
+ class: "game-2048-button",
310
+ type: "button",
311
+ onClick: _cache[2] || (_cache[2] = ($event) => unref(continuePlaying)())
312
+ }, " 继续游戏 ")) : createCommentVNode("", true),
313
+ isLost.value && !undoDisabled.value ? (openBlock(), createElementBlock("button", {
314
+ key: 1,
315
+ class: "game-2048-button",
316
+ type: "button",
317
+ onClick: _cache[3] || (_cache[3] = ($event) => unref(undo)())
318
+ }, " 悔一步 ")) : createCommentVNode("", true),
319
+ overlayVisible.value ? (openBlock(), createElementBlock("button", {
320
+ key: 2,
321
+ class: "game-2048-button is-primary",
322
+ type: "button",
323
+ onClick: _cache[4] || (_cache[4] = ($event) => unref(newGame)())
324
+ }, " 再来一局 ")) : createCommentVNode("", true)
325
+ ])], 2)
326
+ ], 44, _hoisted_14)
327
+ ]);
328
+ };
329
+ }
330
+ });
331
+ export { Game2048_default as Game2048, useGame };
332
+
333
+ //# sourceMappingURL=index.js.map