井字棋 二维数组java_GitHub - java-a/lab7: 进击的井字棋 / Advanced Tic-tac-toe
lab7
使用二维数组实现 lab5 的“井字棋”小游戏,实现悔棋和撤销悔棋,并了解注释的书写。
Deadline:2016.11.04 23:59:59(UTC+8)。
问题描述
约定
使用命令行读入控制信息及输出棋盘,棋盘中用.表示空位,O和X表示两位玩家。
两位玩家交替输入一个[0, 8]闭区间中的正整数,表示落子位置(如0表示第一排第一个坑,5表示第二排正中那个坑,8表示第三排最后一个坑)。具体的对应关系如下所示:
0 1 2
3 4 5
6 7 8
玩家输入n个u(undo),回到n步之前的状态。如u表示回到上一步的状态,uuu表示回到三步前的状态。注意,悔棋后落子的玩家可能会发生变化(如悔棋1步后当前玩家可能从X变为O)。
玩家输入n个r(redo),撤销n步悔棋。如r表示回到下一步的状态,rrr表示回到三步后的状态。注意,撤销悔棋后落子的玩家可能会发生变化(如撤销悔棋1步后当前玩家可能从X变为O)。另外,可能会出现无法撤销悔棋的情况,如试图撤销的步数超过之前悔棋的步数,或上一次落子后尚未悔棋。
输入不要求合法性判断,仅考虑上述三种情况。可以在多次输入中连续悔棋、撤销悔棋,或交替使用。
要求
实现基本的“井字棋”的游戏逻辑(可以参考最后的起始代码)。
使用方法分离不同作用的代码块。
使用二维数组保存棋盘状态。
实现悔棋与撤销悔棋(优先实现悔棋,若时间上来不及撤销悔棋可留到课后)。
使用良好的代码风格和适当的注释。
起始代码
下面的起始代码为助教提供的 lab5 参考实现。你可以在这份代码的基础上进行修改,以完成本次 lab 提出的要求;也可以按照自己的编码习惯独立完成。
import java.util.Scanner;
public class TicTacToe {
public static void main(String[] args) {
char[][] board = {{'.', '.', '.'}, {'.', '.', '.'}, {'.', '.', '.'}};
boolean player = true;
Scanner scanner = new Scanner(System.in);
while (true) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(board[i][j]);
}
System.out.println();
}
System.out.print("Next move: ");
int nextPosition = scanner.nextInt();
board[nextPosition / 3][nextPosition % 3] = (player) ? 'O' : 'X';
player = !player;
}
}
}
Tips
棋盘历史记录的保存:由于我们使用二维数组来保存棋盘状态,因此我们可以使用更高一维的数组来表示所有棋盘的历史状态。在这里boardHistory[0]表示棋盘初始状态,boardHistory[3]表示进行到第3步时的状态。
char[][] board = {{'.', '.', '.'}, {'.', '.', '.'}, {'.', '.', '.'}};
char[][][] boardHistory = new char[10][][];
多维数组的复制:可以通过循环来实现多维数组的深复制。
private static char[][] copyArray(char[][] array) {
char[][] newArray = new char[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
newArray[i][j] = array[i][j];
}
}
return newArray;
}
用法:
board = TicTacToe.copyArray(boardHistory[nextStep]);
棋盘状态的记录方法(供参考):使用两个变量来分别记录当前步数currentStep和可以通过撤销悔棋回到的最大步数lastStep。
初始状态时,currentStep与lastStep相等为0。
执行悔棋时,若即将回到的步数nextStep是否大于等于0则可以执行悔棋,将currentStep修改为nextStep。
执行撤销悔棋时,若即将回到的步数nextStep是否小于等于lastStep则可以执行撤销悔棋,将currentStep修改为nextStep。
执行走棋时,清空currentStep到lastStep之间的棋盘状态。随后currentStep自增,lastStep与currentStep相等。
代码风格和注释
PJ 约定的代码风格详见 lab3 中的 Java Style Guide 。注意,提交的代码中若不符合该约定将会被酌情扣分。在这个 lab 中,着重强调以下几点:
缩进
在IntelliJ IDEA中,你可以使用 Ctrl + Alt + L (Windows)或 Option + Command + L(MacOS)来自动格式化代码。
变量命名
在Java中,我们使用驼峰命名法。类名应该以大写字母开头,变量名应以小写字母开头,杜绝中文字符。 正确示例(类名):TicTacToe。错误示例(类名):tic-tac-toe、tic_tac_toe、AnimalFight_landscape。
变量命名必须有意义。正确示例(变量名):nextPosition(下一个落子位置)、gameHistory(历史记录对象的一个实例)、animals(储存所有动物的数组)。错误示例:count_step_for_all、animals$int$2、player2animals$int$2。
代码注释
PJ 中的注释可以参照下面的格式。
文件开头的注释。IntelliJ在新建一个Java文件后会自动生成一段注释。这段注释中应包括作者、创建时间和该文件的主要内容。
/**
* Created by Zhongyi on 01/11/2016.
* This file contains.../ is used to ...
*/
类前的注释。表明类的职责。
/**
* Class Object is the root of the class hierarchy.
* Every class has Object as a superclass. All objects,
* including arrays, implement the methods of this class.
*/
public class Object {}
方法前的注释。表明方法的作用,描述参数和返回值的含义。实例中的Examples和@exception视情况可选。
/**
* Returns a new string that is a substring of this string. The
* substring begins with the character at the specified index and
* extends to the end of this string.
*
* Examples:
* "unhappy".substring(2) returns "happy"
* "Harbison".substring(3) returns "bison"
* "emptiness".substring(9) returns "" (an empty string)
*
* @param beginIndex the beginning index, inclusive.
* @return the specified substring.
* @exception IndexOutOfBoundsException if
* beginIndex is negative or larger than the
* length of this String object.
*/
public String substring(int beginIndex) {
return substring(beginIndex, count);
}
- 代码块中的注释。此处的注释应该用于阐述一段代码**为什么**要这样写,而不是在做什么。当且仅当代码本身无法让读者一眼明白在做什么时,才需要解释代码的作用。
```java
// Check if the input is valid
if (...) {}
Code Review
提交
Deadline延长至2016.11.04 23:59:59(UTC+8)。迟交酌情扣分。
将代码打包,以学号_姓名.文件类型的格式命名,如13302010039_童仲毅.zip。上传至FTP:
ftp://10.132.141.33/classes/16/161 程序设计A (戴开宇)/WORK_UPLOAD/lab7
Lab6的Code Review文档请上传至:
ftp://10.132.141.33/classes/16/161 程序设计A (戴开宇)/WORK_UPLOAD/Code Review/lab6