汇编 课程设计 剪刀石头布( 文字描述的)

功能分析:

小游戏剪刀石头布主要功能包括:退出程序,开始游戏。开始游戏中可以选择剪刀石头布还有返回主菜单四个选项,用户回车选择了剪刀石头布中的一个时,在界面底部将会显示用户选了什么,电脑选了什么,谁赢了的情况。

界面初始化:本程序采用了彩色字符界面,运行本程序是会自动初始化,跳转到开始游戏界面时也会初始化形成另一个界面。

开始游戏:跳转到游戏界面的入口,当光标停留在这选项时,回车即可进入。进入后可选择剪刀石头布其中一项进行游戏,也可以选择返回主菜单选项。

退出程序:光标停留在这一行时,回车退出程序。

剪刀选项:光标移动到这一行,回车即代表使用者选择出剪刀,将会在底部提示出现猜拳结果。

石头选项:同上。

布选项:同上。

返回主菜单选项:光标移动到这一行,回车即跳转到上级菜单。

底部提示:当使用者按下回车时显示所选择的选项,当按下错误的按键时,给

出提示。当选择剪刀石头布选项时,给出使用者的选择,电脑的选择以及输赢结果。

效果如图:

第一个界面,有两个选项。第一个是进入游戏界面的选项,第二个是退出程序的选项。显示模式是16色的彩色文本模式,80列*25行。界面的设置参考了教材上的例子8-7。第一个选项位于第12行,第二个选项位于14行,两者都开始于第20列。为了更好地显示光标位置,每个选项的开头都是空格,光标所在行则以右三角替换空格。涉及到的函数有show函数,对程序界面初始化。Innershow函数,设置第一个界面,建立小窗口。

设计了与第一个界面对应的按键处理方法。调用16H的0号功能,从键盘获取一个输入的扫描码,判断是up还是down还是enter。为此设计了一个keylsit函数用来判断输入

当按下的是up按键时,判断当前光标的位置,若是光标行位置在12的话,不移动光标,继续等待键盘的输入。如果不是,则光标上移两行,原来光标所在行的右三角以空格替换,新光标所在的行的开头以右三角替换空格。当输入的是down时类似,要判断当前光标的行位置,再决定是否移动光标。当按下的是enter按键,将光标位置转换为选项序号,如果是1,则执行第二个界面的初始化,并调用keylist1函数。如果是2则跳转到标号exit退出程序。







第二个界面有四个选项,选项一代表选择了猜拳出剪刀,选项二代表了猜拳出石头,选项三类似。选项四为返回界面一选项。界面2涉及函数innershow1函数。

keylsit1函数原理同keylist函数。因为有四个选项,所以按下up或down要判断光标行位置条件与keylist不同。当按下enter后要判断选项序号再调用scissor或stone或paper函数,又或者跳转到程序开头,即返回了界面1。

这个界面为了实现电脑出拳,设计了四个函数,一个是随机函数,另外三个是scissor,stone,paper函数。这三个函数都要调用随机函数以模拟出拳的随机性。根据随机函数得到的随机数判断电脑是出了什么拳,并给出输赢结果在底部显示。

本程序还做了提示处理,当按下的按键不是三个按键时,将在界面底部显示提示字符串。当选择了选项时底部也有提示,当选择的是任一三个出拳选项时,在底部给出使用者和电脑的出拳情况以及输赢结果。底部提示的行从第20行开始。


以下是源码:

;***本文件为dos.exe标准模板文件***
;//
;程序名:
;作者:
;完成日期:
;程序说明:
;//
        
        ; 数据段
