吐槽
前面的实验都很友好,这个又臭又长,零零散散写了几天很好地锻炼我们编写LC3汇编的能力
实验目的
- 分析和理解指定的需解决问题
- 利用LC-3的汇编代码设计实现相关程序
- 通过LC-3仿真器调试和运行相关程序并得到正确的结果
实验内容
-
四子棋是一款普遍流行的简易型桌面游戏,据说,虎克船长曾因专注于此游戏而长期隐身在住所,当船员们发现船长的这一专长之后,他们称这个游戏为“船长的情妇”。
-
四子棋是个双人游戏,两人轮流下棋,棋盘由行和列组成的网格,每个选手每次下一个子直到两人中有一人的棋子连成一条水平线、垂直线或者是对角线。
-
本实验需要在LC-3中实现简易版四子棋的游戏,两位选手通过键盘和输出窗口轮流交互操作,棋盘由6 X 6的网格组成。
游戏规则如下:
– 两位选手依次轮流落子;
– 选手不能悔棋;
– 有子的地方不能继续落子;
直到有一方的四个棋子能够连成一条水平线、垂直线或者是对角线;
如果棋盘已满,无人获胜,则平局。 -
游戏最初时应该打印空的棋盘,可以用ASCII码"-" (即ASCII 码 x002D)来表示该处为空,“O”(ASCII 码 x004F)表示第一位选手的棋子,“X” (ASCII 码 x0058)来表示第二位选手的棋子,为了让棋盘更易于观察,在各列间加一个空格,第6列之后不要添加,初始棋盘应该如下:
-
选手一始终先下第一步棋,然后两者轮流落子,在每次落子之后,应该打印该选手的信息,提示他落子,以选手一为例,应该打印信息如下:
Player 1, choose a column: -
为了明确选手的落子的位置,该选手应该输入数字1-6,然后回车,数字1-6指示在落子所在的列,从左到右,无需输入行号,程序应默认从行号6到行号1递减的顺序填入该棋子,若前后输入的列号相同,则行号减一。*例如,如果选手第一次在左起第二列落子,应该输入2,然后回车,则该棋子落在行6列2处,当后面输入的列号再次为2时,则将棋子落子行5列2处,以此类推,详情见后续示例输出。*程序应该确保选手输入的数字对应正确的列的范围,如果输入不合理,应该输出一条错误信息,提示该选手继续输入,例如,如果对于选手一:
Player 1, choose a column: D
Invalid move. Try again.
Player 1, choose a column: 7
Invalid move. Try again.
Player 1, choose a column: -
程序应该一直提示该选手,知道输入正确的数字,当用户输入完成,程序应通过显示回馈给选手,然后通过换行符(‘\n’ x0A)换行。
-
当选手输入成功后,程序应打印更新后的棋盘,并检查是否有人获胜,如果没人获胜,则轮到下一位输入。
-
当其中一位获胜或平局时,游戏结束,程序显示最后的棋盘情况并终止(Halt)。例如,如果选手二有四子相连,应该输出:
Player 2 Wins.
如果平局,程序应该输出:
Tie Game.
思路简述
- 棋盘信息用6*6=36位的数组存储,0为空,1为P1,-1为P2
- 非法输入,区间两边进行两次判断
- 胜负判断我做了个分区判断
冗余还是有点多,主要想避免边界检查 - 话不多说上代码
代码实现
.ORIG x3000
JSR INIT
AgD JSR DISPLAY
JSR JUDGE
JSR ISOVER
AgT JSR TURN
JSR PLACE
ADD R0, R0, 0
BRz AgT
BRp AgD
; 初始化
INIT:
AND R1, R1, 0
ADD R1, R1, 1
ST R1, STATE
AND R2, R2, 0
LEA R3, ROW1 ;R3状态数组的指针
LD R4, num1 ;R4计数
LOOP0 STR R2, R3, 0
ADD R3, R3, 1
ADD R4, R4, 1
BRn LOOP0
RET
; 打印棋盘
DISPLAY:
ST R7, SAVEDP
LEA R3, ROW1
LD R4, num1
AND R6, R6, 0
ADD R6, R6, 6
LOOP1 LDR R2, R3, 0
BRp ISO
BRn ISX
LD R0, CHAR1
OUT
BRnzp AGAIN
ISO LD R0, CHAR2
OUT
BRnzp AGAIN
ISX LD R0, CHAR3
OUT
AGAIN ADD R6, R6, -1
BRz Endline
LD R0, BLANK
OUT
BRnzp CHECK
Endline LD R0, NEWLINE
OUT
ADD R6, R6, 6
CHECK ADD R3, R3, 1
ADD R4, R4, 1
BRn LOOP1
LD R7, SAVEDP
RET
SAVEDP .BLKW 1
num1 .FILL -36
CHAR1 .FILL x002D
CHAR2 .FILL x004F
CHAR3 .FILL x0058
BLANK .FILL x0020
NEWLINE .FILL X000A
SAVETN .BLKW 1
; 输入
TURN:
ST R7, SAVETN
RES LD R1, STATE
BRp Print1
BRz Print2
Print1 LEA R0, Player1
PUTS
BRnzp INPUT
Print2 LEA R0, Player2
PUTS
INPUT GETC
OUT
ST R0, Column
LD R0, NEWLINE
OUT
LD R1, Column
LD R2, num2
ADD R1, R1, R2 ;将字符转化为数字
BRnz Invalid ;R1<=0 再次输入
ADD R2, R1, -6 ;R1>6 再次输入
BRp Invalid
LD R7, SAVETN
ST R1, Column
RET
Invalid JSR PrintInvalid
BRnzp RES
PrintInvalid:
ST R7, SAVEIV
LEA R0, IvMSG
PUTS
LD R7, SAVEIV
RET
Player1 .STRINGZ "Player 1, choose a column:"
Player2 .STRINGZ "Player 2, choose a column:"
IvMSG .STRINGZ "Invalid move. Try again.\n"
SAVEIV .BLKW 1
num2 .FILL -48
; 放置棋子(设置数组状态)
PLACE:
LD R1, Column
ADD R1, R1, -1 ;R1此处是偏移量
LEA R2, ROW6 ;R2是指针
ADD R2, R2, R1
AND R5, R5, 0
ADD R5, R5, 6 ;R5是当前行数
PLTry LDR R3, R2, 0
BRnp NEXTROW
LD R4, STATE
BRp PLO ;P1
BRz PLX ;P2
PLO ADD R3, R3, 1
STR R3, R2, 0
AND R4, R4, 0
ST R4, STATE ;更新下一步落子方
BRnzp RET1
PLX ADD R3, R3, -1
STR R3, R2, 0
ADD R4, R4, 1
ST R4, STATE
BRnzp RET1
NEXTROW ADD R2, R2, -6
ADD R5, R5, -1
BRz RET0 ;如果放不下返回0
BRp PLTry ;再次尝试
RET0 ST R7, SAVEPL
JSR PrintInvalid
AND R0, R0, 0
LD R7, SAVEPL
RET
RET1 AND R0, R0, 0
ADD R0, R0, 1
RET
SAVEPL .BLKW 1
; 平局结束判断
ISOVER:
LEA R1, ROW1
LD R2, num3
CKIT LDR R3, R1, 0
BRz CG ;存在为空的位置,返回
ADD R1, R1, 1
ADD R2, R2, 1
BRn CKIT
BRz TG
TG LEA R0, TGMSG
PUTS
AND R0, R0, 0
ADD R0, R0, 1
HALT
CG AND R0, R0, 0
RET
num3 .FILL -36
TGMSG .STRINGZ "Tie Game."
ROW1 .BLKW 6
ROW2 .BLKW 6
ROW3 .BLKW 6
ROW4 .BLKW 6
ROW5 .BLKW 6
ROW6 .BLKW 6
STATE .FILL 1
SAVE1 .BLKW 1
SAVE2 .BLKW 1
SAVE3 .BLKW 1
SAVE4 .BLKW 1
SAVE71 .BLKW 1
SAVE72 .BLKW 1
location .BLKW 1
Column .FILL 1
Row .FILL 1
SAVE14 ST R1, SAVE1
ST R2, SAVE2
ST R3, SAVE3
ST R4, SAVE4
RET
LD14 LD R1, SAVE1
LD R2, SAVE2
LD R3, SAVE3
LD R4, SAVE4
RET
; 落子分为四个区,以中心为坐标轴,分为一二三四区
JUDGE:
ST R7, SAVE71
LEA R1, ROW1
LD R2, num3
AND R3, R3, 0
ADD R3, R3, 1
AND R4, R4, 0
ADD R4, R4, 1
DO ST R1, location
ST R3, Row
ST R4, Column
JSR SAVE14
JSR JCA
JSR LD14
ADD R1, R1, 1
ADD R4, R4, 1
ADD R6, R4, -7 ;大于六行数加一
BRz Rplus
CKR2 ADD R2, R2, 1
BRn DO
BRzp finish
Rplus ADD R3, R3, 1
ADD R4, R4, -6
BRnzp CKR2
finish LD R7, SAVE71
RET
; 分区的判断
JCA ST R7, SAVE72
LD R1, Column
LD R2, Row
ADD R3, R1, -3
BRnz is23
BRp is14
is23 ADD R3, R2, -3
BRnz is2
BRp is3
is14 ADD R3, R2, -3
BRnz is1
BRp is4
is1 JSR JD1
BRnzp endret
is2 JSR JD2
BRnzp endret
is3 JSR JD3
BRnzp endret
is4 JSR JD4
endret LD R7, SAVE72
RET
SAVE73 .BLKW 1
JDINIT LD R1, location
AND R0, R0, 0 ;R0是对应分区方向的偏移量
AND R2, R2, 0 ;R2是棋子计数
ADD R3, R1, 0 ;R3是棋子地址的拷贝
AND R5, R5, 0 ;R5是单次计数器,设置为4
ADD R5, R5, 4
RET
; 一区
JD1 ST R7, SAVE73
JSR JDINIT
LD R7, SAVE73
LP11 ADD R0, R0, -1
BRnzp LP1
LP12 ADD R0, R0, 6
BRnzp LP1
LP13 ADD R0, R0, 1
BRnzp LP1
LP1 LDR R4, R3, 0
ADD R2, R2, R4
ADD R6, R2, 0
ADD R6, R6, 4 ;判断是否为四或负四
BRz WIN
ADD R6, R2, 0
ADD R6, R6, -4
BRz WIN
ADD R3, R3, R0
ADD R5, R5, -1
BRp LP1
AND R2, R2, 0
ADD R3, R1, 0 ;R3复位
ADD R5, R5, 4 ;R5复位
ADD R6, R0, 1
BRz LP12
ADD R6, R0, -5
BRz LP13
RET
JD2 ST R7, SAVE73
JSR JDINIT
LD R7, SAVE73
LP21 ADD R0, R0, 1
BRnzp LP2
LP22 ADD R0, R0, 5
BRnzp LP2
LP23 ADD R0, R0, 1
BRnzp LP2
LP2 LDR R4, R3, 0
ADD R2, R2, R4
ADD R6, R2, 4 ;判断是否为四或负四
BRz WIN
ADD R6, R2, -4
BRz WIN
ADD R3, R3, R0
ADD R5, R5, -1
BRp LP2
AND R2, R2, 0
ADD R3, R1, 0
ADD R5, R5, 4
ADD R6, R0, -1
BRz LP22
ADD R6, R0, -6
BRz LP23
RET
JD3 ST R7, SAVE73
JSR JDINIT
LD R7, SAVE73
LP31 ADD R0, R0, -6
BRnzp LP3
LP32 ADD R0, R0, 1
BRnzp LP3
LP33 ADD R0, R0, 6
BRnzp LP3
LP3 LDR R4, R3, 0
ADD R2, R2, R4
ADD R6, R2, 4 ;判断是否为四或负四
BRz WIN
ADD R6, R2, -4
BRz WIN
ADD R3, R3, R0
ADD R5, R5, -1
BRp LP3
AND R2, R2, 0
ADD R3, R1, 0
ADD R5, R5, 4
ADD R6, R0, 6
BRz LP32
ADD R6, R0, 5
BRz LP33
RET
JD4 ST R7, SAVE73
JSR JDINIT
LD R7, SAVE73
LP41 ADD R0, R0, -7
BRnzp LP4
LP42 ADD R0, R0, 1
BRnzp LP4
LP43 ADD R0, R0, 5
BRnzp LP4
LP4 LDR R4, R3, 0
ADD R2, R2, R4
ADD R6, R2, 4 ;判断是否为四或负四
BRz WIN
ADD R6, R2, -4
BRz WIN
ADD R3, R3, R0
ADD R5, R5, -1
BRp LP4
AND R2, R2, 0
ADD R3, R1, 0
ADD R5, R5, 4
ADD R6, R0, 7
BRz LP42
ADD R6, R0, 6
BRz LP43
RET
WIN LD R2, STATE
BRz p1win
BRp p2win
p1win LEA R0, WINMSG1
PUTS
HALT
p2win LEA R0, WINMSG2
PUTS
HALT
WINMSG1 .STRINGZ "Player 1 Wins."
WINMSG2 .STRINGZ "Player 2 Wins."
.END
如果对你有帮助的话点个赞叭