其他分享
首页 > 其他分享> > 试验四 实验四 LC-3简单游戏设计(Nim游戏)

试验四 实验四 LC-3简单游戏设计(Nim游戏)

作者:互联网

试验四 实验四 LC-3简单游戏设计(Nim游戏)

一、实验内容:

本次实验对Nim游戏做了一些小的改变,具体如下:游戏界面由三行组成,计数器类型为石子,其中A行包含3个石子,B行包含5个石子,C行包含8个石子。
规则如下:
1. 每个玩家轮流从某一行中移除一个或多个石子。
2. 一个玩家不能在一个回合中从多个行中移除石子。
3. 当某个玩家从游戏界面上移除最后一个石子时,此时游戏结束,该玩家战败。

二、实验要求:

  1. 在游戏开始时,你应该显示游戏界面的初始化状态。具体包括:在每行石子的前面,你应该先输出行的名称,例如“ROW A”。你应该使用ASCII字符小写字母“o”(ASCII码 x006F)来表示石子。游戏界面的初始化状态应该如下:
     ROW A: ooo
     ROW B: ooooo
     ROW C: oooooooo
  1. 游戏总是从玩家1先开始,之后玩家1和玩家2轮流进行。在每一个回合开始时,你应该输出轮到哪一个玩家开始,并提示玩家进行操作。例如,对于玩家1,应该有如下显示:
	Player 1,choose a row and number of rocks: 
  1. 为了指定要移除哪一行中的多少石子,玩家应该输入一个字母后跟一个数字(输入结束后不需要按Enter键),其中字母(A,B或C)指定行,数字(从1到所选行中石子的数量)指定要移除的石子的数量。你的程序必须要确保玩家从有效的行中移除有效数量的石子,如果玩家输入无效,你应该输出错误提示信息并提示该玩家再次进行输入。
    例如:如果轮到玩家1
	    Player 1, choose a row and number of rocks: D4
		Invalid move. Try again.
		Player 1, choose a row and number of rocks: A9
		Invalid move. Try again.
		Player 1, choose a row and number of rocks: A*
		Invalid move. Try again.
		Player 1, choose a row and number of rocks: &4
		Invalid move. Try again.
		Player 1, choose a row and number of rocks: 

你的程序应保持提示玩家,直到玩家选择有效的输入为止。确保你的程序能够回显玩家的输入到屏幕上,当回显玩家的输入后,此时应该输出一个换行符(ASCII码x000A)使光标指向下一行

  1. 玩家选择有效的输入后,你应该检查获胜者。如果有一个玩家获胜,你应该显示相应的输出来表明该玩家获胜。如果没有胜利者,你的程序应该更新游戏界面中每行石子的数量,重新显示更新的游戏界面,并轮到下一个玩家继续。
  2. 当某个玩家从游戏界面上移除最后一个石子时,游戏结束。此时,你的程序应该显示获胜者然后停止。例如,如果玩家2移除了最后一个石子,你的程序应该输出一下内容:
	Player 1 Wins.

三、实验设计思路:

  1. 编写主程序,调用子程序print,实现游戏界面的输出
  2. 调用子程序Cin1,提示玩家1输入,并进行判断在子程序里判断输入是否合法,合法就更新游戏界面,不合法提示再输入;
  3. 返回主程序判断是否有人赢了,没有的话游戏继续,轮到玩家2输入,流程和玩家1一致;
  4. 有人赢了,输出赢的人,游戏结束。如果没人赢,就继续循环步骤2、3直到有人赢
  5. 程序中寄存器的作用:
	R0:用于字符串的输入和输出
	R1,R2,R3:分别存储A、B、C行的石头数
	R4:用于判断字符和数字是否输入正确,进行计算
	R5、R6:分别存储输入的字母和数字的ASCII码
	R7:返回主程序以及参与判断是否胜利的计算

四、实验步骤

