.
MODEL SMALL
.DATA
GMSG DB 'Computer TIC TAC TOE.',0DH,0AH
DB 'User is X, computer is O',0DH,0AH,0DH,0AH,'$'
BOARD DB '123456789'
BTXT DB 0DH,0AH
DB ' | | ',0DH,0AH
DB '---------',0DH,0AH
DB ' | | ',0DH,0AH
DB '---------',0DH,0AH
DB ' | | ',0DH,0AH,0DH,0AH,'$'
BPOS DB 2,6,10,24,28,32,46,50,54
PMSG DB 'Enter your move (0 to 9): $'
PIM1 DB 0DH,0AH,'That move does not make sense, try again.',0DH,0AH,'$'
PIM2 DB 0DH,0AH,'That square is occupied, try again.',0DH,0AH,'$'
CMSG DB 'I choose square $'
CRLF DB 0DH,0AH,'$'
WINS DW 1,2,3, 4,5,6, 7,8,9 ;any row
DW 1,4,7, 2,5,8, 3,6,9 ;any column
DW 1,5,9, 3,5,7 ;either diagonal
XWIN DB 'X wins the game!',0DH,0AH,'$'
OWIN DB 'O wins the game!',0DH,0AH,'$'
MTIE DB 'The game is a tie.',0DH,0AH,'$'
.CODE
.STARTUP
LEA DX,GMSG ;set up pointer to greeting
MOV AH,9 ;display string function
INT 21H
CALL SHOWBRD ;display board
NEXT: CALL PMOVE ;get player move
CALL SHOWBRD ;display board
CALL CHECK ;did player win or tie?
JZ EXIT
CALL CMOVE ;let computer move
CALL SHOWBRD ;display board
CALL CHECK ;did computer win or tie?
JZ EXIT
JMP NEXT ;continue with game
EXIT: .EXIT
SHOWBRD PROC NEAR
MOV CX,9 ;set up loop counter
SUB SI,SI ;set up index pointer
LBC: MOV AL,BPOS[SI] ;get a board position
CBW ;convert to word
MOV DI,AX ;set up pointer to board string
MOV AL,BOARD[SI] ;get player symbol
MOV BTXT[DI],AL ;write into board string
INC SI ;advance index pointer
LOOP LBC ;repeat for all nine positions
LEA DX,BTXT ;set up pointer to board string
MOV AH,9 ;display string function
INT 21H ;DOS call
RET
SHOWBRD ENDP
PMOVE PROC NEAR
LEA DX,PMSG ;set up pointer to player string
MOV AH,9 ;display string function
INT 21H ;DOS call
MOV AH,1 ;read keyboard function
INT 21H ;DOS call
CMP AL,'1' ;insure user input is a digit
JC BPM
CMP AL,'9'+1
JNC BPM
SUB AL,31H ;remove ASCII bias
CBW ;convert to word
MOV SI,AX ;set up index pointer
MOV AL,BOARD[SI] ;get board symbol
CMP AL,'X' ;is position occupied?
JZ PSO
CMP AL,'O'
JZ PSO
MOV BOARD[SI],'X' ;save player move
LEA DX,CRLF ;set up pointer to newline string
MOV AH,9 ;display string function
INT 21H ;DOS call
RET
BPM: LEA DX,PIM1 ;set up pointer to illegal string
STP: MOV AH,9 ;display string function
INT 21H ;DOS call
JMP PMOVE ;go give user a second chance
PSO: LEA DX,PIM2 ;set up pointer to occupied string
JMP STP ;go process error message
RET
PMOVE ENDP
CMOVE PROC NEAR
SUB SI,SI ;clear index pointer
NCM: MOV AL,BOARD[SI] ;get board symbol
CMP AL,'X' ;is position occupied?
JZ STN
CMP AL,'O'
JZ STN
MOV BOARD[SI],'O' ;save computer move (not very tough, is it?)
MOV AX,SI ;save move value
PUSH AX
LEA DX,CMSG ;set up pointer to choice string
MOV AH,9 ;display string function
INT 21H ;DOS call
POP DX ;get move value back
ADD DL,31H ;add ASCII bias
MOV AH,2 ;display character function
INT 21H ;DOS call
LEA DX,CRLF ;set up pointer to newline string
MOV AH,9 ;display string function
INT 21H ;DOS call
RET
STN: INC SI ;advance to next position
JMP NCM ;go check next position
CMOVE ENDP
CHECK PROC NEAR
SUB SI,SI ;clear index pointer
MOV CX,8 ;set up loop counter
CAT: MOV DI,WINS[SI] ;get first board position
MOV AH,BOARD[DI-1] ;get board symbol
MOV DI,WINS[SI+2] ;get second board pisition
MOV BL,BOARD[DI-1] ;get board symbol
MOV DI,WINS[SI+4] ;get third board position
MOV BH,BOARD[DI-1] ;get board symbol
ADD SI,6 ;advance to next set of psitions
CMP AH,BL ;do all three symbols match?
JNZ NMA
CMP AH,BH
JNZ NMA
CMP AH,'X' ;does match contain X?
JNZ WIO
LEA DX,XWIN ;set up pointer to x-wins string
JMP EXC ;go process string
WIO: LEA DX,OWIN ;set up pointer to o-wins string
JMP EXC ;go process string
NMA: LOOP CAT ;no match, try another group
SUB SI,SI ;clear index pointer
CFB: MOV AL,BOARD[SI] ;get board symbol
CMP AL,'X' ;is symbol X?
JZ IAH
CMP AL,'O' ;is symbol O?
JZ IAH
RET ;no tie yet
IAH: INC SI ;advance to next position
LOOP CFB ;go check another board symbol
LEA DX,MTIE ;set up pointer to tie message
EXC: MOV AH,9 ;display string function
INT 21H ;DOS call
SUB AL,AL ;set zero flag
RET
CHECK ENDP
END