²Ä 26 ³¹¡@³B²z¹ï¸Ü²°¤¤ªº«öÁä


­ì²z

¦b²Ä¤Q³¹»Pªþ¿ý¤T¡A´¿¤¶²Ð¤F¦p¦ó¥H¼Ò¦¡¹ï¸Ü²°¨Ó¼¶¼gµ{¦¡¡C¥Î³oºØ¤èªk¡A¥i¥H´î¤Ö³\¦hµ{¦¡½X¡A«D±`ªº¤è«K¡C¤@¥¹¼Ò¦¡¹ï¸Ü²°«Ø¥ß«á¡A§@·~¨t²Î·|«Ø¥ß¹ï¸Ü²°ºÞ²z¾¹¡A¹ï¸Ü²°ºÞ²z¾¹·|³B²z³\¦h¨Æ±¡¡A¨Ò¦p«Ø¥ß¹ï¸Ü²°ªº¦U­Ó±±¨î¶µ¡B³B²z°T®§¨Ã©I¥s¹ï¸Ü²°¨ç¦¡ ( dialog box procedure )¡C³o¨Ç³£·|¦Û°Ê§¹¦¨¡A¤£¥²µ{¦¡³]­pªº¤H¶O¤ß¡C¤@­Ó¹ï¸Ü²°ùسq±`§t¦³¼Æ­Ó±±¨î¶µ¡A¦b³o¨Ç±±¨î¶µ¤¤¡A¥u¦³¤@­Ó±±¨î¶µ¨ã¦³¿é¤JµJÂI¡A¨Ï¥ÎªÌ¹ïÁä½Lªº¿é¤J°T®§¡A¨Ò¦p WM_KEYDOWN¡BWM_KEYUP µ¥µ¥¡A§¡·|¶Ç¨ì³o­Ó±±¨î¶µùØ¡C¦ý¬O¡A«Ü¤£©¯ªº¡A³B²zÁä½L°T®§ªºµ{¦¡½X³£¥Ñ¹ï¸Ü²°ºÞ²z¾¹­t³d¡A¨Ã¤£·|¶Ç°eµ¹¹ï¸Ü²°¨ç¦¡³B²z¡C¦]¦¹¦b¹ï¸Ü²°¤¤¡A§Y¨Ï±z¼W¥[¤F³B²z WM_KEYDOWN ¤§Ãþªºµ{¦¡½X¡A¤]¤@¼ËµLªk¹F¨ì¹w´Áªº¥Ø¼Ð¡C

¤p¤ì°¸¥´ºâ¼¶¼g³Ìªñ«Ü¬y¦æªº¤p¹CÀ¸¡A2048¡A¦p¤U¹Ï©Ò¥Ü¡C§Ú·Q¥H 16 ­ÓÀRºA±±¥ó ( ÀRºA±±¨î¶µ ) ¼ÒÀÀ©³¤U 4¡Ñ4 ªº¯x°}¡A¦A¥H 4 ­ÓÀRºA±±¥óÅã¥Ü¥k¤W¤èªº¤À¼ÆÀRºA±±¥ó¡G¡uSCORE¡v¡B¡uBEST¡v¡B¡u65924¡v¡B¡u0¡v( ¥H¶À¦â®Ø½u³ò¦í )¡C¦b´¼¼z«¬¤â¾÷¥i¥Î¤â«ü·Æ°Ê¨Ó²¾°Ê¼Æ¦r¡F¦Ó¦b¹q¸£¤W¡A¤p¤ì°¸·Q¥ÎÁä½L¤Wªº¤W¡B¤U¡B¥ª¡B¥kÁä¡A¤À§O¨Ï¼Æ¦r©¹³o¥|­Ó¤è¦V²¾°Ê¡A¨Ã¨Ï±o¬Û¾F¥B¬Û¦Pªº¨â¼Æ¦r¬Û¥[¡C°£¦¹¤§¥~¡A¤p¤ì°¸¤]·Q¦A²K¥[¤@­Ó·s¥\¯à¡A´N¬Oª±®a¯à°÷¤Ï®¬¤@¨B¡A·íª±®a«ö¤U Ctrl¡ÐZ ®É¡A¯à°÷¦^¨ì¤W¤@¨Bªºª¬ºA¡C

¤£¹L°ÝÃD¨Ó¤F¡A¦p¤@¶}©l©Ò»¡ªº¡AWindows §@·~¨t²Î®Ú¥»¤£·|§âÁä½L°T®§¶Çµ¹¹ï¸Ü²°ªº¹ï¸Ü²°¨ç¦¡¡A¨º»ò¤S¦p¦ó³B²z©O¡H¤p¤ì°¸¬d¹Mºô¸ô¤Wªº¤åÄm¡Aµo²{¦³¨âºØ¤èªk¡A²Ä¤@ºØ¥i¯à¬O¸û¬°¥¿²Îªº¤èªk¡A§Q¥ÎÄdºI°T®§ ( hook )¡F²Ä¤GºØ¸û¬°¡u¤g¡v¡A¦b¥»³¹ùØ¡A¤p¤ì°¸·Q¤¶²Ð³oºØ¤èªk¡C¦¹ºØ¤èªk¬O¥ý¡u¤lÃþ¤Æ¡v¬Y­Ó±±¨î¶µ¡A©Ò¿×¡u¤lÃþ¤Æ¡vªº·N«ä¡A´N¬O¥ý¨ú±o¬Y­Ó±±¨î¶µªºµøµ¡¨ç¦¡¦ì§}¡A¦s°_¨Ó¡A¦A¦Û¦æ¼¶¼g³B²z§Ú­Ì·P¿³½ìªº°T®§°µ¬°·sªºµøµ¡¨ç¦¡¡A³Ì«á¦A©I¥s­ì¥ýªºµøµ¡¨ç¦¡¡C¦Ó¤p¤ì°¸ªº¤èªk«h¬O¦b¦Û¦æ¼¶¼gªºµøµ¡¨ç¦¡ùØ¡A¹J¨ì¹³ WM_KEYDOWN¡BWM_KEYUP ³o¨ÇÁä½L°T®§®É¡A§Q¥Î SendMessage §â³o¨Ç°T®§¶Ç°eµ¹¹ï¸Ü²°µøµ¡¨ç¦¡¡C³¡¥÷­ì©l½X¦p¤U¡G

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
;---------------------------------------------------------------------------------------------------
;·sªº½s¿è®Øµøµ¡¨ç¦¡
new_button_proc PROC    hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
.IF uMsg==WM_KEYDOWN
        .IF (wParam>=VK_LEFT)&&(wParam<=VK_DOWN)
                INVOKE  SendMessage,hDialog,WM_KEYDOWN,wParam,lParam
        .ELSEIF wParam==VK_CONTROL
                mov     bCtrlDown,TRUE
        .ELSEIF wParam==VK_Z
                INVOKE  SendMessage,hDialog,WM_CHAR,wParam,lParam
        .ELSE
                INVOKE  CallWindowProc,lpOldButtonProc,hWnd,uMsg,wParam,lParam
                ret
        .ENDIF
.ELSEIF uMsg==WM_GETDLGCODE
                mov     eax,DLGC_WANTALLKEYS
                ret
.ELSE
                INVOKE  CallWindowProc,lpOldButtonProc,hWnd,uMsg,wParam,lParam
                ret
.ENDIF
                xor     eax,eax
                ret
new_button_proc ENDP
;---------------------------------------------------------------------------------------------------
;¹ï¸Ü²°¨ç¦¡
DlgProc         PROC    hDlg:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
.IF uMsg==WM_INITDIALOG
                mov     bCtrlDown,FALSE
            ;¤lÃþ§O¤Æ«ö¶s
                INVOKE  GetDlgItem,hDlg,IDB_NEW
                INVOKE  SetWindowLong,eax,GWL_WNDPROC,OFFSET new_button_proc
                mov     lpOldButtonProc,eax
 
.ELSEIF uMsg==WM_CHAR
   .IF bCtrlDown==TRUE
                mov     bCtrlDown,FALSE
      .IF (wParam=="Z")||(wParam=="z")
        ;¦¹³B¬°³B²z«ö¤U Ctrl-Z Á䪺µ{¦¡
      .ENDIF
   .ELSE
   .ENDIF

.ELSEIF uMsg==WM_KEYDOWN
   .IF wParam==VK_DOWN
        ;¦¹³B¬°³B²z«ö¤U¡u¡õ¡vÁ䪺µ{¦¡
   .ELSEIF wParam==VK_UP
        ;¦¹³B¬°³B²z«ö¤U¡u¡ô¡vÁ䪺µ{¦¡
   .ELSEIF wParam==VK_RIGHT
        ;¦¹³B¬°³B²z«ö¤U¡u¡÷¡vÁ䪺µ{¦¡
   .ELSEIF wParam==VK_LEFT
        ;¦¹³B¬°³B²z«ö¤U¡u¡ö¡vÁ䪺µ{¦¡
   .ENDIF

.ELSEIF uMsg==WM_CLOSE
                INVOKE  EndDialog,hDlg,NULL

.ELSE           ;¨ä¥L¥¼³B²zªº°T®§ªð¦^ FALSE
                mov     eax,FALSE
                ret

.ENDIF          ;¤w³B²zªº°T®§¡Aªð¦^ TRUE
                mov     eax,TRUE   
                ret
DlgProc         ENDP
;---------------------------------------------------------------------------------------------------

¤W­±ªºµ{¦¡¤ù¬qªº²Ä 32 ¦æ¡A¤p¤ì°¸¥H GWL_WNDPROC ¬°°Ñ¼Æ©I¥s SetWindowLong¡A§â¡u·s¹CÀ¸¡v«ö¶sªºµøµ¡¨ç¦¡­«·s³]¬° new_button_proc °Æµ{¦¡¡CSetWindowLong ¦b¦¨¥\³]©w·sªºµøµ¡¨ç¦¡¦ì§}®É¡A·|¶Ç¦^¡u·s¹CÀ¸¡v«ö¶s­ì¥ýªºµøµ¡¨ç¦¡¦ì§}¡A±µµÛ§â¥¦¦s©ó lpOldButtonProc ÅܼÆùØ ( ¨£²Ä 33 ¦æ )¡C¦b¡u·s¹CÀ¸¡v«ö¶s¤¤¡A·sªºµøµ¡¨ç¦¡·|³B²z WM_KEYDOWN °T®§¡C¥¦¹J¨ì WM_KEYDOWN °T®§®É¡AÀˬd¨Ï¥ÎªÌ¬O§_«ö¤U©³¤Uªº¤TºØ«öÁä¡G

  1. ¦pªG«ö¤U¤è¦VÁä¡G§Y¤W¡B¤U¡B¥ª¡B¥kÁä ( ¤À§O¬O 26h¡B28h¡B25h¡B27h )¡A¦pªG¬O«h§â WM_KEYDOWN °T®§­ì«Ê¤£°Ê¶Çµ¹¹ï¸Ü²°¨ç¦¡ ( ²Ä 6 ¦æ )¡C
  2. ¦pªG«ö¤U Ctrl Áä¡A«h³]©w bCtrlDown ÅܼƬ° TRUE ( ²Ä 8 ¦æ )¡C
  3. ¦pªG«ö¤U­^¤å¦r¥Àªº¡uZ¡vÁä¡A«h§â WM_CHAR °T®§¶Çµ¹¹ï¸Ü²°ªºµøµ¡¨ç¦¡ ( ²Ä 10 ¦æ )¡C

¥Ñ¤W­±¬yµ{¨Ó¬Ý¡A­n³B²z²Õ¦X«öÁä¡A¨Ò¦p Ctrl¡ÐZ¡K¡Aªº¤èªk¬O¥ý³]¤@­ÓÅܼƷí§@ºX¼Ð¡A·í Ctrl ³QÀ£¤U®É¡A§â¦¹ÅܼƳ]¬° TRUE¡AµM«á¦bµøµ¡¨ç¦¡³B²z WM_CHAR ®É¡A¦b¦¹ÅܼƬ° TRUE ®É¡AÀˬd¡uZ¡vÁä¬O§_³Q«ö¤U§Y¥i ( ¨£µ{¦¡²Ä 36¡ã41 ¦æ )¡C

·íµM¡A³oºØ¥H¤lÃþ¤Æ«ö¶s´ÛÄF§@·~¨t²Î¡A¦Ó§âÁä½L°T®§¶Çµ¹¹ï¸Ü²°¨ç¦¡ªº°µªk¡A¬O¦³¯ÊÂIªº¡C·í¡u·s¹CÀ¸¡v«ö¶s¥¢¥h¿é¤JµJÂI®É¡Aª±®a«ö¤U¤è¦VÁä´NµL§@¥Î¤F¡A©¯¦n¦b³o­Ó¹CÀ¸¤¤¡A¦¹¯ÊÂI¨Ã¤£¤Ó¤j¡A¬Æ¦Üª±®a¥i¯à³£«ÜÃø¨Ï¡u·s¹CÀ¸¡v«ö¶s¥¢¥h¿é¤JµJÂI¦Ó¤£°h¥X¹CÀ¸¡C¤£¹L¦pªG¹ï¸Ü²°§t¦³³\¦h«ö¶s¡B½s¿è®Øªº¸Ü¡A¦¹¤èªk´NÃø¥H¨Ï¥Î¤F¡C


­ì©l½X

©³¤U¬O 2048.RC ªº­ì©l½X¡G

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "c:\masm32\include\resource.h"
 
#define IDS_00          0x08000
#define IDS_MARK        0x08100
#define IDS_BEST        0x08101
#define IDS_MARKTEXT    0x08102
#define IDS_BESTTEXT    0x08103
#define IDB_NEW         0x08104
#define IDB_EXIT        0x08105
#define x               4
#define y               22
#define RT_MANIFEST     24
 
Game2048        DIALOG  200, 100, 180, 200
STYLE   DS_SETFONT|WS_POPUP|WS_CAPTION|WS_VISIBLE|WS_SYSMENU
CAPTION "2048"
FONT    16,"Times New Roman"
BEGIN
 CTEXT  "SCORE",IDS_MARKTEXT,  78,    4, 45,  7
 CTEXT  "",         IDS_MARK,  78,   11, 45,  7
 CTEXT  "BEST", IDS_BESTTEXT, 129,    4, 45,  7
 CTEXT  "",         IDS_BEST, 129,   11, 45,  7
 CTEXT  "",IDS_00,         x,    y, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0x1,  x+44,    y, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0x2,  x+88,    y, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0x3, x+132,    y, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0x4,     x, y+40, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0x5,  x+44, y+40, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0x6,  x+88, y+40, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0x7, x+132, y+40, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0x8,     x, y+80, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0x9,  x+44, y+80, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0xA,  x+88, y+80, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0xB, x+132, y+80, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0xC,     x,y+120, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0xD,  x+44,y+120, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0xE,  x+88,y+120, 38, 35,SS_OWNERDRAW
 CTEXT  "",IDS_00+0xF, x+132,y+120, 38, 35,SS_OWNERDRAW
 PUSHBUTTON  "·s¹CÀ¸",IDB_NEW , 26,180, 50, 14
 PUSHBUTTON  "Â÷¶}"  ,IDB_EXIT,104,180, 50, 14
END
 
1   RT_MANIFEST MOVEABLE PURE "2048.EXE.MANIFEST"
 
Game2048        ICON    2048.ico

³o­Ó¸ê·½´y­zÀÉùئ³ 16 ­ÓÀRºA±±¥ó¥Î¨ÓÅã¥Ü¼Æ­È¡A¨äÃѧO½X½d³ò¬O 8000h¡ã800Fh¡A¦ý¬O¦b¸ê·½´y­zÀɤ¤¡A¦b¼Æ­È«e¥[¤W¡u0x¡v¬°¦r­ºªí¥Ü¦¹¼Æ¬°¤Q¤»¶i¦ìªí¥Üªk¡C¥t¥~¤]¥i¥H¥Î¹³²Ä 23¡ã38 ¦æªº¤è¦¡ªí¥ÜÃѧO½X¡A³s±±¨î¤¸¥óªº¦ì¸m¤]¥i¥H¥Î±`¼Æ§@¹Bºâ¨Ó´y­z¡C¤p¤ì°¸§â±±¨î¤¸¥óªº¦ì¸m¥H x¡By ±`¼Æªí¥Ü¡A¨ä­ì¦]¬O¥i¥H«Ü®e©ö­×§ï¨ä¦ì¸m¡A¦ý¬O¨C­Ó±±¨î¤¸¥ó¤W¤U¥ª¥kªº¶ZÂ÷«o¤£ÅÜ¡C

©³¤U¬O 2048.EXE.MANIFEST ªº­ì©l½X¡G

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<dependency>
   <dependentAssembly>
      <assemblyIdentity type='win32'
                        name='Microsoft.Windows.Common-Controls'
                        version='6.0.0.0'
                        processorArchitecture='*'
                        publicKeyToken='6595b64144ccf1df'
                        language='*'
      />
   </dependentAssembly>
</dependency>
</assembly>

©³¤U¬O 2048.ASM ªº­ì©l½X¡G

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
                OPTION  CASEMAP:NONE
                .586
                .MODEL  FLAT,STDCALL
 
INCLUDE         WINDOWS.INC
INCLUDE         COMCTL32.INC
INCLUDE         GDI32.INC
INCLUDE         KERNEL32.INC
INCLUDE         USER32.INC
INCLUDELIB      COMCTL32.LIB
INCLUDELIB      GDI32.LIB
INCLUDELIB      KERNEL32.LIB
INCLUDELIB      USER32.LIB
 
IDS_00          EQU     8000h
IDS_03          EQU     8003h
IDS_07          EQU     8007h
IDS_0B          EQU     800Bh
IDS_0C          EQU     800Ch
IDS_0F          EQU     800Fh
IDS_MARK        EQU     8100h
IDS_BEST        EQU     8101h
IDS_MARKTEXT    EQU     8102h
IDS_BESTTEXT    EQU     8103h
IDB_NEW         EQU     8104h
IDB_EXIT        EQU     8105h
 
cr0Text         EQU     0b4c0cdh
cr2Text         EQU     0656e77h
cr8Text         EQU     0f2f6f9h
crScoreText     EQU     0dae4eeh
 
DIMENSION       EQU     4       ;4¡Ñ4ÀRºA±±¥ó¯x°}
TOPTODOWN       EQU     0       ;·í¨Ï¥ÎªÌ«ö¤UVK_DOWNÁä¡A¥Ñ¤W¦Ó¤U
DOWNTOTOP       EQU     1       ;·í¨Ï¥ÎªÌ«ö¤UVK_UPÁä¡A¥Ñ¤U¦Ó¤W
RIGHTTOLEFT     EQU     2       ;·í¨Ï¥ÎªÌ«ö¤UVK_LEFTÁä¡A¥Ñ¥k¦Ó¥ª
LEFTTORIGHT     EQU     3       ;·í¨Ï¥ÎªÌ«ö¤UVK_RIGHTÁä¡A¥Ñ¥ª¦Ó¥k
;***************************************************************************************************
.CONST
;crBk¬OÀRºA±±¥óªº­I´ºÃC¦â¡A­I´ºÃC¦âÀHÀRºA±±¥óªº¼ÐÃD¼Æ­È¤£¦P¦Ó¤£¦P¡A¨Ò¦p¼Æ­È0®É¡AÃC¦â¬°0b4c0cdh
                        ;  0        2        4        8       16       32       64      128
crBk            DWORD   0b4c0cdh,0dae4eeh,0c8e0edh,079b1f2h,06395f5h,05f7cf6h,03b5ef6h,072cfedh
                        ;256      512      1024     2048     4096     8192     16384    32768    65536
                DWORD   061ccedh,050c8edh,03fc5edh,02ec2edh,0323a3ch,0323a3ch,0323a3ch,0323a3ch,0323a3ch
szDlgName       DB      "Game2048",0    ;¹ï¸Ü²°­±ªO¦WºÙ
szZero          DB      "0",0
szTwo           DB      "2",0
szFour          DB      "4",0
szFontFace      DB      "Verdana",0     ;Åã¥Ü¦b4¡Ñ4ÀRºA±±¥ó¯x°}¤Wªº¦r§Î
szFilename      DB      "BEST2048.TXT",0;³Ì¨Î¤À¼ÆÀÉ®×
szNumFmt        DB      "%d",0
szFailure       DB      "¹CÀ¸µ²§ô¡I",0
szFailureTitle  DB      "³qª¾",0
;***************************************************************************************************
.DATA
hInstance       HANDLE  ?               ;°õ¦æ¹ê¨Ò¥N½X
hDialog         HANDLE  ?               ;¹ï¸Ü²°¥N½X
lpOldButtonProc DWORD   ?               ;¡u·s¹CÀ¸¡v­ì¦³ªºµøµ¡¨ç¦¡¦ì§}
;ÀRºA±±¥óªºÅÞ¿è¦r§Î¡A¼ÐÃD¤p©óµ¥©ó64ªÌ¥ÎhFont[0]¡A¤j©ó64¥B¤p©óµ¥©ó8192ªÌ¥ÎhFont[4]¡A¨ä¥L¥ÎhFont[8]
hFont           HFONT   3 DUP (?)
hbrBkStatic     HBRUSH  17 DUP (?)      ;ÀRºA±±¥óªº­I´ºµe¨ê
hbrBkDlg        HBRUSH  ?               ;¹ï¸Ü²°ªº­I´ºµe¨ê
hbrBkScore      HBRUSH  ?               ;ªí¥Ü¤À¼Æ(IDS_MARK¡BIDS_BEST¡BIDS_MARKTEXT¡BIDS_BESTTEXT)ªº­I´ºµe¨ê
dwScore         DWORD   0               ;·í¤Uªº¤À¼Æ
dwOldScore      DWORD   ?               ;¤W¦¸«ö¤U¤è¦VÁä«áªº¤À¼Æ¡A¥Î©óª±®a«ö¤UCtrl¡ÐZ®É
dwBest          DWORD   ?               ;³Ì°ª¤À°O¿ý
number          DWORD   16 DUP (?)
bCtrlDown       DWORD   ?               ;CtrlÁä¬O§_«ö¤UªººX¼Ð¡ATRUEªí¥Ü¥¿³Q«ö¤U¡FFALSEªí¥Ü¨S³Q«ö¤U
hFile           HFILE   ?               ;BEST2048.TXTªºÀÉ®×¥N½X
BytesRead       DWORD   ?
BytesWritten    DWORD   ?
dwN             DWORD   DIMENSION DUP (?)
szBuffer        DB      10h DUP (?)
;***************************************************************************************************
.CODE
;---------------------------------------------------------------------------------------------------
;¨ú±oÃѧO½X¬°ECXÀRºA±±¥óªº¼Æ­È»P°Ñ¼Æx¤ñ¸û¡A¦pªG¬Ûµ¥¡AEAX³]¬°1¡F¦pªG¤£µ¥¡AEAX³]¬°0
chk_reduce      PROC    x:DWORD
                INVOKE  GetDlgItemInt,hDialog,ecx,0,0
            .IF eax==x
                mov     eax,1
            .ELSE
                sub     eax,eax
            .ENDIF
                ret