dseg    segment			;定义数据段
   	;to do:数据添加到下面
   	;//
   	string1 db 'please chose a item and enter  '
   	str_len equ $-string1
	item1  db ' go to play!',0ah,0dh,'$'  
	item1_len equ ($-item1)
	item2 db ' exit the program',0ah,0dh,'$' 
	item2_len equ ($-item2)    
  
        msg db 'your select is: $' ;提示信息  
    	item4   db ' scissor',0ah,0dh,'$' 
    	item4_len equ ($-item4)                              
    	item5    db ' stone  ',0ah,0dh,'$'  
    	item5_len equ ($-item5)
    	item6     db ' paper  ',0ah,0dh,'$'  
    	item6_len equ ($-item6) 
    	item7     db ' return mian menu',0ah,0dh,'$' 
    	item7_len equ ($-item7)  
    	result1 db 'result:you play even   ' ,0ah,0dh,'$'
    	result_len  equ ($-result1) 
    	result2 db 'result:haha,you win  ' ,0ah,0dh,'$'
    	result_len2  equ ($-result2)  
   	result3 db 'result:sorry,you lost' ,0ah,0dh,'$'
   	result_len3  equ ($-result3)
    	youchose db  'you chose: $'
    	cpuchose db   'cpu chose :' ,'$'                               
    	err1 db 'please presss up or down $,' 
    	err2 db  0ah,0dh, '                    key or enter key,','$'

dseg    ends


        ; 堆栈段
sseg    segment stack   	;定义堆栈段

        db      100h    dup(?) ;设置堆栈段大小为100h

sseg    ends

        ; 代码段
cseg    segment			;定义代码段

        assume  cs:cseg, ds:dseg, ss:sseg   ;关联段寄存器

start:        ;主程序入口点
  	;to do:添加主程序代码
	; ------------------------------------------------------

	;-------------------------------------------------------
        ; 退出 dos
         mov ax,dseg
         mov ds,ax
         mov es,ax
         
     
         
init:   call show
        call innershow 
      
         
                 
     
         
inkey:  call keylist 
              
up:    call up0
up1:   call up2 	
down:  call down0 
down1: call down2	 
inkey1:call keylist1 

ensure:
	
      call enterkey 
      cmp dl,31h
      je  choice1 
      cmp dl,32h             
      jne inkey 
      jmp exit
	 
choice1:
     call show  
     call innershow1
     jmp  inkey1 



ensure1:  
     call enterkey   
     cmp dl,31h 
     je  callsc
     cmp dl,32h
     je callst
     cmp dl,33h
     je callpa
     cmp dl,34h             
     je  init
     jmp inkey1

callsc:
      call  scissor
      jmp   inkey1 
callst:
      call  stone
      jmp   inkey1
callpa:
      call  paper
      jmp   inkey1       
exit:  mov ah,07h
       int 21h                     

       mov     ax, 4c00h  ;返回dos系统
       int     21h 
show   proc
         mov ah,0
         mov al,3
         int 10h
         
         mov ah,6
         mov al,0
         mov ch,0
         mov cl,0
         mov dh,24
         mov dl,79
         mov bh,07
         int 10h
        
         
         mov ah,6
         mov al,0
         mov ch,3
         mov cl,16
         mov dh,23
         mov dl,50
         mov bh,0f0h
         int 10h
         
         mov ah,13h
         lea bp,string1
         mov cx,str_len
         mov dh,3
         mov dl,16
         mov bh,0
         mov al,1
         mov bl,3ch
         int 10h   
       
       ret
show   endp 
error proc 
         push ax
         push cx
         push dx  
          
         mov ah,02h
	 mov dh,18
	 mov dl,20
	 int 10h
                              
         mov ah,6
         mov al,5
         mov ch,18
         mov cl,16
         mov dh,23
         mov dl,50
         mov bh,0f0h
         int 10h        
                  
         mov ah,2h
	 mov dh,20
	 mov dl,20
	 int 10h 
       
	 
	 mov ah,09h
 	 mov dx,offset err1
	 int 21h    
	      
	    
	 mov ah,09h
 	 mov dx,offset err2
	 int 21h  
	          
         mov ah,1
         int 21h
         
         mov ah,6
         mov al,5
         mov ch,18
         mov cl,16
         mov dh,23
         mov dl,50
         mov bh,0f0h
         int 10h       
     
         mov ah,02h
         mov bh,0 
         pop dx 
	 mov dl,20
	 int 10h ;设置光标位置(第行第列),调用bios断
	 mov ah,02h
	 mov dl,16
	 int 21h ;光标所位置显示右三角,
  
         pop cx
         pop ax
         ret
error endp
keylist  proc
         mov ah,0       
         int 16h ;调用bios断,获取键盘扫描码
         cmp ah,48h ;按了上键
         jz up ;跳转"up"
         cmp ah,50h ;按了下键
	 jz down ;同理
	 cmp ah,1ch ;按了回车
	 jz ensure ;同理    
	 call error
	 jmp  inkey 
         ret