(一)主程序编写

  1. 程序从x3000开始,开始编写主程序:先初始化R1,R2,R3的值,表示A、B、C行的值,R5、R6分别存储输入的字母和数字的ASCII码在这里插入图片描述
  2. 调用子程序print,实现游戏界面的输出
  3. 调用子程序Cin1,提示玩家1输入,并进行判断在子程序里判断输入是否合法,合法就更新游戏界面,不合法提示再输入;
  4. 返回主程序判断是否有人赢了,如果winnerA存的是1,玩家2胜利,没有的话游戏继续,轮到玩家2输入,流程和玩家1一致;
  5. 输出胜利者是谁,游戏结束
continue JSR Print				;调用子程序Print:输出游戏盘面
		 JSR Cin1				;调用子程序Cin:
		 LD R4,winnerA			;把地址winnerA的内容存入R4,判断是否有人赢了
		 ADD R4,R4,#-1			;R4等于1,则玩家2胜
		 BRz winner2			

		
		JSR Print				;输出界面
		JSR Cin2				;提示玩家2输入并判断输入是否合法
		LD R4,winnerB			;
		ADD R4,R4,#-2			;R4等于2,则玩家1胜
		BRz winner1			
		
		BRnzp continue			;如果没有分出胜负,则继续游戏
		
winner1 	LD R0,chanline		;把换行符传入R0
			OUT					;输出换行
			LEA R0,p1win			
			PUTS				;输出字符串
			BRnzp end			;
winner2 	LD R0,chanline		;把换行符传入R0
			OUT					;输出换行
			LEA R0,p2win			
			PUTS				;输出字符串
			BRnzp end			;
end			HALT				;		
  1. 主程序的数据区
char .fill x41					;存储输入的字符的ASCII码
num .fill #0					;存储输入数字的ASCII码
p1win .STRINGZ "Player1 Wins."
p2win .STRINGZ "Player2 Wins."
winnerA .fill #0
winnerB .fill #0
chanline .fill x000A	

(二)编写子程序Print:用于输出游戏页面

  1. 首先保存R7,将R1、R2、R3作为循环计数器,分别输出所在行的石头数o
  2. 然后换行,恢复R7,返回主程序
;子程序:Print,输出游戏盘面

Print	ST R7,SaveR7			;保存R7,放置无法返回主程序
;输出行A
		LD R0,chanline			;把换行符传入R0
		OUT						;输出换行
		LEA R4,rowA			
		ADD R0,R4,#0			
		PUTS					;输出“ROW A:"
		LD R0,Ochar				;将字符o的ASCII码存入R0

		ADD R4,R1,#0			;将行A的石头数传给R4,让它作为计数器输出
againA	BRz RB					;如果R4等于0,跳转到输出行B
		OUT						;输出石头‘o'
		ADD R4,R4,#-1			;循环次数减一
		BRnzp againA			;

;输出行B
RB		LD R0,chanline			;把换行符传入R0
		OUT						;输出换行
		LEA R4,rowB				
		ADD R0,R4,#0			
		PUTS					;输出“ROW B:"
		LD R0,Ochar				;将字符o的ASCII码存入R0
		ADD R4,R2,#0			;将行B的石头数传给R4,让它作为计数器输出
againB	BRz RC					;如果R4等于0,跳转到输出行C
		OUT						;输出石头‘o'
		ADD R4,R4,#-1			;循环次数减一
		BRnzp againB			;

;输出行C
RC		LD R0,chanline			;把换行符传入R0
		OUT						;输出换行
		LEA R4,rowC				;
		ADD R0,R4,#0			;
		PUTS					;输出“ROW C:"
		LD R0,Ochar				;将字符o的ASCII码存入R0
		ADD R4,R3,#0			;将行C的石头数传给R4,让它作为计数器输出
againC		BRz Next			;如果R4等于0,跳转到Next
		OUT						;输出石头‘o'
		ADD R4,R4,#-1			;循环次数减一
		BRnzp againC			;
Next	LD R0,chanline			;把换行符传入R0
		OUT						;输出换行
		LD R7,SaveR7			;恢复R7
		RET						;返回主程序

Ochar	.fill x006F				;石头'o'
SaveR7  .fill #0			
rowA	.STRINGZ "ROW A:"		
rowB	.STRINGZ "ROW B:"		
rowC	.STRINGZ "ROW C:"		