chk_reduce      ENDP
;---------------------------------------------------------------------------------------------------
;Àˬd©Ò¦³¬Û¾FªºÀRºA±±¥ó¬O§_¬Ûµ¥¡A­Y¦³¬Ûµ¥«hªð¦^TRUE¡A§_«hªð¦^FALSE
check_gameover  PROC
                LOCAL   IdNum,value,nReduce:DWORD
                mov     nReduce,0       ;nReduce¬ö¿ý¦³¬Ûµ¥ªºÀR±±±±¥ó­Ó¼Æ¡A¥i¨ÑÁY´î
                mov     IdNum,IDS_00
    .WHILE IdNum<IDS_0F
                INVOKE  GetDlgItemInt,hDialog,IdNum,0,0
                mov     value,eax
        .IF IdNum<=IDS_0B
                mov     ecx,IdNum
                add     ecx,4
                INVOKE  chk_reduce,value
                add     nReduce,eax
            .IF (IdNum==IDS_03)||(IdNum==IDS_07)||(IdNum==IDS_0B)
            .ELSE
                mov     ecx,IdNum
                inc     ecx
                INVOKE  chk_reduce,value
                add     nReduce,eax
            .ENDIF
        .ELSE
                mov     ecx,IdNum
                inc     ecx
                INVOKE  chk_reduce,value
                add     nReduce,eax
        .ENDIF
                inc     IdNum
    .ENDW
                xor     eax,eax
                cmp     nReduce,eax
                jz      exit
                inc     eax