keylist         endp
keylist1  proc
         mov ah,0       
         int 16h ;调用bios断,获取键盘扫描码
         cmp ah,48h ;按了上键
         jz up1 ;跳转"up"
         cmp ah,50h ;按了下键
	 jz down1 ;同理
	 cmp ah,1ch ;按了回车
	 jz ensure1 ;同理     
	 call error
	 jmp  inkey1 
         ret
keylist1         endp
innershow proc
                    
         mov ah,13h
         lea bp,item1
         mov cx,item1_len  
         mov dh ,10
         mov dl,20
         mov bh,0
         mov al,0
         mov bl,4ah
         int 10h   
    
         mov ah,02h
         mov bh,0  
	 mov dh,10
	 mov dl,20
	 int 10h ;设置光标位置(第行第列),调用bios断
	 mov ah,02h
	 mov dl,16
	 int 21h ;光标所位置显示右三角,
   
         mov ah,13h
         lea bp,item2
         mov cx,item2_len   
         mov dh ,12
         mov dl,20
         mov bh,0
         mov al,0
         mov bl,4ah
         int 10h        
        
          
         mov ah,02h
         mov bh,0 ; 页号
         mov dh,10
         mov dl,20
         int 10h ; 
          
          
         ret
innershow endp          
innershow1 proc
                    
         mov ah,13h
         lea bp,item4
         mov cx,item4_len  
         mov dh ,10
         mov dl,20
         mov bh,0
         mov al,0
         mov bl,4ah
         int 10h   
    
         mov ah,02h
         mov bh,0  
	 mov dh,10
	 mov dl,20
	 int 10h ;设置光标位置(第行第列),调用bios断
	 mov ah,02h
	 mov dl,16
	 int 21h ;光标所位置显示右三角,
   
          mov ah,13h
         lea bp,item5
         mov cx,item5_len   
         mov dh ,12
         mov dl,20
         mov bh,0
         mov al,0
         mov bl,4ah
         int 10h        
         
     
         
         mov ah,13h
         lea bp,item6
         mov cx,item6_len   
         mov dh ,14
         mov dl,20
         mov bh,0
         mov al,0
         mov bl,4ah
         int 10h   
         
         mov ah,13h
         lea bp,item7
         mov cx,item7_len   
         mov dh ,16
         mov dl,20
         mov bh,0
         mov al,0
         mov bl,4ah
         int 10h 
          
         mov ah,02h
         mov bh,0 ; 页号
         mov dh,10
         mov dl,20
         int 10h ; 
          
          
         ret
innershow1 endp  
enterkey proc
         push dx ;保存光标行信息
	 mov ah,02h
	 mov dh,18
	 mov dl,20
	 int 10h
	 mov ah,09h
 	 mov dx,offset msg
	 int 21h ;显示提示信息

	 pop dx ;取行信息并其显示 
	 push cx 
	 push ax
	 mov cl,2
	 mov ah,0
	 mov al,dh
	 div cl
	 add al,44 

 	 mov ah,02h
 	 mov dl,al  
	 int 21h
	 pop ax
	 pop cx
         ret
enterkey endp  
up0 proc
         cmp dh,10
	 jz inkey ;前光标第1行,则执行程;直接跳转inkey,继续接收按键输入
	 mov ah,02h
  	 mov dl,20
   	 int 10h ;光标移行首
         mov ah,02h
	 mov dl,' '
	 int 21h ;显示空格,原右三角覆盖掉
	 mov ah,02h
	 dec dh
	 dec dh
	 
	 mov dl,20
	 int 10h ;光标移行第列
	 mov ah,02h
	 mov dl,16
	 int 21h ;显示右三角
	 jmp inkey ;跳接收按键输入
         ret
up0 endp  
up2 proc
         cmp dh,10
	 jz inkey1 ;前光标第1行,则执行程;直接跳转inkey,继续接收按键输入
	 mov ah,02h
  	 mov dl,20
   	 int 10h ;光标移行首
         mov ah,02h
	 mov dl,' '
	 int 21h ;显示空格,原右三角覆盖掉
	 mov ah,02h
	 dec dh
	 dec dh
	 mov dl,20
	 int 10h ;光标移行第列
	 mov ah,02h
	 mov dl,16
	 int 21h ;显示右三角
	 jmp inkey1 ;跳接收按键输入
         ret