(三)编写子程序Cin1:

  1. 首先保存R7,初始化winnerA标志为0,调用系统程序输入字符并回显,把输入的字母和数字字符(将字符转化成整型)的ASCII码存入R5、R6中
;子程序Cin1:提示输入以及判断是否合法
Cin1	ST R7,SaveR7			;保存R7,放置无法返回主程序
		AND R4,R4,#0			; 
		ST R4,winnerA			;每次输入前保证winnerA这个标志为0,如果回去是1,说明就有人赢了
;输出提示语以及输入
Again1	LEA R0,play1		
		PUTS					;输出提示输入语“Player1,choose a row and ....."
		GETC					;输入字母存在R0中
		OUT						;回显
		ADD R5,R0,#0			;将输入的字母ASCII码赋给R5
		GETC					;输入数字存在R0中
		OUT						;回显
		LD R6,NumASC			;将字符'0'的ASCII码的相反数赋给R6
		ADD R6,R0,R6			;将输入的字符型数字转化为整型数字(如'2'-'0'=2)
		LD R0,chanline			;把换行符传入R0
		OUT						;输出换行

  1. 对输入的字符进行判断:不等于A、B、C的都是不合法的,先让R5减去字符A的ASCII码,结果存入R4,如果结果小于0就不合法,说明输入的字符比A小,R4再减去2,如果大于0,也不合法,说明输入的字符比C大
;对输入的字符和数字进行判断
		ADD R6,R6,#0		
		BRn error2			;如果输入的数字小于0,报错
		LD R4,NegofA		;将-A的	ASCIII码存入R4
		ADD R4,R5,R4		;将将输入的字母ASCII码减去A的,使得字母A,B,C对应数字0,1,2都>=0
		BRn error1			;如果R4小于0,说明输入的字符小于A,无效
		ADD R4,R4,#-2		;现在字母A,B,C对应数字-1,-2,0都<=0
		BRp error1			;如果R4大于0,说明输入的字符大于C,无效
		BRnzp right1		;如果上面都没跳转,说明输入的字符有效

error1	LEA R0,Tagain		
		PUTS				;字符输入错误,输出提示语:Invalid move.Try again.
		LD R0,chanline		;把换行符传入R0
		OUT					;输出换行
		BRnzp Again1		;重新输入

  1. 对输入的数字是否有效进行判断:对行A:如果有效,更新完之后,还要判断是否有人赢了,如果该行为0,且其他行数的石头数为0,说明该玩家移走的是最后一个石头,战败,winnerA置为1
;字符输入正确,开始对输入的数字进行判断
right1		ADD R4,R6,#0		
		NOT R4,R4			
		ADD R4,R4,#1			;-R4,便于判断该数字是否所在行的石头数
		LD R0,NegofB		
		ADD R0,R5,R0			;将输入的字母ASCII码减去B的,使得字母A,B,C对应数字-1,0,1
;判断行A
		BRzp RowB				;如果R0>=0,说明输入的不是A,进行下一个判断,是否为行B
;如果输入的是行A,进行比较石头数
		ADD R7,R1,R4			;存储修改后的石头数
		BRn error2				;小于0,说明输入的石头数大于行A的石头数,报错
		ADD R1,R7,#0			;输入正确的话,更新行A的石头数
		BRz win111				;如果更新后石头数R1等于0,跳转
		BRnzp over1				;
win111	ADD R7,R2,R3			;R7=R2+R3,如果和为0,说明最后一个石头已经被拿走
		BRz win112				
		BRnzp over1				;和不为0,界面上还有石头,返回

win112	AND R4,R4,#0		
		ADD R4,R4,#1		
		ST R4,winnerA			;如果更新后石头数为0且其他两行石头数为0,则玩家2胜利,存储到内存里
		BRnzp over1			
  1. 同理对行B、行C进行类似的判断,此处省略代码(详见完整代码)
  2. 最后错误的输出提示语,恢复R7,返回主程序
error2	LEA R0,Tagain		
		PUTS				;字符输入错误,输出提示语:Invalid move.Try again.
		LD R0,chanline		;把换行符传入R0
		OUT					;输出换行
		BRnzp Again1		;重新输入

