本帖最后由 不亦心 于 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 |