assembly 为什么在我的石头、剪刀、布游戏中,我的函数每次都不能产生不同的数字?

bkhjykvo  于 2023-06-06  发布在  其他
关注(0)|答案(1)|浏览(147)

我在汇编8086语言中遇到了一个问题。我在做石头剪刀布游戏。当用户给出一个输入,程序会再次问这个问题。问题是计算机的选择永远不会改变。每次调用该函数,我都想再次生成1 - 3之间的数字。
代码如下:

.MODEL SMALL
.STACK 100H

.DATA
    playerChoice DB ?
    computerChoice DB ?
    userInput DB 'ROCK PAPER SCISSORS? (1-Rock 2-Paper 3-Scissors q-Quit) : $'   
    playerWinsMsg DB 'Result : Player Won! $'
    computerWinsMsg DB 'Result : Computer Won! $'
    tieMsg DB 'Result : Tie!! $'
    invalidChoiceMsg DB 'Invalid choice! Try again!! $'

.CODE
    MAIN PROC 
        
       MOV AX, @DATA
       MOV DS, AX
       
    GAME_LOOP:
 
        MOV AH, 09H
        LEA DX, userInput
        INT 21H
              
        
        MOV AH, 01H
        INT 21H
        CMP AL, 'q'
        JE EXIT
        SUB AL, 30H
        MOV playerChoice, AL
        
        MOV AH,2
        MOV DL, 10
        INT 21H
        MOV DL, 13
        INT 21H

        CALL RANDOMIZE
        CALL COMPUTER_CHOICE
        
        

        CMP playerChoice, 1
        JE ROCK
        CMP playerChoice, 2
        JE PAPER
        CMP playerChoice, 3
        JE SCISSORS
       

        LEA DX, invalidChoiceMsg
        MOV AH, 09H
        INT 21H 
        
        MOV AH,2
        MOV DL, 10
        INT 21H
        MOV DL, 13
        INT 21H
        
        JMP GAME_LOOP

    ROCK:
        
        CMP computerChoice, 1
        JE TIE
        CMP computerChoice, 2
        JE COMPUTER_WINS
        CMP computerChoice, 3
        JE PLAYER_WINS
        JMP EXIT

    PAPER:

        CMP computerChoice, 1
        JE PLAYER_WINS
        CMP computerChoice, 2
        JE TIE
        CMP computerChoice, 3
        JE COMPUTER_WINS
        JMP EXIT

    SCISSORS:

        CMP computerChoice, 1
        JE COMPUTER_WINS
        CMP computerChoice, 2
        JE PLAYER_WINS
        CMP computerChoice, 3
        JE TIE
        JMP EXIT

    PLAYER_WINS:
        MOV AH, 09H
        LEA DX, playerWinsMsg
        INT 21H
        
        MOV AH,2
        MOV DL, 10
        INT 21H
        MOV DL, 13
        INT 21H
        
        JMP GAME_LOOP

    COMPUTER_WINS:
        MOV AH, 09H
        LEA DX, computerWinsMsg
        INT 21H 
        
        MOV AH,2
        MOV DL, 10
        INT 21H
        MOV DL, 13
        INT 21H
        
        JMP GAME_LOOP

    TIE:
        MOV AH, 09H
        LEA DX, tieMsg
        INT 21H
        
        MOV AH,2
        MOV DL, 10
        INT 21H
        MOV DL, 13
        INT 21H
        
        JMP GAME_LOOP    

    RANDOMIZE:
        MOV AH, 2CH
        INT 21H
        MOV AH, DL
        XOR AH, AH
        ADD DL, 1
        MOV BX, 3
        XOR DX, DX
        DIV BX
        ADD AL, 1
        MOV computerChoice, AL
        RET

    COMPUTER_CHOICE:
        CALL RANDOMIZE
        RET 
        
    EXIT:
        MOV AH, 4CH
        INT 21H

    MAIN ENDP
END MAIN
zzlelutf

zzlelutf1#

对于每个computerChoice,您调用 randomize 两次。不幸的是,randomize 代码有一些重要的错误:

  • 实际上,您并没有使用从系统时间获得的返回值,因为您错误地将DL移动到AH。

因此,计算将基于AL中加载的最后一个值,并且恰好是MOV DL, 13INT 21H中DOS返回的13。
因此,第一次调用 randomize 时,AL包含13,一旦除以3,就会产生商4,然后递增到5。
第二次,AL包含5,一旦除以3产生商1,然后递增到2。
因此,计算机总是播放2

  • 你应该检查除以3的余数,而不是像现在这样检查商。

余数将是范围[0,2]中的一个数字,并且递增 that 将在范围[1,3]中产生有用的选择。
这是改进后的代码,其中我还删除了一些冗余,并首选使用字节大小的除法:

RANDOMIZE:
  mov  ah, 2Ch   ; DOS.GetSystemtime
  int  21h       ; -> CX DX
  mov  al, dl    ; [0,99]
  cbw
  mov  dl, 3
  div  dl        ; AX / DL --> Quotient AL, Remainder AH
  inc  ah
  mov  computerChoice, ah
  ret

我相信没有必要为每个computerChoice调用两次 randomize

相关问题