计算机组成原理与接口设计——期中课程设计:使用汇编实现的迷宫游戏
程序员文章站
2022-04-12 23:32:14
...
功能简介与实现效果
一个用X86实现的迷宫游戏,首先,在进入游戏首页之后,玩家可以根据自己的喜好选择自己想要玩的难度,本游戏总共有是三个难度,Easy,Normal,Hard,分别对应三个不同难度的迷宫;
在选择了迷宫难度之后,将会刷新出一个对应难度的迷宫,在这个游戏中,玩家扮演的是一个想要逃离迷宫的小人,这个人用一个笑脸表示,只有当玩家控制角色到达迷宫的出口,即迷宫中标有 A
的位置时候,才能获得游戏的胜利;玩家将通过键盘上的W,A,S,D
键对角色进行移动,分别对应向上,左,下,右移动;当碰到障碍物的时候,角色将不能往那个方向移动;
在成功走出迷宫之后,玩家可以选择进入下一关或者是离开游戏;如果玩家已经走出最难的迷宫,那么玩家也可以选择继续游戏,重新玩一遍游戏;
程序流程图
实现过程
第一步,我们需要在DATA SEGMENT 中存放一些我们之后要使用的数据
- 首先,是将整个迷宫模型保存在MSG_EASYMAZE(简单难度),MSG_NORMALMAZE(普通难度),MSG_HARDMAZE中(困难难度),分别对应三个难度的迷宫模型(这里限于篇幅值显示了MSG_EASYMAZE,另外两个迷宫是一样的原理,具体内容可以下载最下面的源代码查看)
MSG_EASYMAZE DB "---------------------------------------------|", 0AH, 0DH
DB " | | | | | |", 0AH, 0DH
DB "| |------------ |--- | | | | | | | |", 0AH, 0DH
DB "| | | | | | | | | |", 0AH, 0DH
DB "| |--| ---| |--|-----| |------ | |--| |", 0AH, 0DH
DB "| | | | |--| | |", 0AH, 0DH
DB "|--- | |-----| | ------| ------|", 0AH, 0DH
DB "| | | | |--| | | |", 0AH, 0DH
DB "| ------| ------| |--| | |--- |--- | |", 0AH, 0DH
DB "| | | | A", 0AH, 0DH
DB "|--------------------------------------------|$"
- 然后,是一些字符串,这些字符串将在游戏引导界面告诉玩家该如何操作:
NEW_LINE DB 13,10,"$"
MSG_WON DB "You Have Won!!! $", 0AH, 0DH
MSG_NEXTLEVEL DB 13,10,"Go To The Next Level: Enter Y to the Next Level,Input Others to Exit!$",0AH, 0DH
MSG_CONTINUE DB 13,10,"If Continue: Enter Y to Continue,Input Others to Exit!$",0AH, 0DH
MSG_INSTRUCTION DB "WELCOME !!! $", 0AH, 0DH
MSG_SETLEVEL DB "Enter the level you want to play(0 for easy,1 for normal,2 for difficulty): ",0AH, 0DH
DB "Any Invalid Input Will Be Treat As 0: $",0AH, 0DH
MSG_CONTROL DB "You are about to play the game, remember,you can use the w,a,s,d in the keyboard to move",0AH, 0DH
DB "w for up, a for west, s for down, d for east, enter any key to play the game, have a good time!!!$",0AH, 0DH
- 然后是一些我们需要使用的变量:
变量名 | 功能 |
---|---|
x | 玩家当前的x坐标 |
y | 玩家当前的y坐标 |
NextX | 玩家下一步的x坐标 |
NextY | 玩家下一步的y坐标 |
position | 临时变量,用于取出某个位置的内容(用于判断是不是为空,如果为空,则可以移动到该位置) |
dirInput | 临时变量,用于保存输入的移动指令,w,s,a,d |
difficulty | 临时变量,用于保存输入的难度 |
player | 表示玩家(打印该变量即打印玩家) |
direction | 输入的指令(如Y表示Yes,用于判断是否继续游戏等函数) |
x DB 0H ; the x-coordinate of the player
y DB 0H ; the y-coordinate of the player
NextX DB 0H ; the next x-coordinate of the player
NextY DB 0H ; the next y-coordinate of the player
position DB 0H ; a template variable that we use to contain the character in the position
dirInput DB 0H ; the direction you input that your player will move
difficulty DW 0H
player DB 01H
direction DB 0H
之后我们添加进入游戏之前的引导界面代码
START:
MOV AX, DATA
MOV DS, AX
MOV ES, AX
INSTRUCTION:
CALL CLEAN_SCREEN
LEA DX, MSG_INSTRUCTION ; print the welcome
CALL SHOW
LEA DX, NEW_LINE
CALL SHOW
LEA DX, MSG_CONTROL ; print how to control the player
CALL SHOW
LEA DX, NEW_LINE
CALL SHOW
LEA DX, MSG_SETLEVEL ; choose the difficulty
CALL SHOW
CALL GET_INPUT
MOV direction, AL
CMP direction,'0'
JE GAME_START ; easy game
CMP direction,'1'
JE GAME_START_NORMAL ; normal game
CMP direction,'2'
JE GAME_START_HART ; hard game
CALL GAME_START ; default : easy game
第三步,选择对应难度之后绘制对应难度的地图,下面以easy game为例:
- 首先,是绘制迷宫
;start the game
GAME_START:
CALL EASYMAZE ;draw the maze
CALL SET_STARTPOS ;set the start position of the character
CALL PRINT_PLAYER
JMP ChangePos
; Draw the easy maze
EASYMAZE:
CALL CLEAN_SCREEN
LEA DX, MSG_EASYMAZE
CALL SHOW
RET
- 打印出地图之后,我们需要在起始位置:即迷宫的入口打印玩家:
; Set the begin position of the player
SET_STARTPOS:
MOV NextX, 0H
MOV NextY, 1H
MOV x, 0H
MOV y, 1H
MOV DL, x
MOV DH, y
MOV BH, 0H
MOV AH, 2H
INT 10H
RET
; Print the player to the console
PRINT_PLAYER:
MOV DL, player
CALL SHOW_CHARACTER
RET
第四步,开始监听键盘输入指令,对输入的对应指令进行处理,移动玩家
- 监听键盘输入:w, a, s, d
ChangePos:
CALL GET_INPUT ; get the input
MOV dirInput, AL
; case : w/W(up),a/A(left),s/S(down),d/D(right)
CMP dirInput, 'W'
JE MOVE_NORTH
CMP dirInput, 'A'
JE MOVE_WEST
CMP dirInput, 'S'
JE MOVE_SOUTH
CMP dirInput, 'D'
JE MOVE_EAST
CMP dirInput, 'w'
JE MOVE_NORTH
CMP dirInput, 'a'
JE MOVE_WEST
CMP dirInput, 's'
JE MOVE_SOUTH
CMP dirInput, 'd'
JE MOVE_EAST
JMP ChangePos
- 根据对应的输入控制角色进行相应的移动,我们以输入了W为例,整个移动过程如下
- 删除原位置的字符
- 更新下一步的位置
- 判断下一步的位置是否合法
- 如果是,移动坐标到该位置,反之,不移动
- 回到
ChangePos
继续监听键盘输入,进行下一步移动
MOVE_NORTH:
CALL REMOVE_OLDPOS ;remove the character in previous position
DEC NextY
CALL ISVALID_POS
DEC y ;if the positon is empty, then update the position
MOV DL, x
MOV DH, y
CALL SET_CURSOR
CALL PRINT_PLAYER
JMP ChangePos ; go back to the ChangePos function, to read the next input
- 删除原位置的字符
;This function is used to remove the character in previous position
REMOVE_OLDPOS:
MOV DL, x
MOV DH, y
CALL SET_CURSOR
MOV DL, ' '
CALL SHOW_CHARACTER
RET
- 判断新的位置是否合法:
- 获得新的位置里面的字符
- 该字符为空格,表示可以移动
- 不为空,进入
POS_NOTEMPTY
函数判断是否为 ‘ A ’,为 ’ A ‘,获胜;反之,表示撞到了墙,不移动
ISVALID_POS:
MOV DL, NextX ; get the new position of the player
MOV DH, NextY
CALL SET_CURSOR
MOV BH, 0h
CALL GET_CHARACTER ; get the character in the new position
MOV position, AL ; if if was empty, then we can the player to that direction
CMP position, ' '
JNE POS_NOTEMPTY
RET
POS_NOTEMPTY:
CMP position, 'A' ; if it's the EXIT, then you win!!!
JE WIN
MOV DL, x
MOV DH, y
CALL SET_CURSOR
MOV NextX, DL
MOV NextY, DH ; set the new position the same as the old, it means you hit the wall and can not move
CALL PRINT_PLAYER
JMP ChangePos ; go back to the ChangePos function, to read the next input
- 整个游戏过程就是不停的监听键盘输入,获得输入之后进行移动;如果此时已经离开了迷宫,则游戏成功;反之,继续监听键盘输入。
逃离迷宫之后的界面
- 逃离迷宫后,你将会进入
WIN
函数,在这个函数里,你将选择是进入下一关(如果还有更高的难度的迷宫)还者是继续游戏(你已经通关所有难度的游戏了,可以重新再玩一次):
WIN:
CALL CLEAN_SCREEN
LEA DX, MSG_WON
CALL SHOW
CMP difficulty,02H ; difficulty = 02H, you have pass all the games
JNE SHOW_MSG_NEXTLEVEL ; if difficulty != 02H, go to choose if go to the next level
JMP EXIT_GAME ; if difficulty == 02H, go to choose if continue
EXIT_GAME:
LEA DX, MSG_CONTINUE ; print the instruction
CALL SHOW
CALL READ_INPUT
CMP AL, "Y"
JNE EXIT
JMP GAME_START
EXIT:
CALL CLEAN_SCREEN
MOV AX, 4C00H
INT 21H
一些功能函数
最后我们需要的提供一些功能函数:清屏,获得某个位置的内容,显示字符串,显示字符,设置光标的位置等
; CALL this function to print in the console
SHOW:
MOV AH, 09H
INT 21H
RET
; CALL this function to print a character in the console
SHOW_CHARACTER:
MOV AH, 02H
INT 21H
RET
;CALL this function to clean the console
CLEAN_SCREEN:
MOV AL, 3H
MOV AH, 0H
INT 10H
RET
; Print the player to the console
PRINT_PLAYER:
MOV DL, player
CALL SHOW_CHARACTER
RET
; Get the input from the keyboard
GET_INPUT:
MOV AH, 7H
INT 21H
RET
; Set the position of the cursor
SET_CURSOR:
MOV AH, 2H
INT 10H
RET
; Get the character in a position
GET_CHARACTER:
MOV AL, 0h
MOV AH, 08h
INT 10H
RET
; Get the input
READ_INPUT:
MOV AH, 01
INT 21H
RET
总结
整个程序的运行过程就是这样,一开始比较难处理的是如何获取某个位置的字符内容,之后通过使用上面的SET_CURSOR
函数和GET_CHARACTER
函数就解决了;目前让我比较在意的一点就是迷宫不能做的太大,如果做的太大的话就会导致打印的时候输出很奇怪,不过目前的程序运行起来是没有问题的๑乛◡乛๑
项目下载:Maze Game X86
上一篇: 汇编使用跳转实现1累加到100的和
下一篇: Assembly call和ret指令