【深圳大学】计算机系统(1)重力四子棋

吐槽

前面的实验都很友好,这个又臭又长,零零散散写了几天很好地锻炼我们编写LC3汇编的能力

实验目的

  1. 分析和理解指定的需解决问题
  2. 利用LC-3的汇编代码设计实现相关程序
  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

如果对你有帮助的话点个赞叭

  • 24
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值