Simple Game Design Based on LC3 Simulator: Simple Connect Four

1. Purpose of the experiment

  1. Analyze and understand assigned problems to be solved.
  2. Use the assembly code of LC-3 to design and realize related programs.
  3. Debug and run related programs through LC-3 emulator and get correct results.

2. Experimental content

Connect Four is a popular simple table game. It is said that Captain Hook has been hiding in the residence for a long time because of his concentration on this game. When the crew discovered the captain's specialty, they called this game "Captain's mistress".

Connect four is a two-player game in which two players take turns playing on a grid of rows and columns where each player plays one piece at a time until one of the two pieces connects in a horizontal, vertical, or diagonal line Wire.

This experiment needs to implement a simple version of Connect Four in LC-3. Two players interact with each other through the keyboard and output window in turn. The chessboard is composed of a 6 X 6 grid.

The rules of the game are as follows:

  1. The two players take turns to play;
  2. Players cannot regret a move;
  3. Where there is a child, the child cannot continue to be placed;
  4. Until the four pieces of one side can be connected into a horizontal line, vertical line or diagonal line;
  5. If the board is full and no one wins, there is a draw.

At the beginning of the game, an empty board should be printed. You can use the ASCII code "-" (ASCII code x002D) to indicate that the place is empty, "O" (ASCII code x004F) to indicate the first player's piece, and "X" (ASCII code x0058) to represent the chess piece of the second player. In order to make the chessboard easier to observe, add a space between each column, do not add after the 6th column, the initial chessboard should be as follows:

- - - - - -
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- - - - - -

Player 1 always plays the first move first, and then the two take turns to make moves. After each move, the player's information should be printed to remind him to make a move. Taking player 1 as an example, the printed information should be as follows:

Player 1, choose a column:

In order to clarify the position of the player's move, the player should enter the number 1-6, and then press Enter, the number 1-6 indicates the column where the move is located, from left to right, no need to enter the line number, the program should default from line number 6 to Fill in the pieces in descending order of row number 1. If the column numbers entered before and after are the same, the row number will be reduced by one. For example, if the player places a piece in the second column from the left for the first time, he should enter 2, and then press Enter, then the piece will be placed in row 6, column 2, and when the column number entered later is 2 again, the piece will be placed in the row 5 column 2, and so on, see the following example output for details. The program should ensure that the number entered by the player corresponds to the correct column range, and if the input is unreasonable, an error message should be output, prompting the player to continue typing, for example, if for player one:

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:

The program should always prompt the player to know the correct number to enter, and when the user completes the input, the program should give feedback to the player through display, and then use a newline character (ASCII code x000A) to break the line.
When a player enters successfully, the program should print the updated board and check if anyone has won, and if no one has won, it's the next player's turn to enter.
When one of them wins or draws, the game ends, and the program displays the final board situation and terminates (Halt). For example, if player two has four connected, it should output:

Player 2 Wins.

In case of a tie, the program should output:

Tie Game.

3. Experimental procedures and results

Overall process (main function)

The overall process of my tentatively designed experiment is shown in the figure below. The flowchart is the work of the main function in the code.
insert image description here

Representation of chessboard matrices and round parties

A 6×6 two-dimensional matrix is ​​used to represent the chessboard. The position on the board with no pieces is represented by 0, the position of Player 1’s position is represented by 1, and the position of Play 2’s position is represented by -1. Matrix subscripts start at 0.

The memory addresses in the computer are continuous, so it is necessary to continuously allocate a one-dimensional memory space of 36 units. The specific operation is as follows:

;
;矩阵建立及其初始化
;
	ARRAY	.BLKW	#36