over1	LD R7,SaveR7		;恢复R7
		RET					

(四)编写子程序Cin2:

基本与子程序Cin1一致,区别在于:对输入的数字进行判断时,判断有人战败时,将winnerB置为2,其他方法完全一样,具体代码不再赘述(详见完整代码)

(五)通过LC-3仿真器调试和运行相关程序

  1. 打开simulate.exe,导入上述的.obj文件,进行运行和调试
  2. 运行程序:在halt指令所在行前双击,设置断点,点击运行程序run program键,运行结果:主界面如下在这里插入图片描述输入B2,结果运行如下:在这里插入图片描述
    输入A1,C6,G1,结果运行如下:在这里插入图片描述
    继续输入,最后输入A1,输出Player2 wins,结果正确
    在这里插入图片描述

五、实验结论

  1. 整体上较好的实现本次实验目的,完成了对Nim这一简单游戏的设计。
  2. 通过本次实验,我更加熟悉地掌握了LC-3Edit和simulate的使用方法,对于汇编代码的使用和理解更为深刻。
  3. 另外,在本次实验中,学会了使用子程序来简化汇编代码,尤其是那些需要反复执行的操作,可以通过编写多个子程序,使得主程序简明易懂,值得注意的是,编写子程序时要注意寄存器的保存和恢复,尤其是R7这个隐式的寄存器,才能正常返回主程序。
  4. 总体来说,通过此次实验,我熟练地掌握了子程序的编写和调用,动手实践,也让我对其中的细节更加关注,及时发现问题,解决问题,收益匪浅。

六、实验完整代码(仅供参考)

;此程序实现功能:
;实现了Nim游戏的简单设计
;
;
;主程序:
		.ORIG x3000				;程序从x3000开始
		AND R1,R1,#0			;
		AND R2,R2,#0			;
		AND R3,R3,#0			;
		ADD R1,R1,#3			;R1表示行A石头个数
		ADD R2,R2,#5			;R2表示行B石头个数
		ADD R3,R3,#8			;R3表示行C石头个数

		LD R5,char			;R5存储输入的字符的ASCII码
		LD R6,num			;R6存储输入数字的ASCII码
continue JSR Print			;调用子程序Print:输出游戏盘面
		JSR Cin1			;调用子程序Cin:提示玩家1输入行号和数字,并进行检查输入是否合法
		LD R4,winnerA		;把地址winnerA的内容存入R4,判断是否有人赢了
		ADD R4,R4,#-1		;R4等于1,则玩家2胜
		BRz winner2			;

		
		JSR Print			;输出界面
		JSR Cin2			;提示玩家2输入并判断输入是否合法
		LD R4,winnerB			
		ADD R4,R4,#-2		;R4等于2,则玩家1胜
		BRz winner1			;
		
		BRnzp continue		;如果没有分出胜负,则继续游戏
winner1 LD R0,chanline		;把换行符传入R0
		OUT					;输出换行
		LEA R0,p1win			
		PUTS				;输出字符串
		BRnzp end			;
winner2 LD R0,chanline		;把换行符传入R0
		OUT					;输出换行
		LEA R0,p2win			
		PUTS				;输出字符串
		BRnzp end			;
end		HALT				;

char .fill x41				;存储输入的字符的ASCII码
num .fill #0				;存储输入数字的ASCII码
p1win .STRINGZ "Player1 Wins."
p2win .STRINGZ "Player2 Wins."
winnerA .fill #0
winnerB .fill #0
chanline .fill x000A	
;
;
;-----------------------------------------------------------------------
;子程序:Print,输出游戏盘面
Print	ST R7,SaveR7			;保存R7,放置无法返回主程序
;输出行A
		LD R0,chanline			;把换行符传入R0
		OUT						;输出换行
		LEA R4,rowA			
		ADD R0,R4,#0			
		PUTS					;输出“ROW A:"
		LD R0,Ochar				;将字符o的ASCII码存入R0

		ADD R4,R1,#0			;将行A的石头数传给R4,让它作为计数器输出