exit:           ret
check_gameover  ENDP
;---------------------------------------------------------------------------------------------------
;arrange_a_row¥u³B²z¤@¦æ©Î¤@¦C¡A¥¦§âdwN°}¦C©¹§C¦ì§}¤è¦VÁY´î¡AÁY´î¤è¦¡¬O¦p¦³§C¦ì§}¦³ªÅ®æ(¸Ó¼Æ­È¬°0)¡A
;«h¦b¸û°ª¦ì§}ªºÂù¦r²Õ¼Æ­È²¾¨ì§C¦ì§}¦³ªÅ®æ³B¡A±µ¤U¨ÓÀˬd¬Û¾Fªº¼Æ­È¡A¦pªG¬Û¦P«h¬Û¥[¡C
;ªð¦^®É¡A¦p¦³ÁY´î©Î¬Û¥[¡Aªð¦^NC¡F¦p¨S¦³ÁY´î¤]¨S¬Û¥[¡Aªð¦^CY
arrange_a_row   PROC    USES esi edi
                LOCAL   n,m,TimesOfReduce:DWORD
                xor     eax,eax
                mov     TimesOfReduce,eax
 ;°²¦p¦³ªÅ®æªº¸Ü¡A§â°ª¦ì§}ªº¼Æ­È¶ñ¨ì§C¦ì§}ªºªÅ®æ¤¤
                mov     m,eax
                mov     edx,DIMENSION-1
 .WHILE m<DIMENSION-2
                mov     n,eax
    .WHILE n<edx
                mov     esi,n
                shl     esi,2
                add     esi,OFFSET dwN
        .IF DWORD PTR [esi]==eax
             ;­Y§C¦ì§}ªº¼Æ­È¬°0¡AÀˬd¨ä¥L°ª¦ì§}¬O§_¤]¬°0
                mov     ecx,3
                mov     edi,esi
                sub     ecx,n
                add     edi,4
                push    ecx
                repe    scasd
                pop     ecx
               ;­Y¥þ¬°0¡A¸õ¦Ünext_turn¡F­Y¦³¥ô¦ó¤@­Ó¤£¬°0¡A«h§â¨ä¥L°ª¦ì§}ªº¼Æ­È©¹§C¦ì§}²¾4­Ó¦ì¤¸²Õ
                jz      next_turn
                mov     edi,esi
                add     esi,4
                rep     movsd
                inc     TimesOfReduce
                mov     [edi],eax
        .ENDIF
next_turn:      inc     n
    .ENDW
                inc     m
                sub     edx,m
 .ENDW
 ;§â¬Û¾F¦ì§}¥B¼Æ­È¬Û¦Pªº¬Û¥[¡A¨Ã¦V§C¦ì§}³B²¾°Ê
                mov     m,eax
 .WHILE m<DIMENSION-1
                mov     esi,m
                shl     esi,2
                add     esi,OFFSET dwN
                mov     edx,[esi]
                cmp     edx,eax
                jz      finish
        .IF edx==DWORD PTR [esi+4]
                add     edx,[esi+4]
                inc     TimesOfReduce
                mov     [esi],edx
                add     dwScore,edx
                mov     ecx,DIMENSION-2
                sub     ecx,m
                add     esi,4
                mov     edi,esi
                add     esi,4
                rep     movsd
                mov     [edi],eax
        .ENDIF
                inc     m
 .ENDW
finish: .IF eax==TimesOfReduce
                stc
        .ELSE
                clc
        .ENDIF
                ret
arrange_a_row   ENDP
;---------------------------------------------------------------------------------------------------
;¾ã²z¾ã­Ó4¡Ñ4¯x°}¡A¾ã²z¤èªk¬O©I¥sarrange_a_row°Æµ{¦¡¥|¦¸¡A°Ñ¼Ædirect¬Oªí¥Üª±®a©Ò«öªº¤è¦V«öÁä
;ªð¦^®É¡A¦pªG¦³¥ô¦ó¤@¦æ´¿ÁY´î©Î¬Û¥[¡Aªð¦^NC¡F§_«hªð¦^CY
arrange_matrix  PROC    USES edi direct:DWORD
                LOCAL   n,row,bArrange:DWORD
                LOCAL   ID:DWORD
                ;difference¡×¨C¤@¦æ¤ºÀRºA±±¥óÃѧO½Xªº®t¡AidBetweenRow¡×¨C¤@¦æ¶}©lªºÀRºA±±¥óÃѧO½Xªº®t
                LOCAL   idBetweenRow,difference,StartID:DWORD
                mov     bArrange,0
    .IF direct==TOPTODOWN
        ;¦pªG¬O¥Ñ¤W¦Ó¤U¡A§C¦ì§}¥ÑIDS_0C¶}©l¡AID¨C¦¸´î4¡F¨C´«¤@¦æ¡AStartID¼W¥[¤@(¦¹³Bªº¤@°O¿ý¦bidBetweenRowùØ)
                mov     StartID,IDS_0C
                mov     difference,-4
                mov     idBetweenRow,1
    .ELSEIF direct==DOWNTOTOP
        ;¦pªG¬O¥Ñ¤U¦Ó¤W¡A§C¦ì§}¥ÑIDS_00¶}©l¡AID¨C¦¸¥[4¡F¨C´«¤@¦æ¡AStartID¼W¥[¤@(¦¹³Bªº¤@°O¿ý¦bidBetweenRowùØ)
                mov     StartID,IDS_00
                mov     difference,4
                mov     idBetweenRow,1
    .ELSEIF direct==RIGHTTOLEFT
        ;¦pªG¬O¥Ñ¥k¦Ó¥ª¡A§C¦ì§}ÃѧO½X¥ÑIDS_03¶}©l¡AID¨C¦¸´î¤@¡F¨C´«¤@¦C¡AStartID¼W¥[¥|(¦¹³Bªº¥|°O¿ý¦bidBetweenRowùØ)
                mov     StartID,IDS_00
                mov     difference,1
                mov     idBetweenRow,4
    .ELSE
        ;¦pªG¬O¥Ñ¥ª¦Ó¥k¡A§C¦ì§}¥ÑIDS_03¶}©l¡AID¨C¦¸¥[¤@¡F¨C´«¤@¦C¡AStartID¼W¥[¥|(¦¹³Bªº¥|°O¿ý¦bidBetweenRowùØ)
                mov     StartID,IDS_03
                mov     difference,-1
                mov     idBetweenRow,4
    .ENDIF
  ;¦@¥|¦æ¡A°O¿ý¦browÅܼÆùØ¡A¥Ñ0¶}©l¨ì3
                mov     row,0
    .WHILE row<4
        ;¨ú±o¤@¦æ¤ºªº¥|­ÓÀRºA±±¥ó¼Æ­È¡A¦s©ódwN°}¦C¤¤
                mov     eax,StartID
                mov     n,0
                mov     ID,eax
        .WHILE n<4
                INVOKE  GetDlgItemInt,hDialog,ID,0,FALSE
                mov     edi,n
                shl     edi,2
                mov     dwN[edi],eax
                mov     ecx,difference
                inc     n
                add     ID,ecx
        .ENDW
        ;©I¥sarrange_a_row°Æµ{¦¡¡A¾ã²zÁY´î¤@¦æ
                call    arrange_a_row
            .IF !CARRY?
                inc     bArrange
            .ENDIF
        ;§â¾ã²z«áªº¼Æ­ÈÅܦ¨¦r¦ê¡AµM«á§âÀRºA±±¥ó¼ÐÃD³]¬°¦¹¦r¦ê
                mov     eax,StartID
                mov     n,0
                mov     ID,eax
        .WHILE n<4
                mov     edi,n
                shl     edi,2
                INVOKE  wsprintf,OFFSET szBuffer,OFFSET szNumFmt,dwN[edi]
                INVOKE  SetDlgItemText,hDialog,ID,OFFSET szBuffer
                mov     ecx,difference
                add     ID,ecx
                inc     n
        .ENDW
                inc     row
                mov     eax,idBetweenRow
                add     StartID,eax
    .ENDW
    .IF bArrange>0
                clc
    .ELSE
                stc
    .ENDIF
                ret
arrange_matrix  ENDP
;---------------------------------------------------------------------------------------------------
;«Ø¥ßµe¨ê¡A¦¹µe¨ê¥Î©ó¶îº¡ÀRºA±±¥óªº­I´ºÃC¦â¡A­I´ºÃC¦â¨Ì·ÓÀRºA±±¥ó¼ÐÃDªº¼Æ­È¤£¦P¦Ó¤£¦P¡C©Ò«Ø¥ßªºµe¨ê
;¦s©óhbrBkStatic°}¦C
create_bk_brush PROC
                LOCAL   n:DWORD
                mov     n,0
        .WHILE n<=16
                mov     edx,n
                INVOKE  CreateSolidBrush,crBk[edx*4]
                mov     edx,n
                mov     hbrBkStatic[edx*4],eax
                inc     n
        .ENDW
                ret
create_bk_brush ENDP
;---------------------------------------------------------------------------------------------------
delete_bk_brush PROC
                LOCAL   n
                mov     n,0
        .WHILE n<=17
                mov     edx,n
                INVOKE  DeleteObject,hbrBkStatic[edx*4]
                inc     n
        .ENDW
                INVOKE  DeleteObject,hbrBkDlg
                INVOKE  DeleteObject,hbrBkScore
                ret
delete_bk_brush ENDP
;---------------------------------------------------------------------------------------------------
;ªð¦^®É¡AEAX¬°0¡ã(iRange-1)ªº¶Ã¼Æ
tiny_random     PROC    USES edx iRange
                LOCAL   A,B:DWORD
                rdtsc
                mov     B,0
                mov     A,100711433
                adc     eax,edx
                adc     eax,B
                mul     A
                adc     eax,edx
                mov     B,eax
                mul     iRange
                mov     eax,edx
                ret
