Keithan
Keithan

Reputation: 33

Why is the incorrect character not showing up?

So I am making a typing game, where the word drops down the screen and the user has to type the word before it reaches the bottom of the screen. My code has where if the user types the correct character, it prints it in green and over the original word. Then if the user types the incorrect character, it prints it in red and also over original word but the user has to type the right character for them to continue. The issue I am having is that the incorrect character does display correctly.

include Irvine32.inc

BUFMAX EQU 128

.data
    Words BYTE "house", 0
          BYTE "water", 0 
          BYTE "foods", 0
          BYTE "apple", 0
          BYTE "cloud", 0 ; List of words to be typed

    msElapsed BYTE 0
    positionX BYTE 0   
    positionY BYTE 1 
    nextWord DWORD 0
    score DWORD 0      
    scoreMsg BYTE "Game Over", 0 
    char BYTE ?                                 ; Character input by user
    correctBuffer BYTE BUFMAX DUP (0)           ; Buffer to store correctly typed characters
    incorrectBuffer BYTE BUFMAX DUP (0)
    Index DWORD 0      

.code
main PROC
    call TypingGame   
    invoke ExitProcess, 0 

main ENDP

TypingGame PROC
gameLoop:

    mov dl, positionX                   ; Move positionX value to DL register
    mov dh, positionY                   ; Move positionY value to DH register
    call Gotoxy                         ; Move cursor to the specified (X, Y) position

    ; Print the original word in white
    mov eax, white + (black * 16)       ; Set text color to white on black background
    call SetTextColor                   ; Apply the text color
    mov edx, OFFSET Words               ; Load address of Words array into ESI
    add edx, [nextWord]
    call WriteString                    ; Print the current word

    ; Draw the correctly typed characters in green over the original word
    mov dl, positionX
    mov dh, positionY
    call Gotoxy

    mov eax, green + (black * 16)       ; Set text color to green on black background
    call SetTextColor                   
    mov edx, OFFSET correctBuffer       ; Load address of correctBuffer into EDX
    call WriteString                    ; Print the correctBuffer string

    ; Draw the incorrectly typed characters in red over the original word
    mov dl, positionX
    mov dh, positionY
    call Gotoxy

    mov eax, red + (black * 16)         ; Set text color to red on black background
    call SetTextColor                   
    mov edx, OFFSET incorrectBuffer     ; Load address of incorrectBuffer into EDX
    call WriteString                    ; Print the incorrectBuffer string

    ; Set delay for inputs
    mov eax, 50
    add [msElapsed], 1
    call Delay

    call ReadKey                        ; Read a key from the keyboard
    jz continueLoop
    mov char, al                        ; Store the read character in char

    mov esi, OFFSET Words               ; Load address of Words array into ESI
    add esi, [nextWord]
    add esi, [Index]                    ; Add Index value to ESI to point to the current character
    movzx ebx, char                     ; Move char to EBX and zero-extend it
    
    cmp [esi], bl                       ; Compare current character in Words with char
    jne incorrect                       ; If they are not equal, jump to incorrect

correct:
    mov esi, OFFSET correctBuffer       ; Load address of correctBuffer into ESI
    add esi, [Index]                    ; Add Index value to ESI to point to the correct position
    mov [esi], bl                       ; Store the correct character in correctBuffer
    inc esi
    mov BYTE PTR [esi], 0               ; Null-terminate the correct buffer

    inc [Index]                         ; Increment the Index

    ; Compare Index with the end of the current word
    mov esi, OFFSET Words
    add esi, [nextWord]
    add esi, [Index]
    cmp BYTE PTR [esi], 0
    jne continueLoop                    ; If not the end, continue the loop

    ; If a word is completed, reset index and move to the next word
    mov [Index], 0
    add [nextWord], TYPE BYTE           ; Move to next word
    mov [positionX], 0                  ; Reset X
    mov [positionY], 0                  ; Reset Y

    jl gameLoop                         ; If positionY is less than 24, jump to gameLoop
    jmp endGame                         ; Otherwise, jump to endGame