up2 endp 
down0 proc
         cmp dh,12
	 jz inkey
	 mov ah,02h
	 mov dl,20
	 int 10h
	 mov ah,02h
	 mov dl,' '
	 int 21h
	 mov ah,02h

	 inc dh
	 inc dh
	 mov dl,20
	 int 10h
	 mov ah,02h
	 mov dl,16
	 int 21h
	 jmp inkey 
         ret
down0 endp
down2 proc
         cmp dh,16
	 jz inkey1
	 mov ah,02h
	 mov dl,20
	 int 10h
	 mov ah,02h
	 mov dl,' '
	 int 21h
	 mov ah,02h
	 inc dh
	 inc dh
	 mov dl,20
	 int 10h
	 mov ah,02h
	 mov dl,16
	 int 21h
	 jmp  inkey1 
         ret
down2 endp 
rand  proc
      push cx
      push dx
      push ax
      sti
      mov ah,0             ;读时钟计数器值
      int 1ah
      mov ax,dx            ;清高6位
      and ah,3
      mov dl,101           ;除3,产生0~100余数
      div dl
      mov bl,ah            ;余数存bx,作随机数
      pop ax
      pop dx
      pop cx
      ret
rand  endp   
scissor proc  
         mov ah,02h
	 mov dh,19
	 mov dl,20
	 int 10h
         mov ah,09h
 	 mov dx,offset youchose
	 int 21h ;显示提示信息 
	 mov ah,09h
 	 mov dx,offset item4
	 int 21h  
	    
        call rand
        cmp bl,34
        jl sc1
        cmp bl,67
        jg sc3
        jmp sc2
sc1:     
         mov ah,02h
	 mov dh,20
	 mov dl,20
	 int 10h
         mov ah,09h
 	 mov dx,offset cpuchose
	 int 21h ;显示提示信息 
	 mov ah,09h
 	 mov dx,offset item4
	 int 21h  
	     
	 mov ah,02h
	 mov dh,21
	 mov dl,20
	 int 10h
 
	 mov ah,09h
 	 mov dx,offset   result1
	 int 21h 
	   
	           
         jmp r
sc2:     
         mov ah,02h
	 mov dh,20
	 mov dl,20
	 int 10h
         mov ah,09h
 	 mov dx,offset cpuchose
	 int 21h ;显示提示信息 
	 mov ah,09h
 	 mov dx,offset item5
	 int 21h 
	     
	 mov ah,02h
	 mov dh,21
	 mov dl,20
	 int 10h
         mov ah,09h
 	 
 	 mov dx,offset   result3
	 int 21h        
         jmp r
sc3:     
         mov ah,02h
	 mov dh,20
	 mov dl,20
	 int 10h
          
         mov ah,09h
 	 mov dx,offset cpuchose
	 int 21h ;显示提示信息 
	     
	 mov ah,09h
 	 mov dx,offset item6
	 int 21h 
	     
	 mov ah,02h
	 mov dh,21
	 mov dl,20
	 int 10h
       
	 mov ah,09h
 	 mov dx,offset   result2
	 int 21h 
	            
r:      mov ah,02h
        mov bh,0 
        mov dh,10
	mov dl,20
	int 10h ;设置光标位置(第行第列),调用bios断
	  
         ret                  
             
scissor endp 
stone  proc  
         mov ah,02h
	 mov dh,19
	 mov dl,20
	 int 10h
         mov ah,09h
 	 mov dx,offset youchose
	 int 21h ;显示提示信息 
	 mov ah,09h
 	 mov dx,offset item5
         int 21h  
	    
        call rand
        cmp bl,34
        jl sto1
        cmp bl,67
        jg sto3
        jmp sto2
sto1:     
         mov ah,02h
	 mov dh,20
	 mov dl,20
	 int 10h
         mov ah,09h
 	 mov dx,offset cpuchose
	 int 21h ;显示提示信息 
	 mov ah,09h
 	 mov dx,offset item4
	 int 21h  
	     
	 mov ah,02h
	 mov dh,21
	 mov dl,20
	 int 10h
 
	 mov ah,09h
 	 mov dx,offset   result2
	 int 21h 
	   
	           
         jmp r1
