当前位置: 代码迷 >> 综合 >> 8086 贪吃蛇
  详细解决方案

8086 贪吃蛇

热度:71   发布时间:2024-01-29 17:46:45.0

8086 贪吃蛇

运行环境:MsDos 7.1 或 DOSBox

键盘方向键控制

演示

snake0
snake1

汇编代码

assume cs:code, ds:data, ss:stack; gpu prop byte
; 7    6  5  4  3  2  1  0
; BL   R  G  B  I  R  G  B
;  |   \_____/  |  \_____/
; 闪烁   背景  高亮  前景; game map: 25 x 25
; snake bodys max: 23 x 23data segmentscore dw 0             ; game scorescpre db 'score:'      ; [6] score prefixdead db 'game over!'   ; [10] game overfood dw 0              ; snake food: x|ysdct db 0              ; snake direction 0001-up 0010-down 0100-left 1000-rightslen db 0              ; snake lengthbody dw 529 dup(0)     ; snake bodys: x|y, ...
data endsstack segmentdw 20 dup(0)
stack endscode segment
start:mov ax, datamov ds, ax                ; init data segmov ax, 0b800h            mov es, ax                ; save gpu base addrmov ax, stackmov ss, axmov sp, 20                ; init stackcall clearmov ah, 24mov al, 24push axcall draw_mapcall create_snakecall draw_snakecall create_foodcall draw_foodcall start_gamecall show_scoreend_game:call game_overmov ax, 4c00hint 21h; # start game
; void -> void
start_game:mov cx, 50 
sg0:call listen_key  call clear_lastcall move_snakecall is_deadcall draw_snakecall is_eatcall show_scorecall sleeploop sg0ret; # show game over alert
; void -> void
game_over:push axpush cxpush simov si, 28mov cx, 10  ; string length
go0:mov ax, simov ah, almov al, 12push axmov ah, 00000111bmov al, dead[si - 28]push axcall draw_charinc siloop go0pop sipop cxpop axret; # is the snake dead
; void -> void
is_dead:push axpush cxpush simov ax, body[0]  ; get headcmp ah, 0        ; touch the edgeje end_gamecmp ah, 24je end_gamecmp al, 0je end_gamecmp al, 24je end_gamemov ch, 0mov cl, slendec cxmov si, 2        ; start with secondid0:               ; touch self bodymov ax, body[si]cmp body[0], axje end_gameadd si, 2loop id0pop sipop cxpop axret; # add snake body
; void -> void
add_body:push axpush simov ah, 0mov al, sleninc almov slen, al    ; add bodymov si, axadd si, simov ax, body[si - 4]mov body[si - 2], axinc scorecall create_foodcall draw_foodpop sipop axret; # is snake eat food
; void -> void
is_eat:push axmov ax, foodcmp ax, body[0]jne nt0call add_body
nt0:pop axret; show game score
; void -> void
show_score:push axpush bxpush simov si, 28mov cx, 6  ; string length
po0:         ; draw score prefixmov ax, simov ah, almov al, 2push axmov ah, 00000111bmov al, scpre[si - 28]push axcall draw_charinc siloop po0mov si, 0mov ax, score
sl0:mov bh, 0mov bl, 10div blmov bx, axmov bl, bhmov bh, 0push bx        ; save digitinc si         ; count digitscmp al, 0      ; no more digitje se0mov ah, 0      ; next digitjmp short sl0
se0:mov cx, simov si, 34     ; show start x
sn0:pop bx         ; get each digitadd bx, 30H    ; get digit asciimov ax, simov ah, almov al, 2push axmov ah, 00000111bmov al, blpush axcall draw_char ; draw each digitinc siloop sn0pop sipop bxpop axret; # listen to keys
; void -> void
listen_key:push axmov ah, 1mov al, 0int 16h          ; keboard interruptcmp ah, 1je lk0mov ax, 0int 16hcmp ax, 4800h    ; press upje kupcmp ax, 5000h    ; press downje kdowncmp ax, 4b00h    ; press leftje kleftcmp ax, 4d00h    ; press rightje krightjmp short lk0kup:cmp sdct, 0010b  ; direction conflictje lk0mov sdct, 0001b  ; set directionjmp short lk0kdown:cmp sdct, 0001bje lk0mov sdct, 0010bjmp short lk0kleft:cmp sdct, 1000bje lk0mov sdct, 0100bjmp short lk0kright:cmp sdct, 0100bje lk0mov sdct, 1000blk0:pop axret; # clear last snake body
; void -> void
clear_last:push axpush simov ah, 0mov al, slenmov si, axadd si, simov ax, body[si - 2] ; last bodypush axmov ah, 00000000bmov al, ' 'push axcall draw_char       ; clearpop sipop axret; # update snake bodys
; void -> void
move_snake:push axpush cxpush simov ch, 0mov cl, slendec cxmov ah, 0mov al, slenmov si, axadd si, si
ms0:  mov ax, body[si - 4]mov body[si - 2], axsub si, 2loop ms0mov ax, body[0]     ; upd headcmp sdct, 0001b     ; upje upcmp sdct, 0010b     ; downje downcmp sdct, 0100b     ; leftje leftcmp sdct, 1000b     ; rightje rightup:dec aljmp short uokdown:inc aljmp short uokleft:dec ahjmp short uokright:inc ahjmp short uokuok:mov body[0], axpop sipop cxpop axret; # draw snake to map
; void -> void
draw_snake:push cxpush sipush axmov ch, 0mov cl, slenmov si, 0
ds0:mov ax, body[si]push axmov ah, 01110000bmov al, ' 'push axcall draw_char       ; draw bodyadd si, 2loop ds0pop axpop sipop cxret; # create snake
; fixed: snake size is 3
; void -> void
create_snake:push cxpush sipush axmov sdct, 1000b ; set direct is rightmov ah, 1mov al, 1mov slen, 2     ; set snake lengthmov ch, 0mov cl, slenmov si, 0mov ah, 6       ; set snake head xmov al, 4       ; set snake head y
c0:mov body[si], axdec ahadd si, 2loop c0pop axpop sipop cxret; draw food to map
; void -> void
draw_food:push ax  mov ax, foodpush axmov ah, 00101000bmov al, ' 'push axcall draw_char   ; draw foodpop axret; # create a food
; fixed: map width and height
; void -> void
create_food:push axpush bxpush cxpush dxpush sire0:mov bx, 23push bxcall rand        ; get xinc dx           ; range: 1-[23]mov ah, dlpush bxcall rand        ; get yinc dxmov al, dlmov ch, 0mov cl, slenmov si, 0
sb0:               ; for snake bodycmp ax, body[si]je re0           ; conflict with body, create againadd si, 2loop sb0mov food, ax     ; save food xypop sipop dxpop cxpop bxpop axret; # rand number
; 0: range -> dx: 0~(range)
rand:push bpmov bp, sppush axmov ax, 0hout 43h, alin al, 40hin al, 40hin al, 40hmov bx, [bp + 4]div blmov dh, 0mov dl, ahpop axpop bpret 2; # sleep tiem
; void -> void
sleep:push cxmov cx, 50000s0:push cxmov cx, 20s1:loop s1pop cxloop s0pop cxret; # draw game map
; 0: width|height -> void
draw_map:push bpmov bp, sp; draw toppush cxpush axpush bxpush dxmov dx, [bp + 4]  ; get widthmov ax, 0mov ch, 0mov cl, dh        ; set widthinc cld0:mov bh, al        ; draw topmov bl, 0push bxmov bh, 00010000bmov bl, ' 'push bxcall draw_charmov bh, al        ; draw bottommov bl, dlpush bxmov bh, 00010000bmov bl, ' 'push bxcall draw_charinc alloop d0mov cl, dl        ; set heightdec cl            ; inside content heightmov al, 1d1:mov bh, 0         ; draw leftmov bl, alpush bxmov bh, 00010000bmov bl, ' 'push bxcall draw_charmov bh, dh        ; draw bottommov bl, alpush bxmov bh, 00010000bmov bl, ' 'push bxcall draw_charinc alloop d1pop dxpop bxpop axpop cxpop bpret 2; # draw char to screen
; 0: x|y, 1: prop|char -> void
draw_char:push bpmov bp, sppush axpush bxpush simov bx, [bp + 6]mov ah, 0mov al, 0a0hmul bl            ; set ymov bl, bhmov bh, 0add bl, bladd bl, bladd ax, bx        ; set xmov si, axmov ax, [bp + 4]mov es:[si], ax   ; set prop and charcmp al, ' 'jne jm0mov es:[si + 2], ax  ; for edge, double draw.jm0:                ; for normal charpop sipop bxpop axpop bpret 4; # clear screen
; void -> void
clear:mov ax, 3hint 10hretcode ends
end start