计算机组成原理与接口设计——期中课程设计:使用汇编实现的迷宫游戏

功能简介与实现效果

一个用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

一些功能函数

最后我们需要的提供一些功能函数:清屏,获得某个位置的内容,显示字符串,显示字符,设置光标的位置等

扫描二维码关注公众号,回复: 3369740 查看本文章
; 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

猜你喜欢

转载自blog.csdn.net/qiuxy23/article/details/81253675