计算机系统1 实验 LC-3 Nim游戏 子程序
写在前面
今天找时间把LC-3的Nim游戏(实验四、五)给做了,浅浅地分享一下吧。
一个目录
- 写在前面
- 一、游戏背景和规则
- 二、实验要求
- 三、样例输入/输出
- 四、代码编写
- 数据存放
- 编写代码
- 五、小小总结
一、游戏背景和规则
背景:Nim是一个简单的双人游戏,可能起源于中国。游戏中使用的计数器类型有很多种类,如石头、火柴、苹果等。游戏界面被划分为很多行,每行中有数量不等的计数器,如表所示:
行号 | 计数器数量 |
---|---|
1 | ○○○ |
2 | ○○○○○○ |
··· | ··· |
n | ○○○○○○○○○ |
本次实验对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.
三、样例输入/输出
据说要和样例输出一模一样
ROW A: ooo
ROW B: ooooo
ROW C: oooooooo
Player 1, choose a row and number of rocks: B2ROW A: ooo
ROW B: ooo
ROW C: oooooooo
Player 2, choose a row and number of rocks: A1ROW A: oo
ROW B: ooo
ROW C: oooooooo
Player 1, choose a row and number of rocks: C6ROW A: oo
ROW B: ooo
ROW C: oo
Player 2, choose a row and number of rocks: G1
Invalid move. Try again.
Player 2, choose a row and number of rocks: B3ROW A: oo
ROW B:
ROW C: oo
Player 1, choose a row and number of rocks: A3
Invalid move. Try again.
Player 1, choose a row and number of rocks: C2ROW A: oo
ROW B:
ROW C:
Player 2, choose a row and number of rocks: A1ROW A: o
ROW B:
ROW C:
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: A1Player 1 Wins.
----- Halting the processor -----
四、代码编写
数据存放
1、程序从x3000开始存放
2、每行石头的数量从x3200开始存放,且以-1结尾作为结束标志,以支持非题目要求的D~Z行(属于是自找麻烦了)
编写代码
注意:
以下代码片段并非代码实际顺序。
并且子程序没有严格地保存和恢复寄存器状态,这是不对滴。
1、石头状态输出子程序:
;石头状态输出
;R1-石头数量地址,R2-数量
FUNC_DRAW ST R7,SAVER7 ;保存R7的值,因为PUTS和OUT会对其进行修改LD R1,PTR_STONES ;石头堆首地址LD R3,CHAR_ROWBASE ;'A'的ASCII码;遍历石头堆
LOOP_1 LDR R2,R1,#0 ;读取当前行石头数量BRn END_DRAW ;若数字为-1,结束输出LEA R0,STR_ROWPUTSAND R0,R0,#0ADD R0,R3,#0OUTLEA R0,STR_ROW2PUTSLD R0,CHAR_SYMBOL ;ADD R2,R2,#0 ;将CC恢复为R2;循环输出o
LOOP_2 BRz OUT_2 ;若数字R2降到0,结束当前循环OUT ADD R2,R2,#-1BRnzp LOOP_2
OUT_2 LD R0,CHAR_LFOUTADD R1,R1,#1ADD R3,R3,#1 BRnzp LOOP_1
END_DRAW LD R7,SAVER7RET
2、检查石头是否被取完:
;检查石头是否被取完了
;Output(R6):没取完(0),取完了(1)
FUN_CHECK LD R1, PTR_STONES ;R1指向石头AND R6, R6, #0ADD R6, R6, #1 ;初始化R6为1
SUB_CHECK_LOOP LDR R2, R1, #0 ;读取当前行石头数BRp SUB_CHECK_FALSE ;任意行非零则返回0BRn SUB_CHECK_END ;遇到-1,说明石头数全为0,返回1ADD R1, R1, #1BRnzp SUB_CHECK_LOOP SUB_CHECK_FALSE ADD R6, R6, #-1 ;R6置为0
SUB_CHECK_END RET
3、判断当前输入的合法性并取走石头:
;判断当前的输入是否还有剩余,若无剩余输出错误信息
;Input(PTR_ROW,PTR_CNT) Output(R6):非法输入(0),取走前一切正常(n)
FUN_HASLEFT ST R7, SAVER7 ;保存R7,因为PUTSLD R1, PTR_STONES ;R1指向首堆石头LD R2, PTR_ROWLD R3, NCHAR_AADD R2, R2, R3 ;行距离A的偏移BRn SUB_HAS_ERROR ;行号非法ADD R1, R1, R2 ;指向输入指定的行AND R6, R6, #0LDR R2, R1, #0BRnz SUB_HAS_ERROR ;剩下的石头<=0,可同时判断行号非法和当前行为0ADD R6, R6, R2 ;R6 = R2
SUB_HAS_SUB LD R2, PTR_CNT ;读取输入的数字LD R3, NCHAR_0ADD R2, R2, R3 ;ASCII -> numBRnz SUB_HAS_ERROR ;数字非法NOT R2, R2ADD R2, R2, #1 ;R2 = -R2ADD R4, R6, R2 ;R4 = 该行剩余 - 取走数量BRn SUB_HAS_ERROR ;该行剩下的石头不够STR R4, R1, #0 ;更新石头数量BRnzp SUB_HAS_END
SUB_HAS_ERROR AND R6, R6, #0 ;需要返回的0LD R0, CHAR_LFOUTLEA R0, STR_INVALIDPUTSLD R0, CHAR_LFOUT
SUB_HAS_END LD R7, SAVER7 ;载入R7RET
4、行号及数量输入:
;输入行号(ABCDEFGHIJKLMNOPQRSTUVWXYZ)
INPUT_ROW ST R7, SAVER7GETCOUTST R0, PTR_ROWLD R7, SAVER7RET;输入个数(123456789)
INPUT_CNT ST R7, SAVER7GETCOUTST R0, PTR_CNTLD R7, SAVER7RET;此处用PTR命名是因为原来是打算用LDI和STI的,后来改用LD和ST懒得改了哈哈哈
PTR_ROW .BLKW 1 ;储存输入的行号(ASCII码A~Z)
PTR_CNT .BLKW 1 ;储存输入的数字(ASCII码0~9)
PTR_PLAYER .FILL x0000 ;储存当前玩家,0为P1,1为P2
5、主程序及玩家控制:
;主程序
;FUNC_MAIN
LOOP_PLAY JSR FUNC_DRAW ;开局先输出一次石堆LD R6, PTR_PLAYERBRz FUNC_P1 ;为0就是玩家1BRp FUNC_P2 ;为1就是玩家2
PLAY_AFTER LD R0, CHAR_LFOUT ;输出换行JSR FUNC_CHANGE ;切换玩家BRnzp LOOP_PLAY ;循环就是了,跳出在玩家控制中;玩家1控制
FUNC_P1 LEA R0, STR_PLAYER1 ;输出游戏提示PUTSJSR INPUT_ROW ;输入行号JSR INPUT_CNT ;输入数量JSR FUN_HASLEFT ;进行一个的判断和取石头ADD R6, R6, #0 ;刷新CCBRnz FUNC_P1 ;非法输入,再来LD R0, CHAR_LFOUT ;为了让输出和样例一模一样JSR FUN_CHECKADD R6, R6, #0 ;刷新CCBRnz PLAY_AFTER ;R6=0,还没赢LD R0, CHAR_LF ;R6=1,赢了OUTLEA R0, STR_WIN_1PUTSBRnzp _END;玩家2控制(结构同玩家1)
FUNC_P2 LEA R0, STR_PLAYER2PUTSJSR INPUT_ROW ;输入行号JSR INPUT_CNT ;输入数量JSR FUN_HASLEFT ;进行一个的判断和取石头ADD R6, R6, #0 ;刷新CCBRnz FUNC_P2 ;非法输入,再来LD R0, CHAR_LFOUT ;为了让输出和样例一模一样JSR FUN_CHECKADD R6, R6, #0 ;刷新CCBRnz PLAY_AFTER ;R6=0,还没赢LD R0, CHAR_LF ;R6=1,赢了OUTLEA R0, STR_WIN_2PUTSBRnzp _END ;玩家切换子程序(没有用到TRAP故)
FUNC_CHANGE LD R6, PTR_PLAYERBRz SUB_ZEROADD R6, R6, #-1 ;如果是1就切0ST R6, PTR_PLAYERBRnzp SUB_CHANGE_RET
SUB_ZERO ADD R6, R6, #1 ;如果是0就切1ST R6, PTR_PLAYER
SUB_CHANGE_RET RET
完整代码如下(仅供参考,建议独立思考,所以我删掉了完整代码中的很多注释哈哈哈哈):
.ORIG x3000;主程序
;FUNC_MAIN
LOOP_PLAY JSR FUNC_DRAWLD R6, PTR_PLAYERBRz FUNC_P1BRp FUNC_P2
PLAY_AFTER LD R0, CHAR_LFOUT ;LFJSR FUNC_CHANGEBRnzp LOOP_PLAY;玩家1
FUNC_P1 LEA R0, STR_PLAYER1PUTSJSR INPUT_ROWJSR INPUT_CNTJSR FUN_HASLEFTADD R6, R6, #0BRnz FUNC_P1LD R0, CHAR_LFOUTJSR FUN_CHECKADD R6, R6, #0BRnz PLAY_AFTERLD R0, CHAR_LFOUTLEA R0, STR_WIN_1PUTSBRnzp _END;玩家2
FUNC_P2 LEA R0, STR_PLAYER2PUTSJSR INPUT_ROWJSR INPUT_CNTJSR FUN_HASLEFTADD R6, R6, #0BRnz FUNC_P2LD R0, CHAR_LFOUTJSR FUN_CHECKADD R6, R6, #0BRnz PLAY_AFTERLD R0, CHAR_LFOUTLEA R0, STR_WIN_2PUTSBRnzp _END ;玩家切换子程序
FUNC_CHANGE LD R6, PTR_PLAYERBRz SUB_ZEROADD R6, R6, #-1ST R6, PTR_PLAYERBRnzp SUB_CHANGE_RET
SUB_ZERO ADD R6, R6, #1ST R6, PTR_PLAYER
SUB_CHANGE_RET RET;输入行号(ABCDEFGHIJKLMNOPQRSTUVWXYZ)
INPUT_ROW ST R7, SAVER7GETCOUTST R0, PTR_ROWLD R7, SAVER7RET;输入个数
INPUT_CNT ST R7, SAVER7GETCOUTST R0, PTR_CNTLD R7, SAVER7RETPTR_ROW .BLKW 1
PTR_CNT .BLKW 1
PTR_PLAYER .FILL x0000;石头状态输出
;R1-石头数量地址,R2-数量
FUNC_DRAW ST R7,SAVER7LD R1,PTR_STONESLD R3,CHAR_ROWBASE;遍历石头堆
LOOP_1 LDR R2,R1,#0BRn END_DRAWLEA R0,STR_ROWPUTSAND R0,R0,#0ADD R0,R3,#0OUTLEA R0,STR_ROW2PUTSLD R0,CHAR_SYMBOLADD R2,R2,#0;循环输出o
LOOP_2 BRz OUT_2OUT ADD R2,R2,#-1BRnzp LOOP_2
OUT_2 LD R0,CHAR_LFOUTADD R1,R1,#1ADD R3,R3,#1 BRnzp LOOP_1
END_DRAW LD R7,SAVER7RET;检查石头是否完了
;Output(R6):false(0),true(1)
FUN_CHECK LD R1, PTR_STONESAND R6, R6, #0ADD R6, R6, #1
SUB_CHECK_LOOP LDR R2, R1, #0BRp SUB_CHECK_FALSEBRn SUB_CHECK_ENDADD R1, R1, #1BRnzp SUB_CHECK_LOOP SUB_CHECK_FALSE ADD R6, R6, #-1
SUB_CHECK_END RET;判断当前的输入是否还有剩余,若无剩余输出错误信息
;Input(x5001) Output(R6):false(0),p-left(n)
FUN_HASLEFT ST R7, SAVER7LD R1, PTR_STONESLD R2, PTR_ROWLD R3, NCHAR_AADD R2, R2, R3BRn SUB_HAS_ERRORADD R1, R1, R2AND R6, R6, #0LDR R2, R1, #0BRnz SUB_HAS_ERRORADD R6, R6, R2
SUB_HAS_SUB LD R2, PTR_CNTLD R3, NCHAR_0ADD R2, R2, R3BRnz SUB_HAS_ERRORNOT R2, R2ADD R2, R2, #1ADD R4, R6, R2BRn SUB_HAS_ERRORSTR R4, R1, #0BRnzp SUB_HAS_END
SUB_HAS_ERROR AND R6, R6, #0LD R0, CHAR_LFOUTLEA R0, STR_INVALIDPUTSLD R0, CHAR_LFOUT
SUB_HAS_END LD R7, SAVER7RET_END HALTCHAR_ROWBASE .FILL x0041 ;'A'的ASCII码
NCHAR_A .FILL xFFBF ;'A'的负值
NCHAR_0 .FILL xFFD0 ;'0'的负值
CHAR_SYMBOL .FILL x006f ;'o'的ASCII码
CHAR_LF .FILL x000A ;换行符的ASCII
NCHAR_LF .FILL xFFF6 ;LF的负值
PTR_STONES .FILL x3200 ;石头数量信息储存起点STR_ROW .STRINGZ "ROW "
STR_ROW2 .STRINGZ ": "
STR_PLAYER1 .STRINGZ "Player 1, choose a row and number of rocks:"
STR_PLAYER2 .STRINGZ "Player 2, choose a row and number of rocks:"
STR_WIN_1 .STRINGZ "Player 1 Wins."
STR_WIN_2 .STRINGZ "Player 2 Wins."
STR_INVALID .STRINGZ "Invalid move. Try again."SAVER7 .BLKW 1 ;保存R7.END
五、小小总结
这次的实验长度(难度)肯定是比上次要翻倍的,不过有了子程序思想的加持,以及对LC-3汇编指令理解的加深,感觉也不是特别的难。
以上代码可能仍存在一些问题,但毕竟只是个实验嘛,凑合着做做(逃)~
计算机系统1 实验 LC-3 Nim游戏 子程序相关推荐
- LC-3 汇编语言 Nim游戏
@_@汇编T_T 目录 题目描述 AC代码 思路分析 题目描述 Nim是一个简单的双人游戏,可能起源于中国.游戏中使用的计数器类型有很多种类,如石头.火柴.苹果等.游戏界面被划分为很多行,每行中有数量 ...
- 计算机系统安装和维护实验,2计算机系统安装维护实验报告.doc
2计算机系统安装维护实验报告 计算机系统安装维护实验报告 院系: 班级: 姓名: 学号: [实验目的] 学习了解u盘硬盘启动维护系统 [实验内容] 通过GHOST11软件进行系统的相关操作 用户可以通 ...
- 【bzoj3150】 cqoi2013—新Nim游戏
www.lydsy.com/JudgeOnline/problem.php?id=3105 (题目链接) 题意 在第一个回合中,第一个游戏者可以直接拿走若干个整堆的火柴.可以一堆都不拿,但不可以全部拿 ...
- LeetCode实战:Nim 游戏
背景 为什么你要加入一个技术团队? 如何加入 LSGO 软件技术团队? 我是如何组织"算法刻意练习活动"的? 为什么要求团队的学生们写技术Blog 题目英文 You are pla ...
- POJ 1704 Georgia and Bob (Nim游戏变形)
题目:http://poj.org/problem?id=1704 思路:Nim游戏策略,做如下转换,如果N是偶数,则两两配对,将两个数之间的格子数(距离)看做成这一堆石头的数量. 如果N是奇数,则将 ...
- BZOJ 3105:[cqoi2013]新Nim游戏
BZOJ 3105:[cqoi2013]新Nim游戏 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3105 题目大意:在传统的Nim取石子 ...
- 【bzoj3105】新Nim游戏
Portal--> bzoj3105 新Nim游戏 Solution 转化一下问题 首先看一下原来的Nim游戏,先手必胜的条件是:每堆数量的异或和不为\(0\) 所以在新的游戏中,如果要保证自己 ...
- 文巾解题 292. Nim 游戏
1 题目描述 2 解题思路 这其实是一个脑筋急转弯一样的题目.先给出结论吧:如果堆中石头的数量 n 不能被 4 整除,那么你总是可以赢得 Nim 游戏的胜利. 下面是推导部分: 让我们考虑一些小例子. ...
- 洛谷P4301 [CQOI2013]新Nim游戏
洛谷P4301 [CQOI2013]新Nim游戏 题目描述 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火 ...
最新文章
- jdbcTemplate 的update 和batchUpdate 方法的使用
- 2021年全球知名开源项目大更新
- 西门子rwd68温控器说明书_西门子RWD68说明书
- iPhone 播放音频声音文件
- document.execCommand() 解析
- elastix中NAT穿越问题解决办法
- 被final关键字坑了
- 写在今年(2022)清明节前
- linux操作系统期末试卷及答案,Linux操作系统期末复习题(含答案).pdf
- Springer-Verlag免费下载图书400本
- Vine已死,秒拍抱团崛起,同是视频社交差距在哪?
- AUTOSAR I-PDU的理解以及I-PDU的Callout
- Qt无边框窗体(Windows)
- Typora编辑器(蓝奏)
- 5G时代下的物联网发展前景,物联网人才的发展机遇有哪些?
- 【Python基础学习笔记day08】python变量的基本使用+变量定义ipython+pycharm+超市买苹果+变量的类型+关于函数+变量的格式化输出+个人名片案例
- 【无标题】一款功能非常强大的免费串口示波器串口助手,支持绘图,logo保存数据保存,历史数据加载与对比。
- Centos离线安装Kubernetes集群
- Electron系列教程——第二篇:第一个示例
- SegFormer: Simple and Efficient Design for Semantic Segmentation with Transformers
热门文章
- 去掉CAJViewer广告的方法
- [LBS学习笔记4]地理特征POI、AOI、路径轨迹
- java安卓app开发教程_[Android教程] Cordova开发App入门(一)创建android项目
- 【processing码绘】简单实现码绘动态图形与拓展
- python 动态图形_在matplotlib中动态更新图形
- 计算机的命令用英语怎么说,计算机外部和内部命令的英语及词汇
- ss3ex集成Beet记录日志
- React中文文档之Rendering Elements
- 鲲鹏Arm64 openEuler 虚拟机学习
- 算法 64式 17、排列组合算法整理