You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Assembly 8086井字棋获胜检测子程序仅检测第一行问题求助

终极井字棋3×3棋盘获胜检测问题排查

我正在开发终极井字棋(ultimate tic tac toe)游戏,已完成大部分功能:实现数组映射、单棋盘获胜检测并将结果映射至3×3数组等。但3×3棋盘的获胜检测子程序CHECK_WINNER仅能检测第一行。我在单井字棋测试文件中该功能运行正常,怀疑问题可能隐藏在其他子程序中。

相关汇编代码如下:

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

问题根源

代码初始化阶段的DX寄存器被清零,却在后续切换行/列时用来重置DI的地址:

  1. 初始化时LEA DI, BIG_BOARD正确指向了棋盘数组的起始地址,但XOR DX, DX将DX设为0,没有把棋盘起始地址存入DX。
  2. 当第一行检测失败进入PROXIMA_LINHA1时,MOV DI, DX会把DI重置为0(而不是棋盘的起始地址),后续ADD DI, BX计算出的偏移完全错误,导致无法正确检测第二、第三行。

修复方案

  1. 修正寄存器初始化:在LEA DI, BIG_BOARD后,将DI的值存入DX,让DX保存棋盘的起始地址:
CHECK_WINNER PROC

    XOR BX, BX
    XOR CX, CX
    XOR DX, DX
    XOR DI, DI
    LEA DI, BIG_BOARD
    MOV DX, DI  ; 保存棋盘起始地址到DX,后续用来重置DI
    
VERIFICA_VENCEDOR_LINHA1:
    ; 后续代码保持不变
  1. 调整获胜后的处理逻辑:GANHOU_BOARD1中的CALL EXIT会直接终止程序,不符合终极井字棋的流程(应该返回获胜状态给调用者,继续游戏逻辑),建议改为设置获胜标志后RET,例如:
GANHOU_BOARD1:
    MOV AX, 1  ; 用AX返回获胜标志(1表示当前玩家获胜)
    RET
  1. 验证对角线步长:右上到左下的对角线步长ADD DI,2是正确的(对应索引2→4→6),但如果棋盘数组的内存布局不是连续的0-8索引,需要重新确认步长是否匹配。

内容的提问来源于stack exchange,提问作者Tomás Ramos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:05:14