tiny_random     ENDP
;---------------------------------------------------------------------------------------------------
;¦bªÅ¥ÕªºÀRºA±±¥ó¤¤¡A¥H¶Ã¼Æ¿ï©w¨ä¤¤¤@­ÓÀRºA±±¥ó¡A¨Ã±N¨ä¼ÐÃD¬°¡u2¡v©Î¡u4¡v
;ªð¦^­È¡GNC¡Ð¦¨¥\ªº³]©w¦nÀRºA±±¥ó
;¡@¡@¡@¡@CY¡Ð¥¢±Ñ¡C­YEAX¡×1¡Aªí¥Ü¨S¦³ªÅ¥ÕªºÀRºA±±¥ó¡F­YEAX¡×0¡Aªí¥Ü¶È¦³¤@­ÓªÅ¥ÕªºÀRºA±±¥ó¡A¦ý³]©w«áµLªkÁY´î
set_number_in_random    PROC
                LOCAL   idBlankStatic[10h]:DWORD
                LOCAL   nBlankStatic:DWORD
                LOCAL   id,n:DWORD
                LOCAL   pidBlankStatic:LPSTR    ;idBlankStatic°}¦Cªº«ü¼Ð
                mov     n,0                     ;n¬°¼ÐÃD¬°¡u0¡vªºÀRºA±±¥ó­Ó¼Æ¡A¦¹³B¥ý³]¬°0
                mov     id,IDS_00
                lea     edx,idBlankStatic
                mov     pidBlankStatic,edx
    ;´M§ä¼ÐÃD¬°¡u0¡vªºÀRºA±±¥óÃѧO½X¡A¦s¤JidBlankStatic°}¦C¤¤
    .WHILE id<=IDS_0F
                INVOKE  GetDlgItemInt,hDialog,id,NULL,FALSE
        .IF eax==0
                mov     eax,pidBlankStatic
                mov     edx,id
                mov     [eax],edx
                add     pidBlankStatic,4
                inc     n
        .ENDIF
                inc     id
    .ENDW
                cmp     n,0
                je      no_blank
    ;¦bidBlankStatic°}¦C¤¤¡A¥H¶Ã¼Æ¨ú¥X¤@­ÓÀRºA±±¥óªºÃѧO½X
                INVOKE  tiny_random,n
                shl     eax,2
                lea     edx,idBlankStatic
                add     edx,eax
                mov     ecx,[edx]       ;ECX¡×¨ú¥XªºÀRºA±±¥óÃѧO½X
                INVOKE  tiny_random,10h
        .IF eax<0ch
                mov     edx,OFFSET szTwo
        .ELSE
                mov     edx,OFFSET szFour
        .ENDIF
    ;³]©w¶Ã¼Æ¿ï¥XªºÀRºA±±¨î¶µªº¼ÐÃD¬°EDX©Ò«ü¦r¦ê
                INVOKE  SetDlgItemText,hDialog,ecx,edx
    ;¦pªGn¡×1¡Aªí¥Ü¤w¨S¦³ªÅ®æ¡AÀˬd¨C¤@­ÓÀRºA±±¥ó¤W¤U¥ª¥k¬O§_¯àÁY´î
        .IF n==1
                call    check_gameover
                or      eax,eax
                jz      failure
        .ENDIF
                clc
                jmp     exit
no_blank:       mov     eax,1
failure:        stc
exit:           ret
set_number_in_random    ENDP
;---------------------------------------------------------------------------------------------------
initial_game    PROC
                LOCAL   idCtrl:DWORD
                mov     idCtrl,IDS_00
                INVOKE  GetDlgItemInt,hDialog,IDS_BEST,0,0      ;¨ú±o¥Ø«e³Ì°ª°O¿ý¡A¦s©ódwBest
        .IF eax>dwBest
                mov     dwBest,eax
        .ENDIF
        .WHILE idCtrl<=IDS_0F
                INVOKE  SetDlgItemText,hDialog,idCtrl,OFFSET szZero
                inc     idCtrl
        .ENDW
                mov     dwScore,0
                call    set_number_in_random
                call    set_number_in_random
                ret
initial_game    ENDP
;---------------------------------------------------------------------------------------------------
new_button_proc PROC    hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
.IF uMsg==WM_KEYDOWN
        .IF (wParam>=VK_LEFT)&&(wParam<=VK_DOWN)
                INVOKE  SendMessage,hDialog,WM_KEYDOWN,wParam,lParam
        .ELSEIF wParam==VK_CONTROL
                mov     bCtrlDown,TRUE
        .ELSEIF wParam==VK_Z
                INVOKE  SendMessage,hDialog,WM_CHAR,wParam,lParam
        .ELSE
                INVOKE  CallWindowProc,lpOldButtonProc,hWnd,uMsg,wParam,lParam
                ret
        .ENDIF
.ELSEIF uMsg==WM_GETDLGCODE
                mov     eax,DLGC_WANTALLKEYS
                ret
.ELSE
                INVOKE  CallWindowProc,lpOldButtonProc,hWnd,uMsg,wParam,lParam
                ret
.ENDIF
                xor     eax,eax
                ret
new_button_proc ENDP
;---------------------------------------------------------------------------------------------------
;Àx¦s·í«eªºª¬ºA¡A·í¨Ï¥ÎªÌ«ö¤UCtrl-Z®É¡A¶·ªð¦^·í«eª¬ºA
save_number     PROC
                LOCAL   n:DWORD
                mov     n,0
        .WHILE n<10h
                mov     ecx,n
                add     ecx,IDS_00
                INVOKE  GetDlgItemInt,hDialog,ecx,0,FALSE
                mov     edx,n
                mov     number[edx*4],eax
                inc     n
        .ENDW
                mov     edx,dwScore     ;Àx¦s·í¤U¤À¼Æ
                mov     dwOldScore,edx
                ret
save_number     ENDP
;---------------------------------------------------------------------------------------------------
;§ânumber°}¦C¤¤ªº¼Æ­ÈÅܦ¨¦r¦ê¡AµM«á§â¦U­Ó®|±±±±¥óªº¼ÐÃD³]¬°¬Û¹ïÀ³ªº¦r¦ê
restore_number  PROC
                LOCAL   n:DWORD
                mov     n,0
        .WHILE n<10h
                mov     edx,n
                INVOKE  wsprintf,OFFSET szBuffer,OFFSET szNumFmt,number[edx*4]
                mov     edx,n
                add     edx,IDS_00
                INVOKE  SetDlgItemText,hDialog,edx,OFFSET szBuffer
                inc     n
        .ENDW
                mov     edx,dwOldScore
                mov     dwScore,edx
                ret
restore_number  ENDP
;---------------------------------------------------------------------------------------------------
;¥Ñ¼Æ­È´«ºâ¦¨¦ì§}¡A¥Î©ó­pºâ¬Y­Ó¼Æ­È¬O¦bhbrBkStatic°}¦C¤¤ªº­þ­Ó°¾²¾¦ì§}
;¡@¡@¼Æ­È(¤Q¶i¦ì)   0  2  4  8  16  32  64  128  256  512  1024  2048  4096
;°¾²¾¦ì§}(¤Q¤»¶i¦ì) 0  4  8  C  10  14  18   1C   20   24    28    2C    30
;¿é¤J¡GEAX¡Ð¼Æ­È
;¿é¥X¡GEDX¡Ð°¾²¾¦ì§}
get_index       PROC
                sub     edx,edx
                cmp     eax,edx
                je      finish1
@@:             shr     eax,1
                jc      finish0
                inc     edx
                jmp     @b
finish0:        shl     edx,2
finish1:        ret
get_index       ENDP
;---------------------------------------------------------------------------------------------------
;¹ï¸Ü²°ªºµøµ¡¨ç¦¡
DlgProc         PROC    hDlg:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
                LOCAL   BkColor:DWORD
                LOCAL   rect:RECT
                LOCAL   hfont:HFONT
                LOCAL   szText[10h]:BYTE
.IF uMsg==WM_INITDIALOG
                INVOKE  CreateFile,OFFSET szFilename,GENERIC_READ or GENERIC_WRITE,0,0,OPEN_ALWAYS,\
                        FILE_ATTRIBUTE_NORMAL,0
                mov     hFile,eax
        ;¦pªGŪ¨ú¨ì4­Ó¦ì¤¸²Õªí¥ÜBEST2048.TXT¤w¦s¦b¡F§_«hªí¥Ü¨S¦³BEST2048.TXTÀÉ®×
                INVOKE  ReadFile,hFile,OFFSET dwBest,4,OFFSET BytesRead,0
        .IF DWORD PTR [BytesRead]==4
                mov     eax,dwBest
        .ELSE
                sub     eax,eax
        .ENDIF
            ;§â³Ì°ª°O¿ýÅã¥Ü¦bIDS_BESTÀRºA±±¥ó¤W
                INVOKE  wsprintf,OFFSET szBuffer,OFFSET szNumFmt,eax
                INVOKE  SetDlgItemText,hDlg,IDS_BEST,OFFSET szBuffer
                mov     ecx,hDlg
                mov     hDialog,ecx
            ;¤lÃþ§O¤Æ«ö¶s
                INVOKE  GetDlgItem,hDlg,IDB_NEW
                INVOKE  SetWindowLong,eax,GWL_WNDPROC,OFFSET new_button_proc
                mov     lpOldButtonProc,eax
            ;³]©w¹Ï¥Ü
                INVOKE  LoadIcon,hInstance,OFFSET szDlgName
                INVOKE  SendMessage,hDlg,WM_SETICON,ICON_SMALL,eax
            ;«Ø¥ßÀRºA±±¥óªº­I´ºµe¨ê
                call    create_bk_brush
            ;«Ø¥ß¹ï¸Ü²°ªº­I´ºµe¨ê
                INVOKE  CreateSolidBrush,0a0adbbh
                mov     hbrBkDlg,eax
            ;«Ø¥ß¤À¼Æ(IDS_MARK¡BIDS_BEST¡BIDS_MARKTEXT¡BIDS_BESTTEXT)­I´ºµe¨ê
                INVOKE  CreateSolidBrush,0909caah
                mov     hbrBkScore,eax
            ;«Ø¥ßÅÞ¿è¤å¦r¡AÀRºA±±¥ó¼ÐÃD¤p©óµ¥©ó64ªÌ¥ÎhFont[0]¡B¤j©ó64¥B¤p©óµ¥©ó8192ªÌ¥ÎhFont[4]
                INVOKE  CreateFont,48,0,0,0,800,0,0,0,0,0,0,0,0,OFFSET szFontFace
                mov     hFont[0],eax
                INVOKE  CreateFont,40,0,0,0,800,0,0,0,0,0,0,0,0,OFFSET szFontFace
                mov     hFont[4],eax
                INVOKE  CreateFont,32,0,0,0,800,0,0,0,0,0,0,0,0,OFFSET szFontFace
                mov     hFont[8],eax
                call    initial_game
                jmp     complete
 
.ELSEIF uMsg==WM_CTLCOLORDLG
                mov     eax,hbrBkDlg
                ret
 
.ELSEIF uMsg==WM_CTLCOLORSTATIC
                INVOKE  GetDlgCtrlID,lParam
                mov     ecx,eax
    .IF (ecx==IDS_MARK)||(ecx==IDS_BEST)
                mov     ecx,0ffffffh
                mov     BkColor,0909caah
                push    hbrBkScore
    .ELSEIF (ecx==IDS_MARKTEXT)||(ecx==IDS_BESTTEXT)
                mov     ecx,crScoreText
                mov     BkColor,0909caah
                push    hbrBkScore
    .ELSE
                INVOKE  GetDlgItemInt,hDlg,ecx,0,FALSE
        .IF eax==0
                mov     ecx,cr0Text
                sub     edx,edx
        .ELSEIF eax==2
                mov     ecx,cr2Text
                mov     edx,4
        .ELSEIF eax==4
                mov     ecx,cr2Text
                mov     edx,8
        .ELSE
                call    get_index
                mov     ecx,cr8Text
        .ENDIF
                push    hbrBkStatic[edx]
                mov     eax,crBk[edx]
                mov     BkColor,eax
    .ENDIF
                INVOKE  SetTextColor,wParam,ecx
                INVOKE  SetBkColor,wParam,BkColor
                pop     eax
                ret
 
