打印

51汇编游戏之“读心术”

[复制链接]
6663|29
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
不亦心|  楼主 | 2009-10-15 23:35 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 不亦心 于 2009-10-16 12:48 编辑

前一段时间在网上看到很多人在玩一个叫“读心术”的游戏,原理很简单,也许各位也有玩过。现在我弄了个51单片机版的“读心术”游戏,与大家分享。
     先说一下游戏的规则:玩者在心中随意想一个两位数,然后用这个两位数减去他的个位数,在减去他的十位数,得到一个新的数据,然后在1602屏幕上找到这个新数据,看它所代表的字符是什么,最后按确认键,这是“神奇的一幕”出现了,1602屏幕上出现了你刚才看到的字符。
    呵呵,这个原理很简单,大家别见笑,我就是拿来练练手的。

看一下源程序,俺先弱弱的问一句:51单片机怎么产生随机数比较好啊??????????????请大家给个方案。我用的是定时器,想找一个更好的随机数产生方法。

;##########################################################
;**********************************************************
;程序名称:51汇编游戏之"读心术"
;主控芯片:89c51 (12MHZ,LCD1602)
;程序功能:读懂你心中所想之事
;程序编写者:buyixin (不亦心)
;编写时间:2009年10月15日  19:49
;不亦心的博客:http://hi.baidu.com/不亦心/
;***********************************************************
;###########################################################
;//////变量地址申明/////////////////////////////////////////
  Page_down    BIT    P1.0     ;向下翻页键
  Page_up      BIT    P1.1     ;向上翻页键
  Make_sure    BIT    P1.2     ;确定键
  Play_start   BIT    P1.3     ;开始键
  RS           EQU    P2.0     ;定义LCD1602的RS为P2.0
  RW           EQU    P2.1     ;定义LCD1602的RW为P2.1
  E            EQU    P2.2     ;定义LCD1602的E为P2.2
  PageS        DATA   30H      ;页数暂存单元
  Num_data     DATA   31H      ;确定符号暂存单元
  Ran_data     DATA   32H      ;随机数暂存单元
  Ran_datas    DATA   33H      ;随机符号暂存单元
  Ran_data0    DATA   34H      ;第一页第一个符号暂存单元
  Ran_data1    DATA   35H
  Ran_data2    DATA   36H
  Ran_data3    DATA   37H
  Ran_data4    DATA   38H
  Ran_data5    DATA   39H
  Ran_data6    DATA   3AH
  Ran_data7    DATA   3BH
  Ran_data8    DATA   3CH
  Ran_data9    DATA   3DH
  Ran_data10   DATA   3EH
  Ran_data11   DATA   3FH      ;第12页第一个符号暂存单元
  data0        DATA   40H      ;数字十位暂存单元
  data1        DATA   41H      ;数字个位暂存单元
;//////主程序开始///////////////////////////////////////////
  ORG      0000H
  AJMP     START   
  ORG      000BH
  LJMP     TIM0                ;定时器0
  ORG      0030H
;------各部分初始化---------------------------------------
START:     MOV SP,#60H         ;设置堆栈
  MOV      Pages,#00H          ;清空关键暂存区
  MOV      Num_data,#00H
  MOV      Ran_data,#00H
  MOV      data0,#00H
  MOV      data1,#00H
  LCALL    Init_tim0           ;调用定时器0初始化
Repeat:    LCALL Ran_num       ;调用随机数产生子程序
  MOV      DPTR,#TAB_code      ;获取确定符号
  MOV      A,B
  MOVC     A,@A+DPTR
  MOV      Num_data,A
  LCALL    Font_code           ;调用随机符号产生子程序
  LCALL    Init_1602           ;调用LCD1602初始化子程序

;------开始游戏-----------------------------------------
Repeat1:   JB       Play_start,$ ;等待开始按键按下
  JNB      Play_start,$  
  MOV        Pages,#00H
FAN_YE:  LCALL    Page_shu       ;调用页数判定子程序
  MOV      P0,#80H               ;LCD1602第一行开始显示
  LCALL    WR_COM                ;调用LCD1602写命令子程序
  LCALL    WR_Page               ;调用LCD1602页写子程序   
  MOV      P0,#0C0H              ;LCD1602第二行开始显示
  LCALL    WR_COM
  LCALL    WR_Page
;--------键判---------------------------------------
AN_JIAN:  JB Page_down,Continue1 ;判断向下翻页键是否按下
  JNB      Page_down,$           
  INC      Pages                 ;页数增加1  
  MOV      A,Pages
  CJNE     A,#0CH,Cont1          ;12页翻完则重头开始
  MOV      Pages,#00H