incorrect:
    ; Store the incorrect character in incorrectBuffer
    mov esi, OFFSET incorrectBuffer     ; Load address of incorrectBuffer into ESI
    add esi, [Index]                    ; Add index to incorrectBuffer position
    mov [esi], bl                       ; Store the incorrect character
    inc esi
    mov BYTE PTR [esi], 0               ; Null-terminate the incorrect buffer

    ; Move cursor to the correct position for the incorrect character
    mov dl, positionX
    movzx eax, BYTE PTR [Index]
    add dl, al
    mov dh, positionY
    call Gotoxy

    mov eax, red + (black * 16)         ; Set text color to red on black background
    call SetTextColor                   ; Apply the text color
    mov al, char                        ; Move the incorrect character to AL
    call WriteChar                      ; Print the incorrect character

    inc [Index]                         ; Increment the Index

    jmp continueLoop                    ; Jump to continueLoop

continueLoop:

    ; Clear previous word
    mov dl, positionX                   ; Move positionX value to DL register
    mov dh, [positionY]                 ; Move positionY value to DH register
    call Gotoxy                         ; Move cursor to the specified (X, Y) position

    ; Print the original word in black
    mov eax, black + (black * 16)       ; Set text color to black on black background
    call SetTextColor                   ; Apply the text color
    mov edx, OFFSET Words               ; Load address of Words array into ESI
    add edx, [nextWord]                 ; 1
    call WriteString                    ; Print the current word

    cmp [msElapsed], 20
    jl skipIncrement                    ; Do not increase y if not 1000ms (1 sec)
    add [positionY], 1                  ; Increment the Y position
    mov [msElapsed], 0                  ; Reset ms counter
skipIncrement:

    cmp [positionY], 24                 ; Compare positionY with 24
    jl gameLoop                         ; If positionY is less than 24, jump to gameLoop
    jmp endGame                         ; Otherwise, jump to endGame

endGame:
    call Clrscr                         ; Clear the screen
    mov edx, OFFSET scoreMsg            ; Load address of scoreMsg into EDX
    call WriteString                    ; Print the score message
    ret                                 ; Return from procedure
TypingGame ENDP
END main

I tried adding a delay in the incorrect loop but the character disappears after the delay ends. Also even if the delay is added, when the user wants to enter the right character to continue, the wrong character stays when it should disappear. I would greatly appreciate it if you can help me out. Thank you so much!

Upvotes: 1

Views: 64

Answers (1)

Sep Roland
Sep Roland

Reputation: 39166

the user has to type the right character for them to continue.

This is an important piece of information. It immediately entails that the incorrectBuffer will never have to store more than one character (plus a terminating zero).

Currently you are storing the incorrect character at an indexed location within the incorrectBuffer. Consider what happens for the word "house" when the user types h followed by the incorrect z.

          words: h, o, u, s, e, 0, ...
  correctBuffer: h, 0, 0, 0, ...
incorrectBuffer: 0, z, 0, 0, ...
                    ^
                    \ you have stored "z" at an indexed location (index=1)

The screen refresh logic that you have at the top of your gameLoop will first draw the whole word in white, then overwrite the "h" in green, and finally overwrite nothing at all in red because the incorrectBuffer begins with a terminating zero!

The solution is to store the incorrect character at the start of your (small) incorrectBuffer, and to not use Gotoxy in the screen refresh logic when switching from outputting in green to red.
Hint: every time a correct character arrives, you should write a zero at the start of the incorrectBuffer.

Future problems:

; If a word is completed, reset index and move to the next word
mov [Index], 0
add [nextWord], TYPE BYTE           ; Move to next word
mov [positionX], 0                  ; Reset X
mov [positionY], 0                  ; Reset Y

jl gameLoop                         ; If positionY is less than 24, jump to gameLoop
jmp endGame                         ; Otherwise, jump to endGame
  • Adding TYPE BYTE will not allow you to move to the next word! Since all your zero-terminated words have 5 characters, just write add nextword, 6.
  • Since you reset the positions X and Y to zero, the jl gameLoop instruction should read jmp gameLoop.
  • Also consider a user that exhausts your list containing only 5 words? That's when you would want to jump to endGame.

Upvotes: 1

Related Questions