.ELSEIF uMsg==WM_DRAWITEM
                ASSUME  ebx:PTR DRAWITEMSTRUCT
                push    ebx
                mov     ebx,lParam
                INVOKE  GetClientRect,[ebx].hwndItem,ADDR rect
                INVOKE  GetDlgItemText,hDlg,[ebx].CtlID,ADDR szText,8
                INVOKE  GetDlgItemInt,hDlg,[ebx].CtlID,0,FALSE
        .IF eax<=64
                mov     ecx,hFont[0]
        .ELSEIF (eax>64)&&(eax<=8192)
                mov     ecx,hFont[4]
        .ELSE
                mov     ecx,hFont[8]
        .ENDIF
                mov     hfont,ecx
                call    get_index
                INVOKE  FillRect,[ebx].hdc,ADDR rect,hbrBkStatic[edx]
                INVOKE  SelectObject,[ebx].hdc,hfont
                INVOKE  DrawText,[ebx].hdc,ADDR szText,-1,ADDR rect,DT_CENTER or DT_SINGLELINE or DT_VCENTER
                pop     ebx
                ASSUME  ebx:NOTHING
 
.ELSEIF uMsg==WM_COMMAND
                mov     eax,wParam
                and     eax,0ffffh      ;EAX¡×ÃѧO½X
        .IF eax==IDB_EXIT
                jmp     exit
        .ELSEIF eax==IDB_NEW
restart:        call    initial_game
                jmp     complete
        .ENDIF
 
.ELSEIF uMsg==WM_KEYDOWN
                call    save_number
   .IF wParam==VK_DOWN
                mov     ecx,TOPTODOWN
   .ELSEIF wParam==VK_UP
                mov     ecx,DOWNTOTOP
   .ELSEIF wParam==VK_RIGHT
                mov     ecx,LEFTTORIGHT
   .ELSEIF wParam==VK_LEFT
                mov     ecx,RIGHTTOLEFT
   .ENDIF
                INVOKE  arrange_matrix,ecx
                jc      complete
                call    set_number_in_random
                jnc     complete
            ;¹CÀ¸µ²§ô¡A¥ý¤ñ¸û¬O§_¶W¶V³Ì°ª°O¿ý¡A¦pªG¶W¶V³Ì¨Î°O¿ý¡A§â³Ì°ª¤À¼Æ¼g¤JÀÉ®×
                mov     eax,dwScore
            .IF eax>dwBest
                mov     dwBest,eax
                INVOKE  wsprintf,OFFSET szBuffer,OFFSET szNumFmt,eax
                INVOKE  SetDlgItemText,hDlg,IDS_MARK,OFFSET szBuffer
                INVOKE  SetFilePointer,hFile,0,0,FILE_BEGIN
                INVOKE  WriteFile,hFile,OFFSET dwScore,4,OFFSET BytesWritten,0
            .ENDIF
            ;Åã¥Ü¼u¥X¹ï¸Ü²°¡A¸ß°Ý¬O§_­nÄ~Äòª±¡H
                INVOKE  MessageBox,hDlg,OFFSET szFailure,OFFSET szFailureTitle,MB_OKCANCEL or MB_ICONSTOP
            .IF eax==IDOK
                jmp     restart
            .ELSE
                jmp     exit
            .ENDIF
complete:       INVOKE  wsprintf,OFFSET szBuffer,OFFSET szNumFmt,dwScore
                INVOKE  SetDlgItemText,hDlg,IDS_MARK,OFFSET szBuffer
                INVOKE  GetDlgItemInt,hDlg,IDS_BEST,0,0
            .IF eax<dwScore
                INVOKE  SetDlgItemText,hDlg,IDS_BEST,OFFSET szBuffer
            .ENDIF
 
.ELSEIF uMsg==WM_CHAR
   .IF bCtrlDown==TRUE
                mov     bCtrlDown,FALSE
      .IF (wParam=="Z")||(wParam=="z")
                call    restore_number
                jmp     complete
      .ENDIF
   .ENDIF
 
.ELSEIF uMsg==WM_CLOSE
exit:           call    delete_bk_brush
            ;Àˬd¬O§_¶W¶V³Ì°ª°O¿ý
                mov     eax,dwScore
            .IF eax>dwBest
                mov     dwBest,eax
                INVOKE  SetFilePointer,hFile,0,0,FILE_BEGIN
                INVOKE  WriteFile,hFile,OFFSET dwScore,4,OFFSET BytesWritten,0
            .ENDIF
                INVOKE  CloseHandle,hFile
                INVOKE  EndDialog,hDlg,NULL
 
.ELSE           ;¨ä¥L¥¼³B²zªº°T®§ªð¦^ FALSE
                mov     eax,FALSE
                ret
 
.ENDIF          ;¤w³B²zªº°T®§¡Aªð¦^ TRUE
                mov     eax,TRUE   
                ret
DlgProc         ENDP
;---------------------------------------------------------------------------------------------------
start:          call    InitCommonControls
                INVOKE  GetModuleHandle,NULL
                mov     hInstance,eax
                INVOKE  DialogBoxParam,hInstance,OFFSET szDlgName,NULL,OFFSET DlgProc,NULL
                INVOKE  ExitProcess,eax
;***************************************************************************************************
END             start

¤U¸ü 2048.ico «á¡A§â¥¦©M 2048.EXE.MANIFEST¡B2048.RC¡B2048.ASM ©ñ¦b¦P¤@¤l¥Ø¿ý¤U¡A¤@¤U­±¨BÆJ²ÕĶ¤Î³sµ²¡A´N¥i¥H±o¨ì 2048.exe ¥i°õ¦æÀÉ¡A±q¦¹§Y¨Ï¤£³s¤Wºô»Úºô¸ô¡A¤]¯à³æ¾÷¨Ï¥Î¡C

E:\HomePage\SOURCE\Win32\2048>rc 2048.rc [ENTER]

E:\HomePage\SOURCE\Win32\2048>ml 2048.asm /link 2048.res [ENTER]
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

 Assembling: 2048.asm

***********
ASCII build
***********

Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

/SUBSYSTEM:WINDOWS
"2048.obj"
"/OUT:2048.exe"
"2048.res"

E:\HomePage\SOURCE\Win32\2048>

¸Ñ»¡

¨ä¹ê¡A³o¤@³¹ªº¥DÃD¤w¸g¦b¤W­±»¡§¹¤F¡A¥u¬O³o­Ó½d¨Ò¡A2048¡Aªº¨ä¥L³¡¥÷«o¬O½ÆÂø¡A©Ò¥H©³¤Uªº»¡©ú¡A¨Ã¨S¦³´£¨ì¹ï¸Ü²°ªº°T®§¶Ç»¼³¡¥÷¡C