Cont1:     AJMP     FAN_YE       ;跳到翻页处
Continue1: JB Page_up,Continue2  ;判断向上翻页按键是否按下
  JNB      Page_up,$
  MOV      A,Pages
  CJNE     A,#00H,Cont2          ;若为第一页则向上为第12页
  MOV      Pages,#0BH
  SJMP     Cont3
Cont2:     DEC Pages             ;页数减1
Cont3:     AJMP  FAN_YE
Continue2: JB Make_sure,Cont4    ;检测确认键是否按下
  JNB      Make_sure,$           ;确认键按下则显示结果
  LCALL     Display              ;调用显示结果子程序
  LJMP     Repeat
  Cont4:   AJMP AN_JIAN
;//////显示结果子程序////////////////////////////////////////////
Display:   MOV P0,#01H   ;清除屏幕
  ACALL    WR_COM   ;调用WR_COM子程序
  MOV      P0,#80H
  ACALL    WR_COM
  MOV      R3,#00H
  MOV      DPTR,#TAB2  ;your choose:
REP4:      MOV A,R3
  MOVC     A,@A+DPTR
  LCALL    WR_DATA
  INC      R3
  MOV      A,R3
  CJNE     A,#0EH,REP4
  MOV      A,Num_data
  LCALL    WR_DATA
  MOV      P0,#0C0H    ;play again
  ACALL    WR_COM
REP5:      MOV A,R3
  MOVC     A,@A+DPTR
  LCALL    WR_DATA
  INC      R3
  MOV      A,R3
  CJNE     A,#1EH,REP5
  LCALL    DELAY600MS
  RET
;//////页数判定子程序//////////////////////////////////
;------入口参数 Pages(页数)---------------------
;------出口参数 R0   (显示数字)------------------------
Page_shu:
  MOV      A,Pages
  CJNE     A,#00H,NEXT1
  MOV      R0,#00H
  MOV      Ran_datas,Ran_data0
NEXT1:     CJNE A,#01H,NEXT2
  MOV      R0,#08H
  MOV      Ran_datas,Ran_data1
NEXT2:     CJNE A,#02H,NEXT3
  MOV      R0,#10H
  MOV      Ran_datas,Ran_data2
NEXT3:     CJNE A,#03H,NEXT4
  MOV      R0,#18H
  MOV      Ran_datas,Ran_data3
NEXT4:     CJNE A,#04H,NEXT5
  MOV      R0,#20H
  MOV      Ran_datas,Ran_data4
NEXT5:     CJNE A,#05H,NEXT6
  MOV      R0,#28H
  MOV      Ran_datas,Ran_data5
NEXT6:     CJNE A,#06H,NEXT7
  MOV      R0,#30H
  MOV      Ran_datas,Ran_data6
NEXT7:     CJNE A,#07H,NEXT8
  MOV      R0,#38H
  MOV      Ran_datas,Ran_data7
NEXT8:     CJNE A,#08H,NEXT9
  MOV      R0,#40H
  MOV      Ran_datas,Ran_data8
NEXT9:     CJNE A,#09H,NEXT10
  MOV      R0,#48H
  MOV      Ran_datas,Ran_data9
NEXT10:    CJNE A,#0AH,NEXT11
  MOV      R0,#50H
  MOV      Ran_datas,Ran_data10
NEXT11:    CJNE A,#0BH,OUT
  MOV      R0,#58H
  MOV      Ran_datas,Ran_data11
OUT:      
  RET

;//////1602写页子程序///////////////////////////////////////
WR_page:
  MOV      R1,#04H
REP6:      LCALL Font_data
  MOV      A,data0
  LCALL    WR_DATA
  MOV      A,data1
  LCALL    WR_DATA
  MOV      A,R0
  MOV      B,#09H
  DIV      AB
  MOV      A,B
  JNZ      NEXT
  MOV      A,Num_data
  SJMP     OVER
NEXT:      MOV A,Ran_datas   ;取随机符号
  ADD      A,#04H
  CJNE     A,#09H,GO_ON
GO_ON:     JC REP7
  SUBB     A,#09H
REP7:      MOV Ran_datas,A
  MOV      A,Ran_datas
  MOV      DPTR,#TAB_code
  MOVC     A,@A+DPTR
OVER:      LCALL WR_DATA
  MOV      A,' '
  LCALL    WR_DATA
  INC      R0
  DJNZ     R1,REP6
  RET