There is a one-to-one correspondence between the coordinates on the two-dimensional matrix and the coordinates on the one-dimensional matrix. For example, on the memory corresponding to the two-dimensional coordinates (i, j), the (6 × i + j)th position counted from the entry of the matrix. The index position on the matrix memory corresponds to the two-dimensional matrix coordinates (index // 6, index % 6). Among them, "//" means divisibility, and "%" means taking the remainder.

Because in this experiment, the coordinates are frequently converted from one-dimensional to two-dimensional, I implemented the multi function and the div function. The function of the multi function is to multiply the incoming parameter by 6 and return, and the function of the div function is to return the quotient and remainder of the incoming parameter.

Use a register R0 to store the current mover. When the register stores 1, the current round is played by Player 1; when -1 is stored, Player 2 plays.

The specific implementation method of each module in the main flow chart is discussed in detail below, and a flow chart is attached.

Implement the print function: print the current situation

To implement the printing function, you only need to traverse the values ​​in the matrix memory in sequence. If the value of the element in the matrix is ​​0, output "-"; if it is 1, output "O"; if it is -1, output "X". It should be noted that each output of "-" must be judged. Under normal circumstances, a space is output, but when a line break is required, the line is changed directly. The flow chart is as follows:
insert image description here

Implement the isTie function: determine whether the current situation is a tie

It is worth noting that if there is a tie, then all 6 elements in row 0 of the chessboard matrix must be non-zero. It also corresponds to the 6 locations from ARRAY to ARRAY + 5 on the memory. Therefore, it is only necessary to judge whether all the six positions are not 0. If all are not 0, the situation is a tie; if there are non-zeros, the situation is not a tie. The process is as follows:
insert image description here

Implement the Play function: the player enters the coordinates and returns the actual drop position

The coordinates entered by the player are an ordinate, and this function needs to find the legal drop position of this column and return its actual coordinates (one-dimensional). If the coordinate does not exist (the column is full or the input is invalid), output an error message and return -1.

According to the current round, this function is divided into Play1 and Play2. Its function is the same.

Algorithm idea: Assume that the input ordinate is j (starting from 0) and the entry address of the last line is ARRAY + 30 + j. Then start from this address, continuously subtract 6 (that is, go back one line), look for the position with a value of 0, and return the subscript if it is found; if it has not been found, return -1.
The flow chart is as follows:
insert image description here

Implement the isOver function: determine whether a party wins

This function has two parameters: move coordinate index and move value value. Its meaning is, when one party changes the value of ARRAY[index] to value, can the game be distinguished from the winner?

This function is the core of this experiment, and four kinds of judgments are required: horizontal judgment, vertical judgment, main diagonal direction judgment and sub-diagonal direction judgment.

insert image description here

To realize the judgment of the four-part line in the above four situations, the brute force algorithm is not considered, because the efficiency is low, and the design of multiple loops is also relatively difficult and prone to confusion. Therefore, I adopt the following optimized algorithm.

Whenever a chess piece falls, the situation is bound to change, and there may be a new situation where four pieces form a line. There may not be such a situation, but if there is, this new move will definitely become one of the four in the line. Then we take this new chess piece as the center and expand in the seven directions shown in the figure below:

insert image description here
For example, to determine whether four pieces form a line in the horizontal direction, it is necessary to count the number of consecutive identical pieces on the left side of the drop point. As shown in the figure below, the red circular chess piece is a new chess piece, so when making a horizontal judgment, you can use this chess piece as the center and extend to the left and right. There are two consecutive identical chess pieces on its left side, and one consecutive identical chess piece on its right side, plus itself, just four pieces form a line, so it is judged that Yuanfang wins.
insert image description here
The judgments of the vertical direction, the main diagonal direction, and the subdiagonal direction are similar to this. The algorithm designed in this way is more efficient and more concise in the process of coding and implementation.

The above is the idea realized by this experiment. The next section will test the correctness and robustness of this program from several angles.

Test 1: Horizontal Victory

insert image description here

Test 2: Vertical Victory

insert image description here

Test 3: The main diagonal direction wins

insert image description here

Test 4: Subdiagonal direction wins

insert image description here

Test 5: Draw

insert image description here

Test 6: Illegal input

Illegal input with top overflow is tested in the left image, and incorrect input with illegal characters is tested in the right image. For these two types of wrong input, the program pops up an error message and reminds the player to re-enter. It shows that the robustness of the program is good.
insert image description here

4. Complete code

Below is the complete Connect Four LC-3 code.

;
; author: Cao-Yixuan 2019282129
; date:2021.6.8
; function: a game called Connect Four
;
;
    .ORIG x3000
;
	JSR	main
;
;函数:打印矩阵
;
print	ST	R0	SAVE_R0		;被调用者保存
		ST	R1	SAVE_R1
		ST	R2	SAVE_R2
		ST	R3	SAVE_R3
		ST	R4	SAVE_R4
		ST	R5	SAVE_R5
		ST	R6	SAVE_R6
		ST	R7	SAVE_R7
;
;R1 = 36,控制循环
;R2 = 6,控制换行
;R3 = ARRAY
;
		LEA	R3	ARRAY
		AND	R1	R1	#0
		ADD	R2	R1	#6
		ADD	R1	R1	#15
		ADD	R1	R1	#15
		ADD	R1	R1	R2
;
PRINT_LOOP	LDR	R0	R3	#0
			BRp	PRINT_1_CH
			BRn	PRINT_2_CH
			LD	R0	BLANK
			BRnzp	PRINT_CH
PRINT_1_CH	LD	R0	P_1_CH
			BRnzp	PRINT_CH
PRINT_2_CH	LD	R0	P_2_CH
			BRnzp	PRINT_CH	
PRINT_CH	TRAP	x21
			ADD	R3	R3	#1
			ADD	R2	R2	#-1
			BRp	PRINT_BLANK
			ADD	R2	R2	#6
			LD	R0	ENDLINE
			TRAP	x21
			BRnzp	PRINT_L_END
PRINT_BLANK	LD	R0	BLANK1
			TRAP	x21
PRINT_L_END	ADD	R1	R1	#-1
			BRp	PRINT_LOOP
;			
;
;
		LD	R0	SAVE_R0		; 被调用者恢复
		LD	R1	SAVE_R1
		LD	R2	SAVE_R2
		LD	R3	SAVE_R3
		LD	R4	SAVE_R4
		LD	R5	SAVE_R5
		LD	R6	SAVE_R6
		LD	R7	SAVE_R7
		RET
;

	P_1_CH	.FILL	x004F
	P_2_CH	.FILL	x0058
	ENDLINE .FILL	x0D
	BLANK	.FILL	x002D
	BLANK1	.FILL	x20

;
;函数:PLAY1落子
;输入:TEMP0
;输出:TEMP0
;如果落子失败,R6处返回-1
;如果落子成功,R6处返回落子位置的下标
;

play1	ST	R0	SAVE_R0		;被调用者保存
		ST	R1	SAVE_R1
		ST	R2	SAVE_R2
		ST	R3	SAVE_R3
		ST	R4	SAVE_R4
		ST	R5	SAVE_R5
		ST	R6	SAVE_R6
		ST	R7	SAVE_R7
;
;初始化返回值R6 = -1
;
		AND	R6	R6	#0
		ADD	R6	R6	#-1
;
;边界检查
;
		LD	R0	TEMP0		;传入参数j
		ADD	R1	R0	#-6
		BRzp	P_1_ERROR
		ADD	R1	R0	#0
		BRn		P_1_ERROR
;
;循环
;R2 = ARRAY+30+j,入口
;R3 = ARRAY+j,出口
;		
			LEA	R2	ARRAY
			ADD	R3	R2	R0
			ADD	R2	R3	#15
			ADD	R2	R2	#15
			NOT	R0	R3
			ADD	R0	R0	#1
P_1_LOOP	LDR	R3	R2	#0
			ADD	R3	R3	#0
			BRz	P_1_RIGHT
			ADD	R2	R2	#-6
			ADD	R4	R2	R0
			BRzp	P_1_LOOP
P_1_ERROR	LEA	R0	ERROR
			TRAP	x22
			BRnzp	PLAY_1_END
P_1_RIGHT	AND	R6	R2	R2
			AND	R4	R4	#0
			ADD	R4	R4	#1
			STR	R4	R6	#0
			LEA	R7	ARRAY
			NOT	R7	R7
			ADD	R7	R7	#1
			ADD	R6	R6	R7
			BRnzp	PLAY_1_END
PLAY_1_END	ST	R6	TEMP0		; 输出
			LD	R0	SAVE_R0		; 被调用者恢复
			LD	R1	SAVE_R1
			LD	R2	SAVE_R2
			LD	R3	SAVE_R3
			LD	R4	SAVE_R4
			LD	R5	SAVE_R5
			LD	R6	SAVE_R6
			LD	R7	SAVE_R7
			RET


;
;函数:PLAY2落子
;输入:TEMP0
;输出:TEMP0
;如果落子失败,R6处返回-1
;如果落子成功,R6处返回落子位置的下标
;

play2	ST	R0	SAVE_R0		;被调用者保存
		ST	R1	SAVE_R1
		ST	R2	SAVE_R2
		ST	R3	SAVE_R3
		ST	R4	SAVE_R4
		ST	R5	SAVE_R5
		ST	R6	SAVE_R6
		ST	R7	SAVE_R7

;
;初始化返回值R6 = -1
;
		AND	R6	R6	#0
		ADD	R6	R6	#-1
;
;边界检查
;
		LD	R0	TEMP0		;传入参数j
		ADD	R1	R0	#-6
		BRzp	P_2_ERROR
		ADD	R1	R0	#0
		BRn		P_2_ERROR
;
;循环
;R2 = ARRAY + 30 + j, 作为入口
;R3 = ARRAY + j, 作为出口
;		
			LEA	R2	ARRAY
			ADD	R3	R2	R0
			ADD	R2	R3	#15
			ADD	R2	R2	#15

			NOT	R0	R3
			ADD	R0	R0	#1
P_2_LOOP	LDR	R3	R2	#0
			ADD	R3	R3	#0
			BRz	P_2_RIGHT
			ADD	R2	R2	#-6
			ADD	R4	R2	R0
			BRzp	P_2_LOOP

P_2_ERROR	LEA	R0	ERROR
			TRAP	x22
			BRnzp	PLAY_2_END

P_2_RIGHT	AND	R6	R2	R2
			AND	R4	R4	#0
			ADD	R4	R4	#-1
			STR	R4	R6	#0
			LEA	R7	ARRAY
			NOT	R7	R7
			ADD	R7	R7	#1
			ADD	R6	R6	R7
			BRnzp	PLAY_2_END
PLAY_2_END	ST	R6	TEMP0		; 输出
			LD	R0	SAVE_R0		; 被调用者恢复
			LD	R1	SAVE_R1
			LD	R2	SAVE_R2
			LD	R3	SAVE_R3
			LD	R4	SAVE_R4
			LD	R5	SAVE_R5
			LD	R6	SAVE_R6
			LD	R7	SAVE_R7
			RET

ERROR	.STRINGZ    "Invalid move. Try again.\n"

;
;函数:判断是否是平局
;output:TEMP1
;

isTie		ST	R0	SAVE_R0		;被调用者保存
			ST	R1	SAVE_R1
			ST	R2	SAVE_R2
			ST	R3	SAVE_R3
			ST	R4	SAVE_R4
			ST	R5	SAVE_R5
			ST	R6	SAVE_R6
			ST	R7	SAVE_R7

			LEA	R0	ARRAY
			AND	R1	R1	#0		;index = 5 to 0
			ADD	R1	R1	#5
			AND	R2	R2	#0		;返回0
;
TIE_LOOP	ADD	R4	R0	R1
			LDR	R3	R4	#0
			ADD	R3	R3	#0
			BRz	TIE_RET
			ADD	R1	R1	#-1
			BRzp	TIE_LOOP

			ADD	R2	R2	#1		;返回1
TIE_RET		ST	R2	TEMP1

			LD	R0	SAVE_R0		; 被调用者恢复
			LD	R1	SAVE_R1
			LD	R2	SAVE_R2
			LD	R3	SAVE_R3
			LD	R4	SAVE_R4
			LD	R5	SAVE_R5
			LD	R6	SAVE_R6
			LD	R7	SAVE_R7
			RET

;
;矩阵建立及其初始化
;
	ARRAY	.BLKW	#36

;
;保存寄存器
;
	SAVE_R0 .FILL #0
	SAVE_R1 .FILL #0
	SAVE_R2 .FILL #0
	SAVE_R3 .FILL #0
	SAVE_R4 .FILL #0
	SAVE_R5 .FILL #0
	SAVE_R6 .FILL #0
	SAVE_R7 .FILL #0
;
;临时存储用寄存器
;

	TEMP0	.FILL	#0
	TEMP1	.FILL	#0
	TEMP2	.FILL	#0
	TEMP3	.FILL	#0
	TEMP4	.FILL	#0
	TEMP5	.FILL	#0
	TEMP6	.FILL	#0
	TEMP7	.FILL	#0
	TEMP8	.FILL	#0
	TEMP9	.FILL	#0


;
;The key function: is it over?
;if return 1, play1 wins
;if return -1, play2 wins
;if return 0, it is not over
;INPUT1: TEMP0, an index of the array
;INPUT2: TEMP1, the value of array[TEMP0] 
;OUTPUT: TEMP0, a bool value
;

isOver		ST	R0	SAVE_R0		;被调用者保存
			ST	R1	SAVE_R1
			ST	R2	SAVE_R2
			ST	R3	SAVE_R3
			ST	R4	SAVE_R4
			ST	R5	SAVE_R5
			ST	R6	SAVE_R6
			ST	R7	SAVE_R7
;
;行判断
;
JUDGE1		LD	R0	TEMP0		;R0 = index
			LD	R1	TEMP1		;R1 = -value
			NOT	R1	R1
			ADD	R1	R1	#1
			JSR	div
			LD	R2	TEMP1		;R2 = i
			LD	R3	TEMP2		;R3 = j
			AND	R4	R4	#0		;R4 = cnt
			LEA	R5	ARRAY		;R5 元素指针,从行首开始
			ADD	R5	R5	R0
			NOT	R6	R3
			ADD	R6	R6	#1
			ADD	R5	R5	R6
			ST	R5	TEMP3		;行首指针存起来

;
;Loop: jump-tp-middle
;
			BRnzp	J_MIDD_1
J_LOOP_1	LDR	R6	R5	#0
			ADD	R6	R6	R1
			BRnp	J_NOT_1
			ADD	R4	R4	#1
			ADD	R5	R5	#1
			ADD	R6	R4	#-4
			BRz	J_RET_TRUE
			BRnzp	J_MIDD_1
J_NOT_1		AND	R4	R4	#0
			ADD	R5	R5	#1
J_MIDD_1	LD	R6	TEMP3
			ADD	R6	R6	#5
			NOT	R6	R6
			ADD	R6	R6	#1
			ADD	R6	R6	R5
			BRn	J_LOOP_1
			
;
;列判断
;
JUDGE2		ADD	R4	R0	#-16
			ADD	R4	R4	#-2
			BRzp	JUDGE3
			LEA	R5	ARRAY
			ADD	R5	R5	R0
			LDR	R6	R5	#6	
			ADD	R6	R6	R1
			BRnp	JUDGE3
			LDR	R6	R5	#12	
			ADD	R6	R6	R1
			BRnp	JUDGE3
			LDR	R6	R5	#18
			ADD	R6	R6	R1
			BRnp	JUDGE3
			
			BRnzp	J_RET_TRUE

;
;主对角线方向判断
;

JUDGE3		AND	R4	R4	#0
			ADD	R4	R4	#1		;cnt=1
			ST	R2	TEMP3		;存储i
			ST	R3	TEMP4		;存储j
J_3_LOOP_1	ADD	R2	R2	#-1
			BRn	J_3_END_1
			ADD	R3	R3	#-1
			BRn	J_3_END_1
			ST	R2	TEMP0
			JSR	multi
			LD	R5	TEMP1
			ADD	R5	R5	R3
			LEA	R6	ARRAY
			ADD	R5	R5	R6
			LDR	R5	R5	#0
			ADD	R5	R5	R1
			BRnp	J_3_END_1
			ADD	R4	R4	#1
			BRnzp	J_3_LOOP_1
J_3_END_1	LD	R2	TEMP3
			LD	R3	TEMP4
J_3_LOOP_2	ADD	R2	R2	#1
			ADD	R5	R2	#-6
			BRzp	J_3_END_2
			ADD	R3	R3	#1
			ADD	R5	R3	#-6
			BRzp	J_3_END_2
			ST	R2	TEMP0
			JSR	multi
			LD	R5	TEMP1
			ADD	R5	R5	R3
			LEA	R6	ARRAY
			ADD	R5	R5	R6
			LDR	R5	R5	#0
			ADD	R5	R5	R1
			BRnp J_3_END_2
			ADD	R4	R4	#1
			BRnzp	J_3_LOOP_2
J_3_END_2	ADD	R4	R4	#-4
			BRzp	J_RET_TRUE
;
;副对角线方向判断
;

JUDGE4		AND	R4	R4	#0
			ADD	R4	R4	#1			;cnt=1
			LD	R2	TEMP3
			LD	R3	TEMP4
J_4_LOOP_1	ADD	R2	R2	#-1
			BRn	J_4_END_1
			ADD	R3	R3	#1
			ADD	R5	R3	#-6
			BRzp	J_4_END_1
			ST	R2	TEMP0
			JSR	multi
			LD	R5	TEMP1
			ADD	R5	R5	R3
			LEA	R6	ARRAY
			ADD	R5	R5	R6
			LDR	R5	R5	#0
			ADD	R5	R5	R1
			BRnp	J_4_END_1
			ADD	R4	R4	#1
			BRnzp	J_4_LOOP_1
J_4_END_1	LD	R2	TEMP3
			LD	R3	TEMP4
J_4_LOOP_2	ADD	R2	R2	#1
			ADD	R5	R2	#-6
			BRzp	J_4_END_2
			ADD	R3	R3	#-1
			BRn	J_4_END_2
			ST	R2	TEMP0
			JSR	multi
			LD	R5	TEMP1
			ADD	R5	R5	R3
			LEA	R6	ARRAY
			ADD	R5	R5	R6
			LDR	R5	R5	#0
			ADD	R5	R5	R1
			BRnp J_4_END_2
			ADD	R4	R4	#1
			BRnzp	J_4_LOOP_2
J_4_END_2	ADD	R4	R4	#-4
			BRzp	J_RET_TRUE
			AND	R1	R1	#0
			ST	R1	TEMP0
			BRnzp	J_RET_FALSE
J_RET_TRUE	NOT	R1	R1
			ADD	R1	R1	#1		;恢复value, return
			ST	R1	TEMP0
J_RET_FALSE	LD	R0	SAVE_R0		; 被调用者恢复
			LD	R1	SAVE_R1
			LD	R2	SAVE_R2
			LD	R3	SAVE_R3
			LD	R4	SAVE_R4
			LD	R5	SAVE_R5
			LD	R6	SAVE_R6
			LD	R7	SAVE_R7
			RET


;
;----------------------------------------------
;函数: 实现对6执行乘法的结果
;input: TEMP0
;output: TEMP1
;这里,单独设计一群寄存器保存multi和div函数,
;防止函数在嵌套时出现内存被篡改的现象
;
SAVE_R0_	.FILL	#0
SAVE_R1_	.FILL	#0
SAVE_R2_	.FILL	#0
;
multi		ST	R0	SAVE_R0_	;被调用者保存
			ST	R1	SAVE_R1_
			ST	R2	SAVE_R2_
			LD	R0	TEMP0
			AND	R1	R1	#0		;返回值
			BRnzp	MUL_MIDDLE
MUL_LOOP	ADD	R1	R1	#6
			ADD	R0	R0	#-1					
MUL_MIDDLE	ADD	R0	R0	#0
			BRp	MUL_LOOP
			ST	R1	TEMP1		; 函数返回值
			LD	R0	SAVE_R0_	; 被调用者恢复
			LD	R1	SAVE_R1_
			LD	R2	SAVE_R2_
			RET

;
;函数:除法,获得非负数对6的积和余数
;input: TEMP0
;output: TEMP1, TEMP2
;

div			ST	R0	SAVE_R0_	; 被调用者保存
			ST	R1	SAVE_R1_
			ST	R2	SAVE_R2_
			LD	R0	TEMP0		;余数
			AND	R1	R1	#0		;积
DIV_LOOP	ADD	R2	R0	#-6
			BRn	DIV_END
			ADD	R1	R1	#1
			AND	R0	R2	R2
			BRp	DIV_LOOP
DIV_END		ST	R1	TEMP1
			ST	R0	TEMP2
			LD	R0	SAVE_R0_	; 被调用者恢复
			LD	R1	SAVE_R1_
			LD	R2	SAVE_R2_
			RET

ENDLINE1	.FILL	0x0D
;
;main function
;
main		AND	R1	R1	#0
			ADD	R1	R1	#1		;落子方标记,1=player1,-1=player2
MAIN_LOOP	JSR	print
			JSR isTie
			LD	R2	TEMP1		;R2用于胜负判断
			ADD	R2	R2	#0
			BRnp	tie
			ADD	R1	R1	#0
			BRn	P2_DO
P1_DO		LEA	R0	PLAY_1
			TRAP	x22
			BRnzp	MAIN_JUDGE
P2_DO		LEA	R0	PLAY_2
			TRAP	x22
MAIN_JUDGE	TRAP x20
			TRAP x21
			ADD R0	R0	#-16
			ADD R0	R0	#-16
			ADD R0	R0	#-16	;index = ascii_code - 48
			ADD	R3	R0	#-1		;index in function is from 0 to 5 in every line
			LD	R0	ENDLINE1
			TRAP	x21
			ST	R3	TEMP0
			ST	R1	TEMP1		;we need a input
			ADD	R1	R1	#0
			BRn	P2_DO_1
P1_DO_1		JSR	play1
			BRnzp	P_DO_END1
P2_DO_1		JSR	play2
P_DO_END1	LD	R3	TEMP0
			ADD	R3	R3	#0
			BRzp	MAIN_RIGHT
MAIN_ERROR	;LEA	R0	ERROR
			;TRAP	x22
			BRnzp	MAIN_LOOP
MAIN_RIGHT	ST	R1	TEMP1
			ST	R3	TEMP0
			JSR	isOver
			LD	R4	TEMP0
			ADD	R4	R4	#0
			BRnp	GAME_OVER
			NOT	R1	R1
			ADD	R1	R1	#1
			BRnzp	MAIN_LOOP
GAME_OVER	JSR	print
			ADD	R1	R1	#0
			BRp	p1_win
			BRn	p2_win
;
;三种结局,最终分别调用这三种函数
;
tie			LEA R0	TIE
			TRAP	x22
			HALT	
p1_win		LEA R0	P_1_WIN
			TRAP	x22
			HALT
p2_win		LEA R0	P_2_WIN
			TRAP	x22
			HALT

;
;常用字符串和常量
;
    PLAY_1  .STRINGZ    "Player 1, choose a column: "
    PLAY_2  .STRINGZ    "Player 2, choose a column: "
    P_1_WIN .STRINGZ    "Player 1 Wins.\n"
    P_2_WIN .STRINGZ    "Player 2 Wins.\n"
	TIE		.STRINGZ	"Tie Game.\n"

.END

Guess you like

Origin blog.csdn.net/weixin_46655675/article/details/130810126