againA	BRz RB					;如果R4等于0,跳转到输出行B
		OUT						;输出石头‘o'
		ADD R4,R4,#-1			;循环次数减一
		BRnzp againA			;

;输出行B
RB		LD R0,chanline			;把换行符传入R0
		OUT						;输出换行
		LEA R4,rowB				
		ADD R0,R4,#0			
		PUTS					;输出“ROW B:"
		LD R0,Ochar				;将字符o的ASCII码存入R0
		ADD R4,R2,#0			;将行B的石头数传给R4,让它作为计数器输出
againB	BRz RC					;如果R4等于0,跳转到输出行C
		OUT						;输出石头‘o'
		ADD R4,R4,#-1			;循环次数减一
		BRnzp againB			;

;输出行C
RC		LD R0,chanline			;把换行符传入R0
		OUT						;输出换行
		LEA R4,rowC			
		ADD R0,R4,#0			;
		PUTS					;输出“ROW C:"
		LD R0,Ochar				;将字符o的ASCII码存入R0
		ADD R4,R3,#0			;将行C的石头数传给R4,让它作为计数器输出
againC	BRz Next				;如果R4等于0,跳转到Next
		OUT						;输出石头‘o'
		ADD R4,R4,#-1			;循环次数减一
		BRnzp againC			;
Next	LD R0,chanline			;把换行符传入R0
		OUT						;输出换行
		LD R7,SaveR7			;恢复R7
		RET						;返回主程序

Ochar	.fill x006F				;石头'o'
SaveR7  .fill #0			
rowA	.STRINGZ "ROW A:"		
rowB	.STRINGZ "ROW B:"		
rowC	.STRINGZ "ROW C:"		

;-----------------------------------------------------------------------
;子程序Cin1:提示输入以及判断是否合法
Cin1	ST R7,SaveR7			;保存R7,放置无法返回主程序
		AND R4,R4,#0			; 
		ST R4,winnerA			;每次输入前保证winnerA这个标志为0,如果回去是1,说明就有人赢了
;输出提示语以及输入
Again1	LEA R0,play1		
		PUTS				;输出提示输入语“Player1,choose a row and ....."
		GETC				;输入字母存在R0中
		OUT					;回显
		ADD R5,R0,#0		;将输入的字母ASCII码赋给R5
		GETC				;输入数字存在R0中
		OUT					;回显
		LD R6,NumASC		;将字符'0'的ASCII码的相反数赋给R6
		ADD R6,R0,R6		;将输入的字符型数字转化为整型数字(如'2'-'0'=2)
		LD R0,chanline		;把换行符传入R0
		OUT					;输出换行

;对输入的字符和数字进行判断
		ADD R6,R6,#0		
		BRn error2			;如果输入的数字小于0,报错
		LD R4,NegofA		;将-A的	ASCIII码存入R4
		ADD R4,R5,R4		;将将输入的字母ASCII码减去A的,使得字母A,B,C对应数字0,1,2都>=0
		BRn error1			;如果R4小于0,说明输入的字符小于A,无效
		ADD R4,R4,#-2		;现在字母A,B,C对应数字-1,-2,0都<=0
		BRp error1			;如果R4大于0,说明输入的字符大于C,无效
		BRnzp right1		;如果上面都没跳转,说明输入的字符有效

error1	LEA R0,Tagain		
		PUTS				;字符输入错误,输出提示语:Invalid move.Try again.
		LD R0,chanline		;把换行符传入R0
		OUT					;输出换行
		BRnzp Again1		;重新输入

;字符输入正确,开始对输入的数字进行判断
right1	ADD R4,R6,#0		
		NOT R4,R4			
		ADD R4,R4,#1			;-R4,便于判断该数字是否所在行的石头数
		LD R0,NegofB		
		ADD R0,R5,R0			;将输入的字母ASCII码减去B的,使得字母A,B,C对应数字-1,0,1
;判断行A
		BRzp RowB				;如果R0>=0,说明输入的不是A,进行下一个判断,是否为行B
;如果输入的是行A,进行比较石头数
		ADD R7,R1,R4			;存储修改后的石头数
		BRn error2				;小于0,说明输入的石头数大于行A的石头数,报错
		ADD R1,R7,#0			;输入正确的话,更新行A的石头数
		BRz win111				;如果更新后石头数R1等于0,跳转
		BRnzp over1			