sto2:     
         mov ah,02h
	 mov dh,20
	 mov dl,20
	 int 10h
         mov ah,09h
 	 mov dx,offset cpuchose
	 int 21h ;显示提示信息 
	 mov ah,09h
 	 mov dx,offset item5
	 int 21h 
	     
	 mov ah,02h
	 mov dh,21
	 mov dl,20
	 int 10h
         mov ah,09h
 	 
 	 mov dx,offset   result1
	 int 21h        
         jmp r1
sto3:     
         mov ah,02h
	 mov dh,20
	 mov dl,20
	 int 10h
          
         mov ah,09h
 	 mov dx,offset cpuchose
	 int 21h ;显示提示信息 
	     
	 mov ah,09h
 	 mov dx,offset item6
	 int 21h 
	     
	 mov ah,02h
	 mov dh,21
	 mov dl,20
	 int 10h
       
	 mov ah,09h
 	 mov dx,offset   result1
	 int 21h 
	            
r1:     mov ah,02h
        mov bh,0 
        mov dh,12
	mov dl,20
	int 10h ;设置光标位置(第行第列),调用bios断
	  
              
       ret      
stone  endp 
paper  proc
         mov ah,02h
	 mov dh,19
	 mov dl,20
	 int 10h
         mov ah,09h
 	 mov dx,offset youchose
	 int 21h ;显示提示信息 
	 mov ah,09h
 	 mov dx,offset item6
	 int 21h  
	    
        call rand
        cmp bl,34
        jl pa1
        cmp bl,67
        jg pa3
        jmp pa2
pa1:     
         mov ah,02h
	 mov dh,20
	 mov dl,20
	int 10h
         mov ah,09h
 	 mov dx,offset cpuchose
	 int 21h ;显示提示信息 
	 mov ah,09h
 	 mov dx,offset item4
	 int 21h  
	     
	 mov ah,02h
	 mov dh,21
	 mov dl,20
	 int 10h
 
	 mov ah,09h
 	 mov dx,offset   result3
	 int 21h 
	   
	           
         jmp r2
pa2:     
         mov ah,02h
	 mov dh,20
	 mov dl,20
	 int 10h
         mov ah,09h
 	 mov dx,offset cpuchose
	 int 21h ;显示提示信息 
	 mov ah,09h
 	 mov dx,offset item5
	 int 21h 
	     
	 mov ah,02h
	 mov dh,21
	 mov dl,20
	 int 10h
         mov ah,09h
 	 
 	 mov dx,offset   result2
	 int 21h        
         jmp r2
pa3:     
         mov ah,02h
	 mov dh,20
	 mov dl,20
	 int 10h
          
         mov ah,09h
 	 mov dx,offset cpuchose
	 int 21h ;显示提示信息 
	     
	 mov ah,09h
 	 mov dx,offset item6
	 int 21h 
	     
	 mov ah,02h
	 mov dh,21
	 mov dl,20
	 int 10h
       
	 mov ah,09h
 	 mov dx,offset   result1
	 int 21h 
	            
r2:      mov ah,02h
         mov bh,0 
         mov dh,14
	 mov dl,20
	 int 10h ;设置光标位置(第行第列),调用bios断
	      
       ret     
paper  endp

cseg    ends
	;to do: 添加其他段 [可选]
	;///

end start      ; 程序结束

于每个界面的选项数目不同,选项对应的功能不同,所以必须分成两套键盘按键处理方案。好在按键处理原理相同,麻烦的只是设置了太多标号,跳转的时候眼花缭乱而已。

由于有两个界面,界面的切换也是比较重要的处理,随着界面的切换,按键处理也要跟着切换。处理办法是跳转到一个标号choice1,初始化界面2,然后再跳转到标号inkey1,调用函数keylist1。在调试中遇到的另外一个问题是随机函数,随机函数是在网上找的,一开始我把除以101改成除以3,调试时总是溢出,后来认真看了代码,源代码是高位6位清零后再除以101,这时候就不会溢出。

于是我干脆不改这个函数了,而是在调用随机函数后判断的随机数小于34还是大于67,还是处于两者之间。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值