8086 Assembly Code for Minesweeper Game
.MODEL SMALL
.STACK 1024
.DATA ; data section
; key definitions
LEFT EQU 4bh
RIGHT EQU 4dh
UP EQU 48h
DOWN EQU 50h
ESCAPE EQU 1Bh
board DB 100 DUP(?) ; space to save 10x10 board
posX DW 0 ; cursor position
posY DW 0
nMines DW 0; the number of mines
nHidden DW 100; the number of hidden positions
loseMsg DB 'You lost!', 0
winMsg DB 'You won!', 0
waitmsg DB 'Press ESC to exit...', 0
.CODE ; code section
.STARTUP
main PROC ; program entry point
mov ah, 0
mov al, 3h ; set graphics mode to 640x480
int 10h
mov ax, 0b800h ; point to screen with es
mov es, ax
call clearBoard ; clear the board
call generateMines ; generate the mines randomly
call fillNumbers ; count all mines
call printBoard ; print the initial board
call printCursor ; print the cursor
gameStart:
mov ah, 01h ; wait for key pressed
int 16h
jnz readKey
jmp noKey
readKey:
mov ah, 00h ; get code of key pressed
int 16h
cmp al, ESCAPE ; if it was escape, exit
jne ifarrow
jmp exit
ifarrow:
cmp ah, LEFT
je moveLeft
cmp ah, RIGHT
je moveRight
cmp ah, UP
je moveUp
cmp ah, DOWN
je moveDown
cmp al, ' ' ; if it's a space
je showMine
cmp al, 'f' ; if it's a f character
je jmpflag
jmp noKey ; if any other key, ignore it
jmpflag:
jmp flag
moveRight:
mov ax, [posX]
inc ax
cmp ax, 10
jl updrpos
jmp noKey
updrpos:
mov [posX], ax
jmp update
moveLeft:
mov ax, [posX]
dec ax
cmp ax, 0
jge updlpos
jmp noKey
updlpos:
mov [posX], ax
jmp update
moveDown:
mov ax, [posY]
inc ax
cmp ax, 10
jge noKey
mov [posY], ax
jmp update
moveUp:
mov ax, [posY]
dec ax
cmp ax, 0
jl noKey
mov [posY], ax
jmp update
showMine:
mov ax, [posX]
mov bx, [posY]
call getBoardChar ; get character at current position
test al, 80h ; see if the char is hidden
jz noKey ; if it's not hidden, we can't unhide it
test al, 40h ; see if it has a flag
jnz noKey ; if it has a flag, we can't unhide it
xor al, 80h ; else, clear hidden
cmp al, 9; see if it was a mine
je lose; if it was a mine, end game
mov ax, [posX]
mov bx, [posY]
call clearEmpty ; unhide and clear all neighboring empty spaces
mov ax, [nHidden]
cmp ax, [nMines] ; see if we uncovered all but the mines
je win ; if so, we won
jmp update
flag:
mov ax, [posX]
mov bx, [posY]
call getBoardChar ; get character at current position
test al, 80h ; see if the char is hidden
jz noKey ; if it's not hidden, we can't put a flag there
xor al, 40h ; else, set flag
mov cl, al
mov ax, [posX]
mov bx, [posY]
call setBoardChar ; set character at current position
update:
call printBoard
call printCursor ; print the cursor
noKey:
jmp gameStart
win:
call showMines ; show all mines as flagged
call printBoard
lea si, winMsg ; print a win message
mov dl, 10
mov dh, 10
call printString
jmp waitEsc
lose:
call showAll ; set all board chars as visible
call printBoard
lea si, loseMsg ; print a lose message
mov dl, 10
mov dh, 10
call printString
waitEsc:
lea si, waitMsg ; print a press key message
mov dl, 10
mov dh, 11
call printString
waitKey: ; wait for the escape key
mov ah, 00h; wait for a key
int 16h
cmp al, ESCAPE ; if it was escape, exit
jne waitKey
exit:
mov ah, 0
mov al, 3h ; set graphics mode to 640x480
int 10h
mov ah,4ch
int 21h
main ENDP
;///////////////////////////////////
; clear the minesweeper board using
; the char in al
;///////////////////////////////////
clearBoard PROC
lea si, board
mov cx, 100
mov al, 80h ; set all spaces as hidden
iloop:
mov [si], al
inc si
loop iloop
ret
clearBoard ENDP
;///////////////////////////////////
; show all the mines and numbers in
; the board
;///////////////////////////////////
showAll PROC
lea si, board
mov cx, 100
sloop:
mov al, [si] ; get char from board
and al, 0Fh ; set all spaces as not hidden
mov [si], al
inc si
loop sloop
ret
showAll ENDP
;///////////////////////////////////
; show all the mines flagged
;///////////////////////////////////
showMines PROC
lea si, board
mov cx, 100
floop:
mov al, [si] ; get char from board
and al, 0Fh
cmp al, 9 ; if it was a mine
jne skip
or al, 0C0h ; flag it
mov [si], al
skip:
inc si
loop floop
ret
showMines ENDP
;///////////////////////////////////
; generate random mines in the board
;///////////////////////////////////
generateMines PROC
lea si, board
mov cx, 10 ; generate at least 10 mines
call random10 ; get a random number between 0 and 10
add cx, ax ; count between 0 and 16 mines
mov [nMines], cx ; save as number of mines
mov ax, 20
call delay
gloop:
call random10 ; get a random number between 0 and 10
mov dx, ax ; save number in dx
shl ax, 5
xor ax, [nMines]
call delay
call random10; get another random number between 0 and 10
mov bx, ax ; save number in bx
mov ax, dx ; set the char at the generated position
call getBoardChar
and al, 0Fh
jne gloop
push cx
mov ax, dx ; set the char at the generated position
mov cx, 89h ; set a hidden mine
call setBoardChar
pop cx
loop gloop
ret
generateMines ENDP