win111	ADD R7,R2,R3			;R7=R2+R3,如果和为0,说明最后一个石头已经被拿走
		BRz win112			
		BRnzp over1				;和不为0,界面上还有石头,返回

win112	AND R4,R4,#0		
		ADD R4,R4,#1		
		ST R4,winnerA			;如果更新后石头数为0且其他两行石头数为0,则玩家2胜利,存储到内存里
		BRnzp over1			


RowB	ADD R0,R0,#0		
		BRp RowC				;如果R0>0,说明输入的不是B,进行下一个判断,是否为行C
;如果输入的是行B,进行比较石头数
		ADD R7,R2,R4			;存储修改后的石头数
		BRn error2				;小于0,说明输入的石头数大于行A的石头数,报错
		ADD R2,R7,#0			;输入正确的话,更新行B的石头数
		BRz win121				;如果更新后石头数R2等于0,跳转
		BRnzp over1				;
win121	ADD R7,R1,R3			;R7=R1+R3,如果和为0,说明最后一个石头已经被拿走
		BRz win122				;
		BRnzp over1				;和不为0,界面上还有石头,返回

win122	AND R4,R4,#0		
		ADD R4,R4,#1		
		ST R4,winnerA			;如果更新后石头数为0且其他两行石头数为0,则玩家2胜利,存储到内存里
		BRnzp over1			



;如果输入的是行C,进行比较石头数
RowC	ADD R7,R3,R4			;存储修改后的石头数
		BRn error2				;小于0,说明输入的石头数大于行C的石头数,报错
		ADD R3,R7,#0			;输入正确的话,更新行C的石头数
		BRz win131				;如果更新后石头数R2等于0,跳转
		BRnzp over1				;
win131	ADD R7,R1,R2			;R7=R1+R2,如果和为0,说明最后一个石头已经被拿走
		BRz win132			
		BRnzp over1				;和不为0,界面上还有石头,返回

win132	AND R4,R4,#0		
		ADD R4,R4,#1		
		ST R4,winnerA			;如果更新后石头数为0且其他两行石头数为0,则玩家2胜利,存储到内存里
		BRnzp over1			

error2		LEA R0,Tagain		
		PUTS					;字符输入错误,输出提示语:Invalid move.Try again.
		LD R0,chanline			;把换行符传入R0
		OUT						;输出换行
		BRnzp Again1			;重新输入

over1	LD R7,SaveR7			;恢复R7
		RET					
;-----------------------------------------------------------------------
Cin2	ST R7,SaveR7			;保存R7,放置无法返回主程序
		AND R4,R4,#0			; 
		ST R4,winnerB			;每次输入前保证winnerB这个标志为0,如果回去是2,说明就有人赢了
;
;输出提示语以及输入
Again2	LEA R0,play2			;
		PUTS					;输出提示输入语“Player2,choose a row and ....."
		GETC					;输入字母存在R0中
		OUT						;回显
		ADD R5,R0,#0			;将输入的字母ASCII码赋给R5
		GETC					;输入数字存在R0中
		OUT						;回显
		LD R6,NumASC			;将字符'0'的ASCII码的相反数赋给R6
		ADD R6,R0,R6			;将输入的字符型数字转化为整型数字(如'2'-'0'=2)
		LD R0,chanline			;把换行符传入R0
		OUT						;输出换行

;对输入的字符和数字进行判断
		ADD R6,R6,#0		
		BRn error4				;如果输入的数字小于0,报错
		LD R4,NegofA			;将-A的	ASCIII码存入R4
		ADD R4,R5,R4			;将将输入的字母ASCII码减去A的,使得字母A,B,C对应数字0,1,2都>=0
		BRn error3				;如果R4小于0,说明输入的字符小于A,无效
		ADD R4,R4,#-2			;现在字母A,B,C对应数字-1,-2,0都<=0
		BRp error1				;如果R4大于0,说明输入的字符大于C,无效
		BRnzp right2			;如果上面都没跳转,说明输入的字符有效

