1
- import LEVELS from './gameLayout' ;
1
+ import LEVELS from "./gameLayout" ;
2
+ import { translations , Language } from './translations' ;
2
3
3
4
interface Block {
4
5
type : string ;
5
6
x : number ;
6
7
y : number ;
8
+ char ?: string ; // Add this property
7
9
}
8
10
9
11
interface BlockType {
@@ -28,24 +30,57 @@ export class HuarongGame {
28
30
private blocks : Block [ ] ;
29
31
private userId : string | null = null ;
30
32
private currentLevel : number ;
33
+ private language : Language = navigator . language . toLowerCase ( ) . startsWith ( 'en' ) ? 'en' : 'zh' ;
31
34
32
- private readonly BLOCKS : { [ key : string ] : BlockType } = {
33
- CAO_CAO : { width : 2 , height : 2 , char : "曹操" , class : "cao" } ,
34
- VERTICAL : { width : 1 , height : 2 , char : "|" } ,
35
- HORIZONTAL : { width : 2 , height : 1 , char : "一" } ,
36
- SINGLE : { width : 1 , height : 1 , char : "口" } ,
37
- } ;
35
+ private generals = [ "张飞" , "马超" , "赵云" , "黄忠" ] ;
36
+ private generalIndex = 0 ;
37
+ private horizontalGenerals = [ "关羽" , "周仓" , "魏延" , "庞德" ] ;
38
+ private horizontalIndex = 0 ;
39
+
40
+ private BLOCKS : { [ key : string ] : BlockType } ;
41
+
42
+ private getNextGeneral ( ) : string {
43
+ const char = this . generals [ this . generalIndex ] ;
44
+ this . generalIndex = ( this . generalIndex + 1 ) % this . generals . length ;
45
+ return char ;
46
+ }
47
+
48
+ private getNextHorizontalGeneral ( ) : string {
49
+ const char = this . horizontalGenerals [ this . horizontalIndex ] ;
50
+ this . horizontalIndex = ( this . horizontalIndex + 1 ) % this . horizontalGenerals . length ;
51
+ return char ;
52
+ }
38
53
39
54
constructor ( level : number = 0 ) {
55
+ this . BLOCKS = {
56
+ CAO_CAO : { width : 2 , height : 2 , char : "曹操" , class : "cao" } ,
57
+ VERTICAL : { width : 1 , height : 2 , char : "将军" } ,
58
+ HORIZONTAL : { width : 2 , height : 1 , char : "将军" } ,
59
+ SINGLE : { width : 1 , height : 1 , char : "兵" } ,
60
+ } ;
61
+
40
62
this . currentLevel = level ;
41
63
this . bestScore = "-" ;
42
64
this . blocks = JSON . parse ( JSON . stringify ( LEVELS [ level ] . layout ) ) ;
65
+
66
+ // Assign character names to blocks
67
+ this . blocks . forEach ( block => {
68
+ if ( block . type === 'VERTICAL' ) {
69
+ block . char = this . getNextGeneral ( ) ;
70
+ } else if ( block . type === 'HORIZONTAL' ) {
71
+ block . char = this . getNextHorizontalGeneral ( ) ;
72
+ }
73
+ } ) ;
74
+
43
75
this . initializeGame ( ) ;
44
76
this . initializeLevelSelector ( ) ;
77
+ this . initializeLanguageSelector ( ) ;
45
78
}
46
79
47
80
async promptForUserId ( ) : Promise < string | null > {
48
- const id = prompt ( "Congratulations, you won! Enter your user ID to save your score:" ) ;
81
+ const id = prompt (
82
+ "Congratulations, you won! Enter your user ID to save your score:"
83
+ ) ;
49
84
if ( id ) {
50
85
this . userId = id ;
51
86
const existingBestScore = localStorage . getItem ( `bestScore_${ id } ` ) ;
@@ -64,6 +99,7 @@ export class HuarongGame {
64
99
this . createBoard ( ) ;
65
100
this . renderPieces ( ) ;
66
101
this . updateStats ( ) ;
102
+ this . updateUIText ( ) ;
67
103
68
104
const resetBtn = document . getElementById ( "resetBtn" ) ;
69
105
resetBtn ?. addEventListener ( "click" , ( ) => this . resetGame ( ) ) ;
@@ -73,26 +109,60 @@ export class HuarongGame {
73
109
}
74
110
75
111
private initializeLevelSelector ( ) {
76
- const levelSelector = document . getElementById ( 'levelSelector' ) as HTMLSelectElement ;
112
+ const levelSelector = document . getElementById (
113
+ "levelSelector"
114
+ ) as HTMLSelectElement ;
77
115
if ( levelSelector ) {
78
116
levelSelector . value = this . currentLevel . toString ( ) ;
79
- levelSelector . addEventListener ( ' change' , ( e ) => {
117
+ levelSelector . addEventListener ( " change" , ( e ) => {
80
118
const newLevel = parseInt ( ( e . target as HTMLSelectElement ) . value ) ;
81
119
this . changeLevel ( newLevel ) ;
82
120
} ) ;
83
121
}
84
122
}
85
123
124
+ private initializeLanguageSelector ( ) {
125
+ const languageSelector = document . getElementById ( 'languageSelector' ) as HTMLSelectElement ;
126
+ languageSelector . value = this . language ;
127
+ languageSelector . addEventListener ( 'change' , ( e ) => {
128
+ this . language = ( e . target as HTMLSelectElement ) . value as Language ;
129
+ this . updateUIText ( ) ;
130
+ } ) ;
131
+ }
132
+
133
+ private updateUIText ( ) {
134
+ const t = translations [ this . language ] ;
135
+ document . querySelector ( 'h1' ) ! . textContent = t . title ;
136
+ document . getElementById ( 'resetBtn' ) ! . textContent = t . reset ;
137
+ document . getElementById ( 'undoBtn' ) ! . textContent = t . undo ;
138
+ document . querySelector ( '.stats' ) ! . innerHTML =
139
+ `${ t . moves } : <span id="moveCount">${ this . moves } </span> | ${ t . best } : <span id="bestScore">${ this . bestScore } </span>` ;
140
+ }
141
+
86
142
private changeLevel ( level : number ) {
87
143
this . currentLevel = level ;
88
144
this . blocks = JSON . parse ( JSON . stringify ( LEVELS [ level ] . layout ) ) ;
145
+
146
+ // Reset indices and assign new characters for new level
147
+ this . generalIndex = 0 ;
148
+ this . horizontalIndex = 0 ;
149
+ this . blocks . forEach ( block => {
150
+ if ( block . type === 'VERTICAL' ) {
151
+ block . char = this . getNextGeneral ( ) ;
152
+ } else if ( block . type === 'HORIZONTAL' ) {
153
+ block . char = this . getNextHorizontalGeneral ( ) ;
154
+ }
155
+ } ) ;
156
+
89
157
this . moves = 0 ;
90
158
this . moveHistory = [ ] ;
91
159
this . selectedPiece = null ;
92
160
if ( ! this . userId ) {
93
161
this . bestScore = "-" ;
94
162
} else {
95
- const existingBestScore = localStorage . getItem ( `bestScore_${ this . userId } _level${ level } ` ) ;
163
+ const existingBestScore = localStorage . getItem (
164
+ `bestScore_${ this . userId } _level${ level } `
165
+ ) ;
96
166
this . bestScore = existingBestScore ? parseInt ( existingBestScore ) : "-" ;
97
167
}
98
168
this . updateStats ( ) ;
@@ -112,10 +182,10 @@ export class HuarongGame {
112
182
board . innerHTML = "" ;
113
183
114
184
this . blocks . forEach ( ( block , index ) => {
115
- const blockType = this . BLOCKS [ block . type ] ;
185
+ const blockType = { ... this . BLOCKS [ block . type ] } ;
116
186
const piece = document . createElement ( "div" ) ;
117
187
piece . className = `piece ${ blockType . class || "" } ` ;
118
- piece . textContent = blockType . char ;
188
+ piece . textContent = block . char || blockType . char ; // Use stored character
119
189
piece . style . gridColumn = `${ block . x + 1 } / span ${ blockType . width } ` ;
120
190
piece . style . gridRow = `${ block . y + 1 } / span ${ blockType . height } ` ;
121
191
piece . dataset . index = index . toString ( ) ;
@@ -167,24 +237,25 @@ export class HuarongGame {
167
237
// Position the arrow based on direction
168
238
const pieceWidth = rect . width ;
169
239
const pieceHeight = rect . height ;
240
+ const arrowSize = 34 ;
170
241
let left , top ;
171
242
172
243
switch ( direction ) {
173
244
case "Left" :
174
- left = rect . left - boardRect . left - 35 ;
175
- top = rect . top - boardRect . top + pieceHeight / 2 - 15 ;
245
+ left = rect . left - boardRect . left - arrowSize ;
246
+ top = rect . top - boardRect . top + pieceHeight / 2 - arrowSize / 2 - 3 ;
176
247
break ;
177
248
case "Right" :
178
- left = rect . right - boardRect . left + 5 ;
179
- top = rect . top - boardRect . top + pieceHeight / 2 - 15 ;
249
+ left = rect . right - boardRect . left - 7 ;
250
+ top = rect . top - boardRect . top + pieceHeight / 2 - arrowSize / 2 - 3 ;
180
251
break ;
181
252
case "Up" :
182
- left = rect . left - boardRect . left + pieceWidth / 2 - 15 ;
183
- top = rect . top - boardRect . top - 35 ;
253
+ left = rect . left - boardRect . left + pieceWidth / 2 - arrowSize / 2 - 3 ;
254
+ top = rect . top - boardRect . top - arrowSize ;
184
255
break ;
185
256
case "Down" :
186
- left = rect . left - boardRect . left + pieceWidth / 2 - 15 ;
187
- top = rect . bottom - boardRect . top + 5 ;
257
+ left = rect . left - boardRect . left + pieceWidth / 2 - 20 ;
258
+ top = rect . bottom - boardRect . top - 7 ;
188
259
break ;
189
260
}
190
261
@@ -279,15 +350,12 @@ export class HuarongGame {
279
350
const b1Type = this . BLOCKS [ block1 . type ] ;
280
351
const b2Type = this . BLOCKS [ block2 . type ] ;
281
352
return ! (
282
- block1 . x >= block2 . x + b2Type . width ||
283
- block2 . x >= block1 . x + b1Type . width
353
+ block1 . x >= block2 . x + b2Type . width || block2 . x >= block1 . x + b1Type . width
284
354
) ;
285
355
}
286
356
287
357
getPossibleMoves ( block : Block ) {
288
358
const moves : Position [ ] = [ ] ;
289
- const blockType = this . BLOCKS [ block . type ] ;
290
-
291
359
[
292
360
[ - 1 , 0 ] ,
293
361
[ 1 , 0 ] ,
@@ -333,7 +401,10 @@ export class HuarongGame {
333
401
} ) ;
334
402
}
335
403
336
- rectsIntersect ( r1 : { x : number ; y : number ; w : number ; h : number } , r2 : { x : number ; y : number ; w : number ; h : number } ) {
404
+ rectsIntersect (
405
+ r1 : { x : number ; y : number ; w : number ; h : number } ,
406
+ r2 : { x : number ; y : number ; w : number ; h : number }
407
+ ) {
337
408
return ! (
338
409
r2 . x >= r1 . x + r1 . w ||
339
410
r2 . x + r2 . w <= r1 . x ||
@@ -348,12 +419,14 @@ export class HuarongGame {
348
419
if ( ! this . userId ) {
349
420
const id = await this . promptForUserId ( ) ;
350
421
if ( ! id ) {
351
- alert ( `Congratulations! You won in ${ this . moves } moves! (Score not saved)` ) ;
422
+ alert (
423
+ `Congratulations! You won in ${ this . moves } moves! (Score not saved)`
424
+ ) ;
352
425
this . resetGame ( ) ;
353
426
return ;
354
427
}
355
428
}
356
-
429
+
357
430
if ( this . userId ) {
358
431
const scoreKey = `bestScore_${ this . userId } _level${ this . currentLevel } ` ;
359
432
const currentBest = localStorage . getItem ( scoreKey ) ;
@@ -362,7 +435,7 @@ export class HuarongGame {
362
435
localStorage . setItem ( scoreKey , this . moves . toString ( ) ) ;
363
436
}
364
437
}
365
-
438
+
366
439
alert ( `Congratulations! You won in ${ this . moves } moves!` ) ;
367
440
this . resetGame ( ) ;
368
441
} ;
@@ -387,7 +460,16 @@ export class HuarongGame {
387
460
document
388
461
. querySelectorAll ( ".direction-arrow" )
389
462
. forEach ( ( arrow ) => arrow . remove ( ) ) ;
463
+ this . generalIndex = 0 ;
464
+ this . horizontalIndex = 0 ;
390
465
this . blocks = JSON . parse ( JSON . stringify ( LEVELS [ this . currentLevel ] . layout ) ) ;
466
+ this . blocks . forEach ( block => {
467
+ if ( block . type === 'VERTICAL' ) {
468
+ block . char = this . getNextGeneral ( ) ;
469
+ } else if ( block . type === 'HORIZONTAL' ) {
470
+ block . char = this . getNextHorizontalGeneral ( ) ;
471
+ }
472
+ } ) ;
391
473
this . moves = 0 ;
392
474
this . moveHistory = [ ] ;
393
475
this . selectedPiece = null ;
@@ -396,6 +478,7 @@ export class HuarongGame {
396
478
}
397
479
this . updateStats ( ) ;
398
480
this . renderPieces ( ) ;
481
+ this . updateUIText ( ) ;
399
482
}
400
483
401
484
updateStats ( ) {
@@ -408,4 +491,4 @@ export class HuarongGame {
408
491
bestScore . textContent = this . bestScore . toString ( ) ;
409
492
}
410
493
}
411
- }
494
+ }
0 commit comments