【计算机系统1】实验4、5:用LC-3写一个Nim游戏(无子程序)

(因为不会用子程序所以直接写了)

一、Nim游戏规则

Nim是一个简单的双人游戏,可能起源于中国。游戏中使用的计数器类型有很多种类,如石头、火柴、苹果等。游戏界面被划分为很多行,每行中有数量不等的计数器,如图1所示:

行号 计数器数量

1 ooo
2 ooooo
… …
n oooooooooooooo…

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


实验要求

⑴ 在游戏开始时,你应该显示游戏界面的初始化状态。具体包括:在每行石头的前面,你应该先输出行的名称,例如“ROW A”。你应该使用ASCII字符小写字母“o”(ASCII码 x006F)来表示石头。游戏界面的初始化状态应该如下:

ROW A: ooo
ROW B: ooooo
ROW C: oooooooo

⑵ 游戏总是从玩家1先开始,之后玩家1和玩家2轮流进行。在每一个回合开始时,你应该输出轮到哪一个玩家开始,并提示玩家进行操作。例如,对于玩家1,应该有如下显示:
Player 1,choose a row and number of rocks:

⑶ 为了指定要移除哪一行中的多少石头,玩家应该输入一个字母后跟一个数字(输入结束后不需要按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)使光标指向下一行。

⑷ 玩家选择有效的输入后,你应该检查获胜者。如果有一个玩家获胜,你应该显示相应的输出来表明该玩家获胜。如果没有胜利者,你的程序应该更新游戏界面中每行石头的数量,重新显示更新的游戏界面,并轮到下一个玩家继续。

⑸ 当某个玩家从游戏界面上移除最后的石头时,游戏结束。此时,你的程序应该显示获胜者然后停止。例如,如果玩家2移除了最后的石头,你的程序应该输出一下内容:
Player 2 Wins.


二、实验步骤与过程

由于游戏过程整体比较复杂,所以把整个流程分割成几个部分分别编写。
战术思维导图↓

在这里插入图片描述

代码展示:

在正式浏览代码之前,展示一下说明:

;Nim游戏编程
;R0:输入与输出的寄存器
;R1:表示石头数量的寄存器
;R2: 表示行动方的寄存器
;其他寄存器:用于操作

.ORIG x3000
  1. 初始化寄存器:
;初始化
AND R2,R2,#0;R2清零,说明第一次行动由p1开始
  1. 输出棋盘
;输出棋盘
pvt1
        LEA R0,HeadA;   输出a行的开头和石头数量
        PUTS;
        LD R0,Stone;
        LD R1,LineA;
Loop1	
        BRz #3;
        OUT;
        ADD R1,R1,#-1;
        BRnzp Loop1;

		LD R0,ENDL
		OUT

图中仅展示了A行的输出,B和C行代码相似,仅需将HeadA,LineA改为B和C对应的符号、Loop1分别改为别的名字即可

  1. 输入数据、合法判断
;输入和合法判断处理部分
pvt2
        ADD R2,R2,#0;   R2为0则表示轮到p1行动,为-1则表示轮到p2行动
;输入数据相关的代码
        BRn Player2 ;   判断当前棋手
Player1 LEA R0,OutP1;
        BRnzp #1;
Player2 LEA R0,OutP2;
        PUTS;
        GETC;
        OUT;
        LD R6,NegA;	将输入的行数的ascii码(ABC)对应转化为数字(012)
        ADD R6,R0,R6;
        GETC;
        OUT;
		LD R5,NegZero;	同上
		ADD R5,R0,R5;
		LD R0,ENDL;
		OUT;
;判断R5是否会小于等于0
	ADD R5,R5,#0;
	BRnz Restart;
;判断行合法
        ADD R7,R6,#-2;
        BRp Restart;    说明输入行数大于c(ASCII),直接重新输入
        ADD R7,R6,#0;   
        BRn Restart;    说明输入行数小于a(ASCII),直接重新输入
;判断石头数合法
        LEA R3,LineA;
        ADD R3,R3,R6;
        LDR R3,R3,#0;
		NOT R5,R5;
		ADD R5,R5,#1;
        ADD R4,R3,R5;
        BRn Restart;    说明输入的石头数大于了对应行的石头数,直接重新输入
		LEA R3,LineA;
		ADD R3,R3,R6
        STR R4,R3,#0;
        BRnzp pvt3;    说明输入合法,存放完数据之后就进入判断是否游戏结束阶段
  1. 非法输入折返
Restart 
        LEA R0,Invalid;
        PUTS;
        LD R0,ENDL;
        OUT;
        BRnzp pvt2;
  1. 判断游戏结束
pvt3
        AND R3,R3,#0;
        ADD R3,R3,#3;
        LD R1,LineA;    若a行数量为0则r3-=1
        BRp #1;
        ADD R3,R3,#-1;
        LD R1,LineB;    同上
        BRp #1;
        ADD R3,R3,#-1;
        LD R1,LineC;    同上
        BRp #1;
        ADD R3,R3,#-1;
        ADD R3,R3,#0;
        BRz OVER;       如果r3为0,则游戏结束
        NOT R2,R2;         否则,交换棋手,游戏继续
		LD R0,ENDL;
        OUT;            为了美观输出一下换行
        BRnzp pvt1;
  1. 游戏结束语
OVER    
        ADD R2,R2,#0;   判断获胜棋手
        BRn #2;
        LEA R0,over1;
        BRnzp #1;
        LEA R0,over2;
        PUTS;
        LD R0,ENDL;
        OUT;

        HALT

最后是符号表:

;公用符号表
LineA 	.FILL X3
LineB 	.FILL X5
LineC 	.FILL X8
ENDL  	.FILL x000A;

;pvt1输出棋盘部分的符号表
HeadA 	.STRINGZ "Row A: ";
HeadB 	.STRINGZ "Row B: ";
HeadC	.STRINGZ "Row C: ";
Stone	.FILL x006F;

;pvt2输入和合法判断处理部分的符号表
OutP1   .STRINGZ "Player 1, choose a row and number of stone:"
OutP2   .STRINGZ "Player 2, choose a row and number of stone:"
Invalid .STRINGZ "Invalid move. Try again."
NegZero .FILL xFFD0;
NegA    .FILL xFFBF;

;OVER部分用到的字符串符号表
over1   .STRINGZ "Player 1 Wins."
over2   .STRINGZ "Player 2 Wins."

.END

以上就是思路和代码的展示了

三、小结

既然这不是正式的实验报告(而是网上的文章分享),那么测试样例和实验结论啥的咱就不写了

结尾声明一下:本文章中的思路和代码仅供参考,本人仅仅初次接触汇编语言,代码的书写或有不规范,方法的运用或有不熟练,请学界大佬多多包涵与指教,请前来参考的同志在阅读文章过后更要独立思考。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Giro_6Time

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值