error3	LEA R0,Tagain		
		PUTS					;字符输入错误,输出提示语:Invalid move.Try again.
		LD R0,chanline			;把换行符传入R0
		OUT						;输出换行
		BRnzp Again2			;重新输入

;字符输入正确,开始对输入的数字进行判断
right2	ADD R4,R6,#0		
		NOT R4,R4			
		ADD R4,R4,#1			;-R4,便于判断该数字是否所在行的石头数
		LD R0,NegofB			;
		ADD R0,R5,R0			;将输入的字母ASCII码减去B的,使得字母A,B,C对应数字-1,0,1
;判断行A
		BRzp RowB2				;如果R0>=0,说明输入的不是A,进行下一个判断,是否为行B
;如果输入的是行A,进行比较石头数
		ADD R7,R1,R4			;存储修改后的石头数
		BRn error4				;小于0,说明输入的石头数大于行A的石头数,报错
		ADD R1,R7,#0			;输入正确的话,更新行A的石头数
		BRz win211				;如果更新后石头数R1等于0,跳转
		BRnzp over2				;
win211	ADD R7,R2,R3			;R7=R2+R3,如果和为0,说明最后一个石头已经被拿走
		BRz win212			;
		BRnzp over2			;和不为0,界面上还有石头,返回

win212		AND R4,R4,#0		
		ADD R4,R4,#2		
		ST R4,winnerB		;如果更新后石头数为0且其他两行石头数为0,则玩家1胜利,存储到内存里
		BRnzp over2			;

RowB2		ADD R0,R0,#0		
		BRp RowC2			;如果R0>0,说明输入的不是B,进行下一个判断,是否为行C
;如果输入的是行B,进行比较石头数
		ADD R7,R2,R4		;存储修改后的石头数
		BRn error4			;小于0,说明输入的石头数大于行A的石头数,报错
		ADD R2,R7,#0		;输入正确的话,更新行B的石头数
		BRz win221			;如果更新后石头数R2等于0,跳转
		BRnzp over2			;
win221	ADD R7,R1,R3		;R7=R1+R3,如果和为0,说明最后一个石头已经被拿走
		BRz win222			;
		BRnzp over2			;和不为0,界面上还有石头,返回

win222	AND R4,R4,#0		
		ADD R4,R4,#2		
		ST R4,winnerB		;如果更新后石头数为0且其他两行石头数为0,则玩家1胜利,存储到内存里
		BRnzp over2			;

;如果输入的是行C,进行比较石头数
RowC2	ADD R7,R3,R4		;存储修改后的石头数
		BRn error4			;小于0,说明输入的石头数大于行C的石头数,报错
		ADD R3,R7,#0		;输入正确的话,更新行C的石头数
		BRz win231			;如果更新后石头数R2等于0,跳转
		BRnzp over2			;
win231	ADD R7,R1,R2	 	;R7=R2+R3,如果和为0,说明最后一个石头已经被拿走
		BRz win232			;
		BRnzp over2			;和不为0,界面上还有石头,返回

win232	AND R4,R4,#0		
		ADD R4,R4,#2		
		ST R4,winnerB		;如果更新后石头数为0且其他两行石头数为0,则玩家1胜利,存储到内存里
		BRnzp over2			;
error4	LEA R0,Tagain		
		PUTS				;字符输入错误,输出提示语:Invalid move.Try again.
		LD R0,chanline		;把换行符传入R0
		OUT					;输出换行
		BRnzp Again2		;重新输入
over2	LD R7,SaveR7		;恢复R7
		RET					

NegofA	.fill xFFBF			;存储-A的ASCII码
NegofB	.fill xFFBE			;存储-B的ASCII码
NumASC  .fill xFFD0			;字符'0'的ASCII码的相反数
Tagain	.STRINGZ "Invalid move.Try again."
play1	.STRINGZ "Player1,choose a row and number of rocks."
play2	.STRINGZ "Player2,choose a row and number of rocks."

	.END

标签:R4,R7,R0,LC,Nim,石头,ADD,输入,游戏
来源: https://blog.csdn.net/m0_55937906/article/details/116805546