我正在使用Easy 68K模拟器创建一个简单的黑色插孔游戏,需要使用随机数来分配卡片。我的卡必须在2到11的范围内。我似乎每次都得到相同的数字,并且它不在我期望的范围内。我的卡值最终需要在D3中,所以我有以下随机数码:
CLR.L D0
CLR.L D3
MOVE.B #8, D0 ;Access time
TRAP #15
AND.L #$5FFFFF,D1 ;prevent overflow in divu
DIVU #10, D1
SWAP D1
ADDQ.W #1, D1
MOVE D1, D3
我通过修改此网站上的代码来实现:https://notendur.hi.is/voe1/3.%20onn/Tolvuhogun/EASy68K/Examples/tutorial3.X68
我希望能找到2到11号的帮助。我一直在网上搜索几个小时。我知道我需要通过使用Move.B#8,D0来获取时间,但除此之外,我还没有取得多大进展。非常感谢任何帮助!
答案 0 :(得分:5)
在AND.L
中使用的掩码(“防止在divu中溢出”)仅对除法有效 - 你需要用0x7FFFF
掩码除以10。
为什么:
0xFFFFFFFF / #100 = 0x28f5c28 - too big for a single word!
0x5FFFFF / #100 = 0xF5C2 - that fits
0x5FFFFF / #10 = 0x99999 - too big for a single word!
0x7FFFF / #10 = 0xCCCC - that fits
此外,您拥有的代码将为您提供1到10之间的数字(0-9 + 1)。如果您想要2到11,则必须添加2而不是1。
这是一个更高级的随机数生成器,借鉴了Mac OS QuickDraw源代码。请注意,您可能需要稍微翻译一下语法(它是在25年前写的!)和/或修改它加载和存储其种子的方式。
;--------------------------------------------------------------
;
; FUNCTION Random: INTEGER;
;
; returns a signed 16 bit number, and updates unsigned 32 bit randSeed.
;
; recursion is randSeed := (randSeed * 16807) MOD 2147483647.
;
; See paper by Linus Schrage, A More Portable Fortran Random Number Generator
; ACM Trans Math Software Vol 5, No. 2, June 1979, Pages 132-138.
;
; Clobbers D0-D2, A0
;
;
; GET LO 16 BITS OF SEED AND FORM LO PRODUCT
; xalo := A * LoWord(seed)
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE #16807,D0 ;GET A = 7^5
MOVE D0,D2 ;GET A = 7^5
MULU RANDSEED+2(A0),D0 ;CALC LO PRODUCT = XALO
;
; FORM 31 HIGHEST BITS OF LO PRODUCT
; fhi:=HiWord(seed) * ORD4(a) + HiWord(xalo);
;
MOVE.L D0,D1 ;COPY xalo
CLR.W D1
SWAP D1 ;GET HiWord(xalo) as a long
MULU RANDSEED(A0),D2 ;MULT BY HiWord(seed)
ADD.L D1,D2 ;ADD LEFTLO = FHI
;
; GET OVERFLOW PAST 31ST BIT OF FULL PRODUCT
; k:=fhi DIV 32768;
;
MOVE.L D2,D1 ;COPY FHI
ADD.L D1,D1 ;CALC 2 TIMES FHI
CLR.W D1
SWAP D1 ;CALC FHI SHIFTED RIGHT 15 FOR K
;
; ASSEMBLE ALL THE PARTS AND PRE-SUBTRACT P
; seed:=((BitAnd(XALO,$0000FFFF) - P) + BitAnd(fhi,$00007FFF) * b16) + K;
;
AND.L #$0000FFFF,D0 ;GET LO WORD XALO
SUB.L #$7FFFFFFF,D0 ;SUBTRACT P = 2^31-1
AND.L #$00007FFF,D2 ;BitAnd(fhi,$00007FFF)
SWAP D2 ;TIMES 64K
ADD.L D1,D2 ;PLUS K
ADD.L D2,D0 ;CALC TOTAL
;
; IF seed < 0 THEN seed:=seed+p;
;
BPL.S UPDATE
ADD.L #$7FFFFFFF,D0
UPDATE MOVE.L D0,RANDSEED(A0) ;UPDATE SEED
CMP.W #$8000,D0 ;IS NUMBER -32768 ?
BNE.S NUMOK ;NO, CONTINUE
CLR D0 ;YES, RETURN ZERO INSTEAD
NUMOK MOVE.W D0,4(SP) ;RETURN LO WORD AS RESULT
RTS
答案 1 :(得分:0)
您需要根据间隔(最小和最大)使用正确的掩码,此代码将解决所有问题,它带有两个参数:D5中的最小值和D6中的最大值,还使用D0,D7和A1。
RAND_GEN
SUB D5,D6 ;You should give Min in D5 and Max in D6
MOVE D6,D7
ADDI #1,D6
MULU #$FFFF,D7
LEA SEED,A1
MOVE.B #8,d0
TRAP #15
ADD (A1),D1
MULU #$FFFF,D1
EOR.L #$F321F23A,D1
MOVE D1,(A1)
AND.L D7,D1 ;PREVENT OVERFLOW FOR (Max-Min)
DIVU D6,D1 ;time count / (Max-Min)
SWAP D1 ;swap upper and lower words of D1 to put remainder in low word
ADD D5,d1 ;D1.W contains number in the range of (Min,Max)
RTS
* Put variables and constants here
SEED
DC.W 1
默认情况下,SEED在程序开始时为1,并在每次RAND_GEN调用后自动更新,您也可以随时对其进行更改。
在EASY68K上测试。