欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 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

相关标签: 汇编