¹ï¸Ü²°¤ÎÀRºA±±¥óªº¥~Æ[

¹ï¸Ü²°ªº­I´ºÃC¦â

¦b§@·~¨t²Î­nµe¥X¹ï¸Ü²°¤§«e¡A§@·~¨t²Î·|¥ýµo¥X WM_CTLCOLORDLG µ¹¹ï¸Ü²°¨ç¦¡¡Aµ{¦¡¥i¥H³B²z WM_CTLCOLORDLG °T®§¥H§ïÅܹï¸Ü²°ªº­I´ºÃC¦â¡A¥u»Ý¦b³B²z§¹ WM_CTLCOLORDLG ®É¡A¶Ç¦^µe¨ê¥N½X§Y¥i¡A¶Ç¦^­È¥²¶·©ñ¦b EAX ¼È¦s¾¹ùØ¡A§@·~¨t²Î·|¥H¦¹µe¨ê¶ñº¡¹ï¸Ü²°­I´º¡C°Ñ¨£µ{¦¡²Ä 503¡ã505 ¦æ¡C

ÀRºA±±¥óªº­I´ºÃC¦â¡B¤å¦r­I´ºÃC¦â»P¤å¦rÃC¦â

³o¤@¤p¸`ªº¼ÐÃD¬O¡uÀRºA±±¥óªº­I´ºÃC¦â¡B¤å¦r­I´ºÃC¦â»P¤å¦rÃC¦â¡v¡A­nª¾¹D¡A³o¤TºØ°Ï°ì¬O¤£¦Pªº¦a¤è¡A¥i¥H°Ñ¦Ò¤W¹Ï¡C¤W¹Ï¤¤¡A¥ª¤W¨¤²Ä¤G­ÓÀRºA±±¥ó¡A¥HÂŦâ®Ø½u³ò¦íªº¬OÃѧO½X¬° IDS_01 ªºÀRºA±±¥ó¡A¦bÂŦâ®Ø½u¤º»Pµµ¬õ¦â®Ø½u¥~¡A¶î¤WªºÃC¦â¬OÀRºA±±¥óªº­I´ºÃC¦â¡C¤å¦r¡u2¡v¥~³ò³Qµµ¬õ¦â®Ø½u³ò¦íªº°Ï°ìºÙ¬°°Åµô¯x§Î¡A¦b°Åµô¯x§Î¤º¡A¦Ó¥B¦©°£¤å¦r¥~ªº°Ï°ì¤~ºÙ¬°¡u¤å¦rªº­I´º¡v¡A¤å¦rªºÃC¦â»P¤å¦rªº­I´ºÃC¦â¤£¦P®É¡A¤H²´¤~¯à¤À¿ë¡C

­n³]©w¤å¦rªºÃC¦â»P¤å¦r­I´ºÃC¦â¡A¥i¥H¦b³B²z WM_CTLCOLORSTATIC ®É¡A¤À§O©I¥s SetBkColor »P SetTextColor¡C¦ý¬O¡A¦pªG­n³]©wÀRºA±±¥óªº­I´ºÃC¦â¡A¥i¤À¬°¨âºØ±¡§Î¡C²Ä¤@ºØ¬O¡A¦pªGÀRºA±±¥ó¤£¨ã¦³¡uSS_OWNERDRAW¡v­·®æ¡A¨º»ò¡A¦P¹ï¸Ü²°¤@¼Ë¡A¦b³B²z WM_CTLCOLORSTATIC °T®§µ²§ô®É¡A¶Ç¦^µe¨ê¥N½X¡A§@·~¨t²Î´N·|¥H¦¹µe¨ê§âÀRºA±±¥óªº­I´º¶îº¡¡C²Ä¤GºØ¡A¦pªG¬OÀRºA±±¥ó¨ã¦³¡uSS_OWNERDRAW¡v­·®æ¡A¨º»òµ{¦¡±o¦Û¦æø¥X­I´ºÃC¦â¡A½Ð°Ñ¦Ò©³¤UÀRºA±±¥óªº¦r§Î¡C°²¦pÀRºA±±¥ó¨ã¦³¡uSS_OWNERDRAW¡v­·®æ¡A¦Óµ{¦¡¦b³B²z§¹ WM_CTLCOLORSTATIC¡A¶Ç¦^µe¨ê¡A¬O¨S¦³®Äªº¡F¤£¹L¹ï©ó¥Î SetBkColor »P SetTextColor ³]©w¤å¦r­I´º¦â©M¤å¦rÃC¦â¡A«o¤£ºÞÀRºA±±¥ó¬O§_¨ã¦³¡uSS_OWNERDRAW¡v­·®æ¡A³£¬O¦³®Äªº¡C

¦b 2048 ¹ï¸Ü²°ùئ@¦³ 20 ­ÓÀRºA±±¥ó¡A¦³¥|­Ó¬O»P¤À¼Æ¦³Ãöªº¡A¨ä¤¤¨â­Ó¬O¡uSCORE¡v»P¡uBEST¡v¡A³o¨â­ÓÀRºA±±¥óªº¤å¦rÃC¦â¬Û¦P¡B¤å¦r­I´ºÃC¦â¬Û¦P¡BÀRºA±±¥ó­I´ºÃC¦â¤]¬Û¦P¡F¥t¥~¨â­Ó¬O·í«e¤À¼Æ»P³Ì°ª¤À¼Æ¡A¥¦­Ìªº¤å¦rÃC¦â¡B¤å¦r­I´ºÃC¦â»PÀRºA±±¥ó­I´ºÃC¦â¤]³£¬Û¦P¡C³Ì«á¬O¹ï¸Ü²°ùئû³Ì¤j°Ï°ìªº 4¡Ñ4 ­ÓÀRºA±±¥ó©Ò²Õ¦¨ªº¯x°}¡A¥¦­Ì©ÒÅã¥Üªº¤å¦rÃC¦â¡B¤å¦r­I´ºÃC¦â»PÀRºA±±¥ó­I´ºÃC¦â·|ÀHµÛÀRºA±±¥óªº¼ÐÃD¦Ó§ïÅÜ¡CÁ¿¤F³o»ò¦h¡A·N«ä´N¬O»¡¡A¦b 2048 ùتºÀRºA±±¥ó¡A¦@¤À¬°¤TºØ¡A¦]¦¹¦b 508¡ã509 ¦æ¨ú±oÀRºA±±¥óªºÃѧO½X«á¡A¥ß§Y¶i¤J¤TºØ¡u¤À¤ä¡v¡C²Ä¤@ºØ¬O 510¡ã513 ¦æ¡A³B²z·í«e¤À¼Æ»P³Ì°ª¤À¼ÆªºÃC¦â¡F²Ä¤GºØ¬O 514¡ã517 ¦æ¡A³B²z¡uSCORE¡v»P¡uBEST¡vªºÃC¦â¡F²Ä¤TºØ¬O 518¡ã536 ¦æ¡A³B²z 4¡Ñ4 Åã¥Ü¼Æ­ÈªºÀRºA±±¥ó¡C³B²z³o¤TºØÀRºA±±¥ó§¹«á¡A³£¬O§â¤å¦rÃC¦â¦s¤J ECX ùØ¡A¤å¦r­I´ºÃC¦â¦s¤J BkColor ùØ¡AÀRºA±±¥ó­I´ºµe¨ê±À¤J°ïÅ|ùØ¡C¨ì¤F²Ä 537¡ã539 ¦æ®É¡A¦A¥H³o¨Ç¼Æ­È³]©w¤å¦rÃC¦â¡B¤å¦r­I´ºÃC¦â©MÀRºA±±¥ó­I´ºÃC¦â¡C

ÀRºA±±¥óªº¦r§Î

¦pªG¤£¯S§O³]©w¡AÀRºA±±¥óªº¦r§Î¬O¥Ñ¸ê·½´y­zÀɤ¤ªº¹ï¸Ü²°­±ªOªº¶µ¥Ø¡uFONT¡v¨Ó©w¸q¡A³oºØ°µªk·|¨Ï¹ï¸Ü²°¤¤©Ò¦³±±¥ó¦r§Î³£¬O¬Û¦Pªº¡C°£¦¹¤§¥~¡A§Ú­Ì¤]¥i¥H¸g¥Ñ³]©wÀRºA±±¥óªº­·®æ¬°¡uSS_OWNERDRAW¡v¡A¨Ó³æ¿W§ïÅܬY­ÓÀRºA±±¥óªº¦r§Î¡C¦pªGÀRºA±±¥óªº­·®æ§t¦³¡uSS_OWNERDRAW¡v¡A¤£ºÞ¦b¤°»ò®É­Ô¡A§@·~¨t²Î©ó¿Ã¹õ¤Wø¥XÀRºA±±¥ó®É¡A´N·|¹ï¸ÓÀRºA±±¥óªº¤÷µøµ¡¤§µøµ¡¨ç¦¡µo¥X¡uWM_DRAWITEM¡v°T®§¡Aµ{¦¡´N¥i¥H¦b¦¹°T®§¤¤§ïÅܦr§Î¡C¦³Ãö WM_DRAWITEM °T®§¡A½Ð°Ñ¦Ò²Ä¤Q¤G³¹ WM_DRAWITEM °T®§»P DRAWITEMSTRUCT µ²ºcÅé ¡C¦b 2048 µ{¦¡ùØ¡A¦]¬°¼Æ­È¦ì¼Æ¤£¦P¡A©Ò¥H¨º 4¡Ñ4 ÀRºA±±¥ó©Òºc¦¨ªº¯x°}¡A±o¥Î¤£¦Pªº¦r§Î¡A¦]¦¹³o 16 ­ÓÀRºA±±¥ó§¡¨ã¦³¡uSS_OWNERDRAW¡v­·®æ¡C

¦b 2048 ªº²Ä 543¡ã545 ¤T¦æùØ¡A¥ý§â EBX «ü©w¬° DRAWITEMSTRUCT ©Ò¦b¦ì§}¡C±µµÛªº²Ä 546¡ã548 ¦æ¡A¬O¨ú±oÀRºA±±¥óªº¤u§@°Ï¤j¤p¡B¨ú±oÀRºA±±¥óªº¼ÐÃD ( ¦s©ó szText ¦r¦êùØ ) ¤Î¼Æ­È¡C±µµÛ²Ä 549¡ã555 ¦æ¡A®Ú¾Ú¼Æ­È¦³´X¦ì¼Æ¡A¿ï¾Ü¾A·íªº¦r§Î¡A³o¨Ç¦r§Î¦b²Ä 493¡ã499 ¦æ³Q«Ø¥ß¡A¦s©ó hFont °}¦C¤¤¡C±zÀ³·í¥i¥H¬Ý¥X¨Ó¡A¦pªGÀRºA±±¥óªº¼Æ­È¶È¦³­Ó¦ì¼Æ©Î¨â¦ì¼Æ¡A¨Ï¥Î hFont[0] ¦r§Î¡A¥ç§Y 48 ÂIªº¡uVerdana¡v¦rÅé¡F¦pªG¬O¤T¦ì¼Æ¡B¥|¦ì¼Æ¡A«h¨Ï¥Î hFont[4] ¦r§Î¡A¥ç§Y 40 ÂIªº¡uVerdana¡v¦rÅé¡F¦pªG¬O¤­¦ì¼Æ¡A«h¨Ï¥Î hFont[8] ¦r§Î¡A¥ç§Y 32 ÂIªº¡uVerdana¡v¦rÅé¡C³Ì«á¦b²Ä 556 ¦æ¡A§â³Q¿ï©wªº¦r§Î¥N½X¦s¤J°Ï°ìÅܼơAhfont¡AùØ¡C¨ì¤F²Ä 559 ¦æ¡A©I¥s SelectObject¡A§â¸Ó¦r§Î¿ï¤J¨ìÀRºA±±¥óªº³]³Æ¤º®e ( device context ) ùØ¡A¨º»ò¡A³o­ÓÀRºA±±¥óªº¼ÐÃD¦r§Î´N·|§ïÅܤF¡C

²Ä 557¡ã558 ¦æ¡A¥D­nªº¥Øªº¬O¦b¾ã­ÓÀRºA±±¥ó¤Wµe¤W¤@­Ó¶ñº¡ªºªø¤è§Î¡C¬°¤°»ò­n³o¼Ë°µ©O¡H­ì¨Ó¨ã¦³¡uSS_OWNERDRAW¡v­·®æªºÀRºA±±¥ó¬OµLªk§Q¥Î³B²z WM_CTLCOLORSTATIC «á¡A¶Ç¦^µe¨ê¥H¶ñº¡¾ã­ÓÀRºA±±¥ó¡A¥²¶·¦Û¦æø»s­I´º¡A©Ò¦³¤~¥s¨Ï¥ÎªÌ¦Û¦æø»s¡C¦]¦¹¡A¦b²Ä 558 ¦æ¡A©I¥s FillRect ¶ñº¡­I´º¡C©I¥s FillRect ©Ò»Ýªº³]³Æ¤º®e¥N½X ( hDC ) ¥i¥Ñ DRAWITEMSTRUCT µ²ºcÅ骺 hdc Äæ¦ì±oª¾¡A¯x§Î¤j¤p¥Ñ²Ä 546 ¦æ¨ú±o¡A¸Ó¯x§Î¤j¤p´N¬OÀRºA±±¥óªº¤u§@°Ï¤j¤p¡CFillRect ©Ò»Ýµe¨ê¥N½X«h¦b hbrBkStatic °}¦C¤¤¡C¦ý¬O©Ò»Ýµe¨ê¬O¦b hbrBkStatic ªº²Ä´X­Ó¦ì§}¡A«h¬O¥Ñ get_index °Æµ{¦¡¨M©w¡Cget_index °Æµ{¦¡¦b²Ä 439¡ã454 ¦æ¡A¿é¤JÀRºA±±¥óªº¼ÐÃD¼Æ­Èµ¹ get_index¡Aget_index ·|Âà´«¸Ó¼Æ­È¦b hbrBkStatic °}¦Cªº°¾²¾¦ì§}¡A¦s©ó EDX ¶Ç¦^¨Ó¡C

initial_game °Æµ{¦¡

initial_game ¬O¥Î¨Óªì©l¤Æ¹CÀ¸ªº°Æµ{¦¡¡A¥¦­n°µªº¤u§@¦³¥|­Ó¡G①³]©w³Ì°ª¤À¼Æ¡B②§â¦ì©ó¹ï¸Ü²°¤¤¥¡³¡¥÷ªº 4¡Ñ4 ¯x°}¤ºªº 16 ­ÓÀRºA±±¥ó¼ÐÃD³]¬°¡u0¡v( ¦¹¡u0¡v¤D¬O¦r¦ê )¡B③§â·í«e¤À¼ÆÂk¹s¡B④¥H¶Ã¼Æ©ó 4¡Ñ4 ¯x°}¤¤ªºÀRºA±±¥ó¡AÀH¾÷¿ï¥X¨â­ÓÀRºA±±¥ó¨ÃÀH¾÷±N¨ä¼ÐÃD³]¬°¡u2¡v©Î¡u4¡v¡C«e¤T¶µÅãµM¬O«Ü²³æ¡A½Ð¦Û¦æ°Ñ¾\µ{¦¡²Ä 365¡ã376 ¦æ¡C³Ì«á¤@­Ó¤u§@²o¯A¨ì¶Ã¼Æ¡A¦b 2048 µ{¦¡¤¤¡A¨ú±o¶Ã¼Æªº°Æµ{¦¡¬O tiny_random¡F¦ÓÀH¾÷³]©w­þ¤@­ÓÀRºA±±¥ó«h¬O set_number_in_random °Æµ{¦¡¡C©³¤U¤p¤ì°¸­n¸Ñ»¡ªº¬Otiny_random¡Bset_number_in_random ³o¨â­Ó°Æµ{¦¡¡C

tiny_random °Æµ{¦¡

¦Ñ¹ê»¡¡Atiny_random °Æµ{¦¡¬O¤p¤ì°¸¦bTUTS4YOU ½×¾Â¤¤ªº Programming and Coding ±o¨ìªº¡A§@ªÌ¤£ª¾¬O½Ö¡CÁöµM¦³¤H ( Blue ) ¦b¸Ó½×¾Â¤Wµo¨¥»¡¡A³o­Óµ{¦¡¨C¦¸°õ¦æ®É¶Ç¦^ªº¶Ã¼Æ§¡¬°¡u2¡v¡A¦ý¬O¤p¤ì°¸¦b§Úªº AMD A4-3300 ¤W°õ¦æ¡A¨C¦¸µ²ªG§¡¤£¦P¡A«Ü²Å¦X¶Ã¼Æªº¦æ¬°¡C³o­Ó tiny_random °Æµ{¦¡»Ý­n¿é¤J¤@­Ó°Ñ¼Æ¡AiRange¡A¸g¹L­pºâ«á¡A¶Ç¦^ªº¶Ã¼Æ¦b 0 ¨ì ( iRange¡Ð1 ) ¤§¶¡¡A¥ç§Y¦pªG iRange ¬° 100¡A¶Ç¦^ªº¶Ã¼Æ¦b 0¡ã99 ¤§¶¡¡C

tiny_random °Æµ{¦¡¤@¶}©l¨Ï¥Î¤F RDTSC «ü¥O¡ARDTSC «ü¥O¬O Pentium CPU ·s¼Wªº¤@±ø«ü¥O¡A­ì¨Óªº­^¤å¦WºÙ¬O¡uReaD Time Stamp Counter¡v¡CPentium ©Î Pentium ¥H¤Wµ¥¯Åªº CPU ùØ­±¡A§t¦³¤@­Ó 64 ¦ì¤¸ªº¡u®É¯ß­p¼Æ¼È¦s¾¹¡v( time-stamp counter¡A²ºÙ TSC )¡C¤@¶}¾÷«á¡A®É¯ß­p¼Æ¼È¦s¾¹´N·|±q¹s¶}©l¡A¨C¸g¹L¤@­Ó®É¯ß¶g´Á ( clock cycle )¡A¨ä¤º¤§¼Æ­È´N¼W¥[¤@¡C¦³Ãö®É¯ß¶g´Á¡A¥i°Ñ¦Ò²Õ¦X»y¨¥·Ç³Æ¤u§@µù¤@¡C¦Ó RDTSC «ü¥O«h¬O¨ú¥X®É¯ß­p¼Æ¼È¦s¾¹¤§­È¡A¨Ã§â¥¦¦s¦b EDX:EAX ©Ò²Õ¦¨ªº 64 ¦ì¤¸¼È¦s¾¹¤º¡C¤£¦P¾÷«¬¡B¤£¦PºØÃþªº CPU¡A¨ä®É¯ß¶g´Á¤]¤£¦P¡C°²¦p¦³¤@­Ó CPU ¤u§@ÀW²v¬O 2000MHz ªº¸Ü¡A¥ç§Y¥Û­^®¶Àú¾¹¨C¬íÄÁ®¶°Ê 2¡Ñ109¦¸¡A¨C®¶°Ê¤@¦¸¡A´N·|¨Ï®É¯ß­p¼Æ¼È¦s¾¹¼W¥[¤@¡A¦]¦¹¨C¤@¬íÄÁ´N¥i¥H¨Ï®É¯ß­p¼Æ¼È¦s¾¹¼W¥[ 2¡Ñ109¡A2¡Ñ109 ¬O¤Q¤»¶i¦ìªº 77359400h¡A64 ¦ì¤¸¯à°÷Àx¦sªº³Ì¤j¼Æ­È¬O 0FFFFFFFFFFFFFFFFh¡A°£¥H 77359400h ±o¨ì 9223372036 ¬í¡A´«ºâ¦¨¦~¼Æ¡A¬ù 292 ¦~¡C

¦³®É­Ô RDTSC ¥²¶·¦b¯SÅvµ¥¯Å 0 ®É¤~¯à°õ¦æ¡A¨ú¨M©ó CPU ªº CR4 ¼È¦s¾¹¡C³o­Ó¼È¦s¾¹ªº²Ä 2 ­Ó¦ì¤¸ºÙ¬° TSD ºX¼Ð ( time stamp disable )¡A­Y³]©w¦¹ºX¼Ð ( ¥ç§Y TSD¡×1 )¡A´N¥u¯à¦b¯SÅvµ¥¯Å 0 ®É¤~¯àŪ¨ú¡u®É¯ß­p¼Æ¼È¦s¾¹¡v¡F§_«h¤£¨ü­­¨î¡C©¯¦nWindows §@·~¨t²Î¨Ã¨S¦³³]©w¦¹ºX¼Ð¡A¦]¦¹¥i©ñ¤ß¦b Windows §@·~¨t²Î¤¤¨Ï¥Î¡C

set_number_in_random °Æµ{¦¡

¹CÀ¸¤@¶}©l®É¡A¹ï¸Ü²°¤¤¥¡ªº 4¡Ñ4 ­ÓÀRºA±±¥ó©Ò²Õ¦¨ªº¯x°}¡A¼ÐÃD§¡¬°¡u0¡v¡A±µµÛ·|¥H¶Ã¼Æ¬D¥X¨ä¤¤¨â­Ó¡A¨Ï¨ä¼ÐÃD³]¬°¡u2¡v©Î¡u4¡v¡C¦b¹CÀ¸¹Lµ{¤¤¡A³o 4¡Ñ4 ªºÀRºA±±¥ó©Ò²Õ¦¨ªº¯x°}¤¤¡A¦³¨Ç¬OªÅ¥Õªº¡A¥ç§Y¼ÐÃD¬°¡u0¡v¡F¦³¨Ç¼ÐÃD¦b¡u2¡v¡ã¡u32768¡v¤§¶¡¡C¨C«ö¤@¦¸«öÁ䤧«á¡Aµ{¦¡¤]¥²¶·¥Ñ¼ÐÃD¬°¡u0¡vªºÀRºA±±¥ó¤¤¡AÀH¾÷¿ï¥X¤@­Ó±±¥ó¡A¨Ã§â¥¦¼ÐÃD³]¬°¡u2¡v©Î¡u4¡v¡C¤p¤ì°¸ªº°µªk¬O¡A¦b³o 4¡Ñ4 ªºÀRºA±±¥ó¡A§â¼ÐÃD¬°¡u0¡vªºÃѧO½X¬D¥X¨Ó¡A¦s¦b idBlankStatic °}¦C¤¤¡C¦b³o¹Lµ{ùØ¡A¥H pidBlankStatic ·í°µ¦b idBlankStatic ªº«ü¼Ð¡A¥H n ·í°µ¼ÐÃD¬°¡u0¡vªºÀRºA±±¥ó­Ó¼Æ¡C°Ñ¨£ 320¡ã335 ¦æ¡C

±µµÛÀˬd n ¬O§_¬°¹s¡A­Y¬°¹sªí¥Ü¨S¦³¼ÐÃD¬°¡u0¡vªºÀRºA±±¥ó¡A±N EAX ³]¬°¤@¡A¨Ã³]©w¶i¦ìºX¼Ð¡A¸õ¦^ set_number_in_random °Æµ{¦¡¡C­Y n ¤£¬°¹s¡A«h¦b idBlankStatic °}¦C¤¤¡A¥H¶Ã¼Æ¨ú¥X¤@­ÓÀRºA±±¥óªºÃѧO½X¡A¨£µ{¦¡²Ä 338¡ã343¡Cµ{¦¡²Ä 338¡ã343 ¦æ¡A¬O©I¥s tiny_random ÀH¾÷¨ú±o 0 ¨ì ( n¡Ð1 ) ªº¶Ã¼Æ¡A¥H¦¹¶Ã¼Æ¨ì idBlankStatic °}¦C¤¤¨ú¥X¬Y­ÓÀRºA±±¥óªºÃѧO½X¡C

µ{¦¡²Ä 344¡ã351 ¦æ¡A©I¥s tiny_random ±o¨ì 0 ¨ì 0Fh ªº¶Ã¼Æ¡A¦pªG¦¹¶Ã¼Æ¤p©ó 0Ch¡A«h§â¦¹ÀRºA±±¥ó¼ÐÃD³]¬°¡u2¡v¡A­Y¤j©ó©Îµ¥©ó 0Ch¡A«h§â¼ÐÃD³]¬°¡u4¡v¡C³o¼Ë´N¯à«OÃÒ·s²£¥Íªº¼ÐÃD¡A¥X²{¡u2¡vªº¾÷²v·|¤ñ¡u4¡v¨Ó±o¦h¡Cµ{¦¡²Ä 352¡ã357 ¦æ¡A³B²z n ¬O§_µ¥©ó¤@¡A¦pªGµ¥©ó¤@¡Aªí¥Ü³o¦¸¤w±N³Ì«á¤@­Ó¼ÐÃD¬O¡u0¡vªºÀRºA±±¥ó³]¬°¡u2¡v©Î¡u4¡v¡C¦¹®É­nÀˬd¬Û¾FªºÀRºA±±¥ó¼ÐÃD¬O§_¦³¬Û¦Pªº¡A¦pªG¨S¦³¬Û¦Pªº¡A¥NªíµLªk¬Û¥[¦Ó¨Ï¨ä¤¤¤@­ÓÀRºA±±¥óªº¼ÐÃDÅܬ°¡u0¡v¡A¹CÀ¸¦]¦¹µ²§ô¡C¸Ô²ÓÀˬd¬Û¾FªºÀRºA±±¥ó¼ÐÃD¬O§_¦³¬Û¦Pªº¹Lµ{¬O¦b check_gameover °Æµ{¦¡ùسB²z¡C

³B²z WM_KEYDOWN °T®§

­ì¥»¹ï¸Ü²°¨ç¦¡¦¡¤£³B²z«öÁä°T®§ªº ( ¥]§t WM_KEYDOWN¡BWM_KEYUP¡K)¡A¦ý¬O¸g¥Ñ¤lÃþ¤Æ«á¡A´ÛÄF«ö¶sªºµøµ¡¨ç¦¡¡A§â WM_KEYDOWN ¶Çµ¹¹ï¸Ü²°¨ç¦¡¡A¨Ï¹ï¸Ü²°¤]¯à±µ¦¬¨ì WM_KEYDOWN °T®§¡C¤@¶}©l³B²z WM_KEYDOWN °T®§¬O¥ý§â·í«e 16 ­ÓÀRºA±±¥óªº¼ÐÃDÅܦ¨¼Æ­È¡A¦s¤J number °}¦C¤¤¡A³o¥ó¨Æ¥Ñ save_number °Æµ{¦¡§¹¦¨¡C±µµÛ¬O©I¥s arrange_matrix °Æµ{¦¡¡A³o­Ó°Æµ{¦¡³B²z¤W¡B¤U¡B¥ª¡B¥kÁä¡A©³¤U¤p¤ì°¸»¡©ú arrange_matrix °Æµ{¦¡¡C

arrange_matrix »P arrange_a_row

arrange_matrix »Ý­n¤@­Ó°Ñ¼Æ¡A³o­Ó°Ñ¼Æ¨M©w¼Æ¦r©¹­þ­Ó¤è¦V²¾°Ê¡Aµ{¦¡²Ä 576¡ã584 ¦æ¨Ì¾Ú WM_KEYDOWN °T®§ªº wParam ¨M©w ECX ­È¡AµM«á¦b²Ä 585 ¦æ¥H ECX ¬°°Ñ¼Æ©I¥s arrange_matrix °Æµ{¦¡¡C¨Ò¦p¡A¦pªG¨Ï¥ÎªÌ«ö¤U¦V¡u¡õ¡vÁä¡A¨º»ò wParam °Ñ¼Æ¬° VK_DOWN¡A«h ECX ³Q³]¬°¡uTOPTODOWN¡v( ªí¥Ü¼Æ¦r¥Ñ¤W©¹¤U²¾°Ê¡A¨ä­È¬° 0 )¡AµM«á¤~©I¥s arrange_matrix °Æµ{¦¡¡C

¨C«ö¤@¦¸¤è¦VÁä¡Aµ{¦¡´N±o³B²z¥|¦æ¼Æ¦r¡A¦Ó³B²z³o¥|¦æ¼Æ¦rªº¤èªk³£¬O¬Û¦Pªº¡C¦]¦¹¡A¥u­n¼g¦n³B²z¤@¦æªº°Æµ{¦¡¡A¨ä¥L¤T¦æ´N¥i¥H¤ñ·Ó¿ì²z¡A¥u­n©I¥s³o­Ó°Æµ{¦¡¥|¦¸´N¥i¥H¤F¡C«Ü©¯¹Bªº¡A³o­Ó°Æµ{¦¡¤£Ãø¼g¡AºÙ¬° arrange_a_row¡C³B²z¨C¤@¦æ¼Æ¦rªº¤èªk¬O¥ý§â¼Æ¦r¦V¸Ó¤è¦V²¾°Ê¡A¦AÀˬd¬Û¾Fªº¼Æ¦r¬O§_¬Û¦P¡A¦pªG¬Û¦P´N¬Û¥[¨Ã¨Ï¨ä©M¦s¨ì¸Ó¤è¦Vªº«e¤@­ÓÀRºA±±¥ó¤W¡A¦Ó¥B¨Ï«á¤@­ÓÀRºA±±¥óÅܬ°¡u0¡v( ©Ò¥H¦³®É¤p¤ì°¸ºÙ¬Û¥[¬°ÁY´î )¡C¥t¥~¡A¦pªG±z«Ü¥J²ÓÆ[¹î 2048 ¤¤¡A·|µo²{¤£ºÞ¼Æ¦r¦V­þ¤@­Ó¤è¦V²¾°Ê¡A¥u­n´x´¤¤T­ÓÅܼơA´N¥i¥H¥u¥Î¤@­Ó°Æµ{¦¡³B²z¥|­Ó¤è¦Vªº¼Æ¦r²¾°Ê»PÁY´î¡C³o¤T­ÓÅܼƬO²Ä¤@¦æªº¼Æ¦r©¹­þ­ÓÀRºA±±¥ó²¾°Ê¡B¨C¤@¦æ²Ä¤@­ÓÀRºA±±¥óÃѧO½X»P¤U¤@¦æ²Ä¤@­ÓÀRºA±±¥óÃѧO½X¤§®t¡B¸Ó¦æ¤U¤@­ÓÀRºA±±¥óÃѧO½X»P¤W¤@­ÓÃѧO½X¤§®t¡A¤À§O¥H StartID¡BidBetweenRow¡Bdifference Åܼƪí¥Ü¡C

½Ð°Ñ¦Ò¥k¹Ï¡CÁ|¨â­Ó¨Ò¤l»¡©ú StartID ©M idBetweenRow ¨â­ÓÅܼơG

  1. ¦pªG«ö¤U¦V¡u¡õ¡vÁä¡A¨º»ò¨C¤@¦æªº¼Æ¦r³£¦V¤U²¾¡A°£«D©³¤U¦³¼Æ¦r¡A¦]¦¹³Ì¥ª¤@¦æ©¹ IDS_0C ²¾°Ê¡B¥ªÃä²Ä¤G¦æ©¹ IDS_0D ²¾°Ê¡K¡C³Ì¥ª¤@¦æ»P¥ªÃä²Ä¤G¦æ¤§¶¡ªºÃѧO½X¬Û®t 1¡C¦]¦¹ StartID ¬° IDS_0C¡AidBetweenRow ¬° 1¡C³o¼Ë¨C³B²z§¹¤@¦æ¡AStartID ¥u­n¥[¤W idBetweenRow ´N¥i¥H³B²z¤U¤@¦æ¡C
  2. ¦pªG«ö¤U¦V¡u¡÷¡vÁä¡A«h³Ì¤W¤@¦æ©¹ IDS_03 ²¾°Ê¡B¤W­±²Ä¤G¦æ©¹ IDS_07 ²¾°Ê¡K¡A³Ì¤W¤@¦æ»P¤W­±²Ä¤G¦æ¤§¶¡ªºÃѧO½X¬Û®t 4¡C©Ò¥H StartID ¬° IDS_03¡AidBetweenRow ¬° 4¡C

Ãö©ó deifference ¬O¨C¤@¦æ«e«áÀRºA±±¥óÃѧO½X¤§®t¡A¦ý¬O¬°¤F­n°t¦X arrange_a_row °Æµ{¦¡²¾°Ê¼Æ¦r»PÁY´î¤è¦¡¡A¦]¦¹¦³¨Ç¬O¥¿­È¡Aªí¥Ü¼W¥[¡A¦³¨Ç¬O­t­È¡Aªí¥Ü´î¤Ö¡Carrange_a_row °Æµ{¦¡²¾°Ê¼Æ¦r©ÎÁY´î¦p¤U¡G³]¤@­Ó§t¦³ 4 ­Ó¦¨­ûªº°}¦C¡AdwN¡A¦pªG¸û§C¦ì§}ªº¼Æ­È¬°¡u0¡v¡A«h¸û°ª¦ì§}ªº¼Æ­È¦V§C¦ì§}²¾°Ê¡C²¾°Ê§¹¦¨¤§«á¡AÀˬd°}¦C¤¤¬Û¾Fªº¦¨­û¬O§_¦³¬Û¦Pªº¡A¦pªG¦³¬Û¦Pªº«h¬Û¥[¡A§â©Ò±o¤§©M¦s¤J§C¦ì§}¡A°ª¦ì§}Åܬ°¡u0¡v¡C¦]¦¹¡A¦pªG«ö¤U¦V¡u¡õ¡vÁä¡A¨º»ò¡AIDS_0C ªº¼Æ¦r¤£°Ê¡A°£«D¬°¡u0¡v¤~·|¨Ï IDS_08 ªº¼Æ¦r²¾¨ì IDS_0C¡A¦]¦¹ StartID ¨ä¹ê¤]¥Nªí¤F°ò·ÇÂI¡A¦Ó difference «hªí¥Ü»P°ò·ÇÂIªº®t­È¡C

µ{¦¡²Ä 201¡ã221 ¦æ¡A¨Ì¾Ú direct ³]©w StartID¡BidBetweenRow¡Bdifference ¤T­ÓÅܼơAdirect ¬Oª±®a©Ò«öªº¤è¦V«öÁä¡C²Ä 224¡ã259 ¦æªº°j°é¡A³B²z 16 ­ÓÀRºA±±¥óªº²¾°Ê©ÎÁY´î¡A¥i¤À¬°¥|³¡¤À»¡©ú¡G

  1. ²Ä¤@³¡¤À¬O±q 225¡ã237 ¦æªºµ{¦¡½X¡A¬O§â¬Y¤@¦æªºÀRºA±±¥ó¼ÐÃDÅܦ¨¼Æ­È¡A¦s¤J dwN °}¦CùØ¡A¥H¨Ñµ¹²Ä 239¡ã242 ¦æ arrange_a_row ¨Ï¥Î¡C±zÀ³·í¥i¥H¬Ý¨£µ{¦¡Åª¨úÃѧO½X¬° ID ªºÀRºA±±¥ó¼ÐÃD¡A¥B dwN ªº³Ì§C¦ì§}¦s©ñªº¬OÃѧO½X¬° StartID ªºÀRºA±±¥ó¼ÐÃD©ÒÅܦ¨ªº¼Æ­È¡A±µµÛ²Ä¤G§C¦ì§}ªº¦¨­û¦s©ñªº¬OÃѧO½X¬° ( StartID¡Ïdifference ) ªºÀRºA±±¥ó¼ÐÃD©ÒÅܦ¨ªº¼Æ­È¡A¨Ì¦¹Ãþ±À¡C
  2. ²Ä¤G³¡¤À¬O©I¥s arrange_a_row¡Aªð¦^«á dwN °}¦C·|Åܦ¨¸g¹L²¾°Ê¼Æ¦r©ÎÁY´îªºµ²ªG¡A¦¹¥~¡A¦p¦³ÁY´î©Î¬Û¥[¡A«h²M°£¶i¦ìºX¼Ð¡F¦p¨S¦³ÁY´î¤]¨S¬Û¥[¡A«h³]©w¶i¦ìºX¼Ð¡C
  3. ²Ä¤T³¡¤À¬O±q 243¡ã255 ¦æ¡A§â dwN °}¦CÅܦ¨¦r¦ê¡A§âÀRºA±±¥ó¼ÐÃD³]¬°¬Û¹ïÀ³ªº¦r¦ê¡C
  4. µ¥¤@¦æ 4 ­ÓÀRºA±±¥ó³B²z§¹«á¡A±z¥i¥H¦b 257¡ã258 ¦æ¬Ý¨£¨C³B²z§¹¤@¦æ 4 ­ÓÀRºA±±¥ó«á¡AStartID ·|­«·s³]¹L¡AÅܦ¨­ì¨Óªº StartID ¦A¥[¤W idBetweenRow¡A©ó¬O¤S­«·s¶}©l·sªº¤@¦æ¡C

WM_GETDLGCODE °T®§

·í¹ï¸Ü²°¦b¿Ã¹õªº³Ì¤W¼h®É ( ¥ç§Y¥¿¦b¨Ï¥Î¤¤¡A¼ÐÃDÄ欰©ú«G¦â¡A«D·t¦â )¡A¦pªG¨Ï¥ÎªÌ«ö¤U¤è¦VÁä®É¡A§@·~¨t²Î¹w©wªº³B²z¤è¦¡¨Ã¤£¬O§â¤è¦VÁä°T®§¶Ç°eµ¹¨ã¦³¿é¤JµJÂIªº±±¥ó¡A¦Ó¬O§â¥¦­Ì¥Î¨Ó¦b¦U­Ó±±¥ó¤§¶¡¤Á´«¿é¤JµJÂI¡C°²³]¤£·Q¥H§@·~¨t²Î¹w©w¤è¦¡³B²z¤è¦VÁä¡A¦Ó­nÅý¤è¦VÁä¶Çµ¹±±¥ó¡A¨º»ò´N±o¥ý³B²z WM_GETDLGCODE °T®§¡C·í§@·~¨t²Î§â WM_GETDLGCODE ¶Çµ¹±±¥óªºµøµ¡¨ç¦¡®É¡AwParam ¬O¨Ï¥ÎªÌ«ö¤U«öÁ䪺µêÀÀÁä½X ( virtual key code )¡AlParam «h¬O¦ì§}«ü¼Ð¡A«ü¦V MSG µ²ºcÅé¡C³B²z§¹ WM_GETDLGCODE °T®§«á¡AÀ³¸Óµ¹§@·~¨t²Îªð¦^­È¡A¦p¤Uªí¡G

ªð¦^­È»¡©ú
DLGC_BUTTON§â«ö¶sªº°T®§¶Çµ¹¹ï¸Ü²°¨ç¦¡
DLGC_DEFPUSHBUTTON§â¤º©w¤UÀ£¦¡«ö¶sªº°T®§¶Çµ¹¹ï¸Ü²°¨ç¦¡
DLGC_HASSETSEL§â EM_SETSEL °T®§¶Çµ¹¹ï¸Ü²°¨ç¦¡
DLGC_RADIOBUTTON§â¶ê§Î«ö¶sªº°T®§¶Çµ¹¹ï¸Ü²°¨ç¦¡
DLGC_STATIC§âÀRºA±±¥óªº°T®§¶Çµ¹¹ï¸Ü²°¨ç¦¡
DLGC_UNDEFPUSHBUTTON
DLGC_WANTALLKEYS§â©Ò¦³«öÁä°T®§¶Çµ¹¹ï¸Ü²°¨ç¦¡
DLGC_WANTARROWS¶È§â¤è¦VÁä°T®§¶Çµ¹¹ï¸Ü²°¨ç¦¡
DLGC_WANTCHARS§â WM_CHAR ¶Çµ¹¹ï¸Ü²°¨ç¦¡
DLGC_WANTMESSAGE§â©Ò¦³«öÁä°T®§¶Çµ¹±±¥óªºµøµ¡¨ç¦¡
DLGC_WANTTAB§â Tab «öÁä°T®§¶Çµ¹¹ï¸Ü²°¨ç¦¡

¦b¤lÃþ¤Æªº«ö¶sµøµ¡¨ç¦¡ùØ¡Anew_button_proc¡A±z¥i¥H¨£¨ì³B²z WM_GETDLGCODE °T®§ªº¹Lµ{¡A¶È¶È¶Ç¦^ DLGC_WANTALLKEYS¡A´N¯à¨Ï©Ò¦³«öÁä°T®§¶Çµ¹¹ï¸Ü²°µøµ¡¨ç¦¡¤F¡C( µ{¦¡²Ä 394¡ã396 ¦æ )


¨ì²Ä¤G¤Q¤­³¹¡A ¦^¨ì­º­¶¡A¨ì²Ä¤G¤Q¤C³¹