汇编 8086 检查井字游戏中获胜者的程序仅检查第一行
我正在制作一个终极井字游戏,我几乎制作了整个游戏,我映射到数组,我检查单板获胜者并将它们映射到 3 x 3 数组,所有这些都有效,但由于某种原因,过程检查 3 x 3 板时仅检查第一行。我已经为单个井字棋游戏制作了一个测试文件,它在那里工作,所以也许我的代码中隐藏了另一个程序或其他东西的问题
CHECK_WINNER PROC
XOR BX, BX
XOR CX, CX
XOR DX, DX
XOR DI, DI
LEA DI, BIG_BOARD
VERIFICA_VENCEDOR_LINHA1:
CMP CX, 3
JE VERIFICA_VENCEDOR_COLUNA1
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE PROXIMA_LINHA1
INC DI
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE PROXIMA_LINHA1
INC DI
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE PROXIMA_LINHA1
INC DI
JMP GANHOU_BOARD1
PROXIMA_LINHA1:
MOV DI, DX
ADD BX, 3
ADD DI, BX
INC CX
JMP VERIFICA_VENCEDOR_LINHA1
VERIFICA_VENCEDOR_COLUNA1:
XOR BX, BX
XOR CX, CX
MOV DI, DX
COLUNA_LOOP1:
CMP CX, 3
JE VERIFICA_VENCEDOR_DIAGONAL1
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE PROXIMA_COLUNA1
ADD DI, 3
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE PROXIMA_COLUNA1
ADD DI, 3
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE PROXIMA_COLUNA1
ADD DI, 3
JMP GANHOU_BOARD1
PROXIMA_COLUNA1:
MOV DI, DX
INC BX
ADD DI, BX
INC CX
JMP COLUNA_LOOP1
VERIFICA_VENCEDOR_DIAGONAL1:
XOR BX, BX
XOR CX, CX
MOV CX, 3
MOV DI, DX
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE DIAG21
ADD DI, 4
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE NAO_GANHOU1
ADD DI, 4
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE DIAG21
JMP GANHOU_BOARD1
DIAG21:
MOV DI, DX
ADD DI, 2
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE NAO_GANHOU1
ADD DI, 2
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE NAO_GANHOU1
ADD DI, 2
MOV AL, [DI]
CMP AL, JOGADOR_CURR
JNE NAO_GANHOU1
JMP GANHOU_BOARD1
NAO_GANHOU1:
RET
GANHOU_BOARD1:
CALL EXIT
CHECK_WINNER ENDP
我决定纠正我最后一个很糟糕的答案。 :/ 我也不知道这个是否会更好。好吧,我发现了这个错误...
程序不起作用,因为寄存器
di
中的值计算方式错误。
第一个
di
包含 offset big_board
,并且在每个 row/column
之后该值都会更改。所以di
指向错误的内存区域。
我写了其余的代码。程序使用更正的 OP 程序。
如果您发现更多错误,请告诉我。 ;)
.286
.model small
.stack 0ffh
.data
big_board db 0,0,0
db 0,0,0
db 0,0,0
board db 13,10,13,10 ; new line
db 218,196,196,196,194,196,196,196,194,196,196,196,191,13,10
db 179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179,13,10 ;;
db 195,196,196,196,197,196,196,196,197,196,196,196,180,13,10
db 179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179,13,10 ;;
db 195,196,196,196,197,196,196,196,197,196,196,196,180,13,10
db 179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179,13,10 ;;
db 192,196,196,196,193,196,196,196,193,196,196,196,217,'$'
turnnumber db 49
firsttime db 0 ;draw everything, skip user keys
keynumber db ? ;what key user pressed
xpos db 6 ;cursor x position on screen
ypos db 5 ;cursor y position on screen
xboard db 1 ;cursor board x position
yboard db 1 ;cursor board y position
x_o db 88 ;79=o 88=x
spacepressed db 0
playercolor db 0ah ;0ah=green 0dh=purple
winner db 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
howto db "Move: use arrows Accept: space bar$"
turn db "Turn: ",'$'
move db 32,32,32,32,"Move: ",'$'
game_winner db "Winner! "
player db "Player "
jogador_curr db 49 ;player number
newline db 13,10,13,10,'$'
byebye db "--- See you next time ---- ",'$'
win_x db "The game ended in a draw.",'$'
;--- macros
setcharattr macro attr;x,y,attr
pusha
mov ah,9 ; service number
mov al,0 ; character code
mov cx,1 ; number of chars to write
mov bh,0 ; active page
mov bl,attr ; character attribute
int 10h
popa
endm
setcursor macro x,y
pusha
mov ah,02h ; service number
mov dl,x ; column
mov dh,y ; row
mov bh, 00h ; active page
int 10h
popa
endm
curshow macro
pusha
mov ah,01h ; service number
mov ch,11 ; start
mov cl,12 ; end
int 10h
popa
endm
curhide macro
pusha
mov ah,01h ; service number
mov ch,20h ; stack, 20h hides the cursor
int 10h
popa
endm
;;------------------------------------------------------------
.code
start:
mov ax,@data
mov ds,ax
mov es,ax
mov ax,0003h ; text mode
int 10h
;mov [firsttime], 1 ;=1 we already draw everythig, now check user input
mov ah,9 ; print "board"
mov dx,offset board
int 21h
setcursor [xpos],[ypos] ; board coords
setcharattr [playercolor] ; current color
mov ah,2 ; show x or o
mov dl,[x_o]
int 21h
setcursor [xpos],[ypos]
call info
mainloop:
setcursor 0,0
;--------------------------------
mov ah,9 ; print "turn"
mov dx,offset turn
int 21h
setcharattr 14 ; yellow
mov ah,2 ; print turnnumber
mov dl,[turnnumber]
int 21h
mov ah,9 ; print "move: "
mov dx,offset move
int 21h
mov bx, offset player ; print "player "
mov cx,8 ; number of characters in "player x"
mov dx,18 ;?
setcursor 17,0
playertext:
push bx ; save player offset
push cx ; save counter
mov ah,9
mov al,[bx] ; char in "player "
xor bx,bx
mov bl,[playercolor]
mov cx,1
int 10h
pop cx ; restore counter
pop bx ; restore player offset
inc bx ; next char
mov ah,2
int 10h
add dl,1 ; next position, increase column number
loop playertext
;-------------- draw board
; setcursor 15,6
; mov ah,2
; mov dl,[xpos]
; add dl,30h
; int 21h
; mov ah,2
; mov dl,20h
; int 21h
; mov ah,2
; mov dl,[ypos]
; add dl,30h
; int 21h
setcursor [xpos],[ypos] ; board coords
call checkkey
cmp al,27 ;esc, exit program
jz endgame
;;--------------------------------------------------------
call boardaction
;;--------------------------------------------------------
mov al,[x_o]
xor dx,dx
mov dl,[jogador_curr]
push dx
mov [jogador_curr],al
call check_winner
pop dx
mov [jogador_curr],dl
mov al,[winner] ; we have the winner
cmp al,1
jz player_wins
;--- switch player
mov al,[spacepressed] ; player pressed spacebar ?
cmp al,1
jnz DontSwitchPlayer
call SwitchPlayer
DontSwitchPlayer:
;--- check if game is finished
mov al,[turnnumber] ; draw or continue game
cmp al,58
jae textmode
jmp mainloop
textmode:
mov ax,0003h ; back to text move
int 10h
nowinner:
setcursor 0,1
mov ah,9
mov dx,offset win_x
int 21h
jmp endgame
player_wins:
mov ax,0003h ; back to text move
int 10h
setcursor 0,1
mov ah,9
mov dx,offset game_winner
int 21h
;mov ah,2
;mov dl,[jogador_curr]
;int 21h
endgame:
setcursor 0,2
mov ah,9
mov dx,offset byebye
int 21h
exit:
mov ax, 4c00h ; end app
int 21h
;--- procedures ----------
info proc
setcursor 0,23
mov cx,80
show_line:
mov ah,2
mov dl,'_'
int 21h
dec cx
jnz show_line
setcursor 1,24
mov ah,9
mov dx,offset howto
int 21h
setcursor 0,0
ret
info endp
checkkey proc
mov ah,0 ; read key
int 16h
cmp al,0
jz extended
jmp normal
extended:
mov [keynumber], ah ; save
mov al,ah
jmp nextturn
normal:
mov [keynumber], al ; save
nextturn:
ret
checkkey endp
SwitchPlayer proc
;switch_player:
cmp [jogador_curr],49 ;1=x 2=o
jz switchtoplayer2
sub [jogador_curr],1
mov [playercolor],0ah
mov [x_o], 88
jmp turn_inc
switchtoplayer2:
add [jogador_curr],1
mov [playercolor],0dh
mov [x_o], 79
turn_inc:
;mov [spacepressed],0 ;;???
inc [turnnumber]
ret
SwitchPlayer endp
;--- boardaction ----------
; checks board boundries
; calculates if position on big_board is free/taken
; and draws graphics accordingly
boardaction proc
cmp al,77 ;right arrow
jz moveright
cmp al,75 ;left arrow
jz moveleft
cmp al,72 ;up arrow
jz moveup
cmp al,80 ;down arrow
jz movedown
cmp al,32 ;space, place x,o on board
jz space
jmp boardactiondone
bb_field:
mov si,offset big_board ; current position
mov bh,[xboard]
mov bl,[yboard]
;3*[yboard]+[xboard]
xor ax,ax ; calculate new position
mov al,3
mul bl
add al,bh
add si,ax
mov al,[si] ; and see what is there
cmp al,0 ; empty field?
ret
moveright:
mov al,[xpos] ; current x position on board, screen coords
cmp al,10 ; right bound detection, is cursor in last column?
jz boardactiondone ; yes
call bb_field ; no, it is not
jnz move_right ; there is x/o in this field, just calculate new coords
setcharattr 0 ; clear current field
move_right: ; new x coords
add [xpos],4
add [xboard],1
jmp boardactiondone
moveleft:
mov al,[xpos] ; current x position on board, screen coords
cmp al,2 ; left bound detection, is cursor in first column?
jz boardactiondone ; yes
call bb_field ; no it is not
jnz move_left ; there is x/o in this field, just calculate new coords
setcharattr 0 ; clear current field
move_left: ; new x coords
sub [xpos],4
sub [xboard],1
jmp boardactiondone
moveup:
mov al,[ypos] ; current y position on board, screen coords
cmp al,3 ; top bound detection, is cursor in first row?
jz boardactiondone ; yes
call bb_field ; no it is not
jnz move_up ; there is x/o in this field, just calculate new coords
setcharattr 0 ; clear current field
move_up: ; new y coords
sub [ypos],2
sub [yboard],1
jmp boardactiondone
movedown:
mov al,[ypos] ; current y position on board, screen coords
cmp al,7 ; bottom bound detection, is cursor in last row?
jz boardactiondone ; yes
call bb_field ; no it is not
jnz move_down ; there is x/o in this field, just calculate new coords
setcharattr 0 ; clear current field
move_down: ; new y coords
add [ypos],2
add [yboard],1
jmp boardactiondone
space:
call bb_field ; is field empty or taken?
jnz boardactiondone ; something is there
mov [spacepressed],1
mov al,[x_o] ; insert x/o
mov [si],al ; in big_board
setcursor [xpos],[ypos]
setcharattr [playercolor]
mov ah,2 ; and show on the screen
mov dl,al
int 21h
setcursor [xpos],[ypos]
jmp space1
; switch_player:
; cmp [jogador_curr],49 ;1=x 2=o
; jz switchtoplayer2
;
; sub [jogador_curr],1
; mov [playercolor],0ah
; mov [x_o], 88
;
; jmp turn_inc
;
; switchtoplayer2:
; add [jogador_curr],1
; mov [playercolor],0dh
; mov [x_o], 79
;
; turn_inc:
; ;mov [spacepressed],0 ;;???
; inc [turnnumber]
boardactiondone:
mov [spacepressed],0
space1:
;--- show char at new coords
mov si,offset big_board
mov bh,[xboard]
mov bl,[yboard]
;3*[yboard]+[xboard]
xor ax,ax
mov al,3
mul bl
add al,bh
add si,ax
xor ax,ax
cmp [si],al
jnz fieldtaken
setcursor [xpos],[ypos]
setcharattr [playercolor]
mov ah,2
mov dl,[x_o]
int 21h
fieldtaken:
setcursor [xpos],[ypos]
endd:
ret
boardaction endp
;--- clear screen ----------
clrscr proc
mov ax,0600h
mov cx,0h
mov bx,0007h
mov dx,184fh
int 10h
ret
clrscr endp
;--- check winner ----------
; op's procedure to see who won
check_winner proc
xor bx, bx
xor cx, cx
xor dx, dx
xor di, di
lea di, big_board
verifica_vencedor_linha1: ; check_winner_line1
cmp cx, 3
je verifica_vencedor_coluna1 ; check_winner_column1
push di
mov al, [di]
cmp al, jogador_curr ; player_curr
jne proxima_linha1 ; next_line1
inc di
mov al, [di]
cmp al, jogador_curr ; player_curr
jne proxima_linha1 ; next_line1
inc di
mov al, [di]
cmp al, jogador_curr ; player_curr
jne proxima_linha1 ; next_line1
inc di
jmp ganhou_board1 ; won_board1
proxima_linha1: ; next_line1
pop di
add di, 3 ; move to next line
inc cx
jmp verifica_vencedor_linha1 ; check_winner_line1
verifica_vencedor_coluna1: ; check_winner_column1
xor bx, bx
xor cx, cx
sub di, 9 ; reset big_board offset
coluna_loop1: ; column_loop1
cmp cx, 3
je verifica_vencedor_diagonal1 ; check_winner_diagonal1
push di
mov al, [di]
cmp al, jogador_curr ; player_curr
jne proxima_coluna1 ; next_column1
add di, 3
mov al, [di]
cmp al, jogador_curr ; player_curr
jne proxima_coluna1 ; next_column1
add di, 3
mov al, [di]
cmp al, jogador_curr ; player_curr
jne proxima_coluna1 ; next_column1
add di, 3
jmp ganhou_board1 ; won_board1
proxima_coluna1: ; next_column1
pop di
inc di ; move to next column
inc cx
jmp coluna_loop1 ; column_loop1
verifica_vencedor_diagonal1: ; check_winner_diagonal1
mov cx, 3
sub di, 3 ; reset big_board offset
mov al, [di]
cmp al, jogador_curr ; player_curr
jne diag21
add di, 4
mov al, [di]
cmp al, jogador_curr ; player_curr
jne nao_ganhou1
add di, 4
mov al, [di]
cmp al, jogador_curr ; player_curr
jne diag21_sub_di_8 ; reset big_board offset
jmp ganhou_board2
diag21_sub_di_8:
sub di, 8 ; row 1 column 3
diag21:
add di, 2
mov al, [di]
cmp al, jogador_curr ; player_curr
jne nao_ganhou1 ; didn't win1
add di, 2
mov al, [di]
cmp al, jogador_curr ; player_curr
jne nao_ganhou1 ; didn't win1
add di, 2
mov al, [di]
cmp al, jogador_curr ; player_curr
jne nao_ganhou1 ; didn't win1
jmp ganhou_board2 ; won_board1
nao_ganhou1: ; didn't win1
ret
ganhou_board1: ; won_board1
pop di
ganhou_board2:
mov [winner],1
ret ;call exit
check_winner endp
end start