;//////1602初始化子程序//////////////////////////////////
Init_1602:
  MOV      P0,#01H ;清除屏幕
  ACALL    WR_COM ;调用WR_COM子程序 .
  MOV      P0,#38H ;8位点阵方式 .
  ACALL    WR_COM
  MOV      P0,#06H
  ACALL    WR_COM
  MOV      P0,#0DH ;开显示
  ACALL    WR_COM
  MOV      P0,#80H
  ACALL    WR_COM
  MOV      R3,#00H
  MOV      DPTR,#TAB1  ;显示welcomr to buyixin's design
REP0:      MOV A,R3
  MOVC     A,@A+DPTR
  LCALL    WR_DATA
  INC      R3
  MOV      A,R3
  CJNE     A,#10H,REP0
  MOV      P0,#0C0H
  LCALL    WR_COM
REP1:      MOV A,R3
  MOVC     A,@A+DPTR
  LCALL    WR_DATA
  INC      R3
  MOV      A,R3
  CJNE     A,#20H,REP1
  LCALL    DELAY600MS
  MOV      P0,#01H ;清除屏幕
  ACALL    WR_COM ;调用WR_COM子程序
  MOV      P0,#80H    ;显示now just go! press page_start
  ACALL    WR_COM
REP21:      MOV A,R3
  MOVC     A,@A+DPTR
  LCALL    WR_DATA
  INC      R3
  MOV      A,R3
  CJNE     A,#30H,REP21
  MOV      P0,#0C0H
  LCALL    WR_COM
REP3:      MOV A,R3
  MOVC     A,@A+DPTR
  LCALL    WR_DATA
  INC      R3
  MOV      A,R3
  CJNE     A,#40H,REP3
  RET   
;//////取字型码子程序//////////////
;------出口参数 Ran_datan (随机字符)
Font_code:  LCALL    Ran_num
  MOV      Ran_data0,B   ;随机取第一页第一个符号
  LCALL    Ran_num
  MOV      Ran_data1,B
  LCALL    Ran_num
  MOV      Ran_data2,B
  LCALL    Ran_num
  MOV      Ran_data3,B
  LCALL    Ran_num
  MOV      Ran_data4,B
  LCALL    Ran_num
  MOV      Ran_data5,B
  LCALL    Ran_num
  MOV      Ran_data6,B
  LCALL    Ran_num
  MOV      Ran_data7,B
  LCALL    Ran_num
  MOV      Ran_data8,B
  LCALL    Ran_num
  MOV      Ran_data9,B
  LCALL    Ran_num
  MOV      Ran_data10,B
  LCALL    Ran_num
  MOV      Ran_data11,B   ;随机取第12页第一个字符
  RET

;//////取数据子程序///////////////////////////////////
;------出口参数 data0,data1 (顺序数字)----------------
Font_data: MOV DPTR,#TAB_data
  MOV      A,R0
  MOV      B,#0AH
  DIV      AB
  MOVC     A,@A+DPTR
  MOV      data0,A
  MOV      A,B
  MOVC     A,@A+DPTR
  MOV      data1,A
  RET
;//////初始化定时器0////////////////////////////////
Init_tim0: MOV  TMOD,#01H
  SETB     EA
  SETB     ET0
  MOV      TH0,#3CH
  MOV      TL0,#0AFH
  SETB     TR0  
  RET

;//////定时器0中断服务程序//////////////////////////
TIM0:      
  MOV      TH0,#3CH
  MOV      TL0,#0AFH
  RETI

相关帖子

沙发
不亦心|  楼主 | 2009-10-15 23:36 | 只看该作者
;//////随机数产生子程序/////////////////////////////
;------出口参数 B (随机数)------------------------
Ran_num:   MOV A,TL0
  MOV      B,#0AH
  DIV      AB
  RET

;//////1602写指令子程序/////////////////////////////
WR_COM:    CLR RS
  CLR            RW
  CLR            E
  ACALL    DELAY60MS
  SETB     E
  RET

;//////1602写数据子程序/////////////////////////////
;------入口参数 A (要写入的数据)-------------------
WR_DATA:   
  MOV      P0,A
  SETB     RS
  CLR      RW
  CLR      E
  LCALL    DELAY60MS
  SETB     E
  RET

;//////延时子程序////////////////////////////
;------60MS延时子程序-----------------------
DELAY60MS: MOV R7,#75H
D2:        MOV R6,#0FFH
  DJNZ     R6,$
  DJNZ     R7,D2
  RET

;------600ms延时子程序----------------------
DELAY600MS: MOV R5,#0AH
D3:        LCALL    DELAY60MS
  DJNZ     R5,D3
  RET

;//////字型码表///////////////////////////////       
TAB1: DB "   Welcome to   "
      DB "Buyixin's design"
      DB "  Now-Just-go!  "
      DB "Press Play_start"
TAB2: DB "  You Choose: "
      DB "   Play again   "
TAB_data:
      DB "0123456789"
TAB_code:
      DB "~!@#$%^&*?"

;//////程序结束///////////////////////////////
  END

使用特权

评论回复
板凳
一朝成名| | 2009-10-15 23:36 | 只看该作者
随即读RAM的数~~随机

使用特权

评论回复
地板
不亦心|  楼主 | 2009-10-15 23:41 | 只看该作者
看一下全过程:
看到press play—Start时,按开始键,然后按上下翻页键找到你的那个新数据所对应的符号,然后按确认键,最后“神奇的一幕开始”显示出你刚才看的那个符号,再重新开始。

eg:你得到的新数据是16,那如果你找到的是16*,则1602就能显示出*。

使用特权

评论回复
5
程序匠人| | 2009-10-15 23:59 | 只看该作者
顶一下魔术师

使用特权

评论回复
6
hyhjjg| | 2009-10-16 08:32 | 只看该作者
楼主您有的什么模拟软件?
我自己用的是PROTEUS 7 Professional,太老了,很多元件都不支持

使用特权

评论回复
7
古道热肠| | 2009-10-16 12:02 | 只看该作者
戏法与街头的小摊,"不用说就知道您姓什么"是一样的.

使用特权

评论回复
8
不亦心|  楼主 | 2009-10-16 12:51 | 只看该作者
你这沙发抢的可真快啊。
3# 一朝成名

使用特权

评论回复
9
不亦心|  楼主 | 2009-10-16 12:52 | 只看该作者
多谢匠人的裤衩啊,\(^o^)/~ 5# 程序匠人

使用特权

评论回复
10
不亦心|  楼主 | 2009-10-16 12:53 | 只看该作者
Proteus 7.5版本。
你可以下载第三方元件库。 6# hyhjjg

使用特权

评论回复
11
icmap| | 2009-10-16 14:37 | 只看该作者
手动为每一个变量指定地址,够麻烦的。

使用特权

评论回复
12
大道至简| | 2009-10-16 14:54 | 只看该作者
晕倒,这种纯粹的算法软件还要用asm来写吗?

使用特权

评论回复
13
不亦心|  楼主 | 2009-10-16 17:06 | 只看该作者
给个比较好的随机数产生方法呗。

顺便问一下icmap,怎么不用手动给变量分配地址啊???请赐教,谢谢。

使用特权

评论回复
14
mohanwei| | 2009-10-16 17:28 | 只看该作者
srand(read_ADC());//喂种,一次就够了
num=rand();//以后就不停调用rand()

至于想知道这个序列怎么产生的,看rand()的源码,往往也就是1行表达式

使用特权

评论回复
15
不亦心|  楼主 | 2009-10-16 17:46 | 只看该作者
这个貌似是C吧
不过还是谢谢。 15# mohanwei

使用特权

评论回复
16
ningling_21| | 2009-10-17 07:59 | 只看该作者
Q,很Q...

使用特权

评论回复
17
爱学小生| | 2009-10-17 08:06 | 只看该作者
沙发

使用特权

评论回复
18
icmap| | 2009-10-17 14:04 | 只看该作者
51 汇编变量、常量定义方法:
(Keil 汇编器和万利汇编器都支持此方法)
(还需要定义数据段,否则不能区分变量所在的段,如 DATA、IDATA、XDATA等)
1:定义字节变量用 ds 关键字,语法为:
    变量名  ds  分配的字节数
2:定义位变量用 dbit 关键字,语法为:
    位变量名  dbit 分配的位数
3:定义特殊功能寄存器(SFR)用 data 关键字,语法为:
    寄存器名 data 寄存器地址
4:定义可位寻址的特殊功能寄存器中的位用 bit 关键字,语法为:
    位名 bit 位地址
5:常量定义用 equ 关键字,语法为:
    常量名 equ 常数

使用特权

评论回复
19
不亦心|  楼主 | 2009-10-17 16:24 | 只看该作者
非常感谢,学习了。
我一直都没看过keil的使用手册,伪指令就这么一路用下来。
再次感谢。
不知可否在指教一下随机数的产生方法。

19# icmap

使用特权

评论回复
20
mohanwei| | 2009-10-18 12:14 | 只看该作者
笨啊,C编译通过了,点一下反汇编窗口,把汇编代码复制一下不就结了……

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2993

主题

10032

帖子

212

粉丝