立方体滚动
一个立方体每个面都有一种颜色,颜色分别用 1,2,3,4,5,6
表示,立方体在一块 n*n
的方格棋盘上滚动,棋盘上的格子会被立方体的底面染色,给出棋盘的维度大小及立方体在棋盘上的滚动路径,输出路径上格子的颜色。
立方体初始状态及下面示例的输入对应路径如下图:
输入:
5
S # # # .
. . . # .
E # . # #
. # . . #
. # # # #
说明:
第一行输入一个整数
n
,代表棋盘的维度是n*n
之后有
n
行输入,表示棋盘上的占位符,各符号有如下含义:
S
,表示起点#
,表示立方体经过该格子.
,表示棋盘上其他的格子(不在立方体路径上)
注意:由于只用字符表示路径上的位置,并不知道滚动位置的先后顺序,故必须对输入有要求:只能够由输入推断得到一条路径,不能产生歧义,否则视为不合法的输入
代码:
import java.util.Scanner;
class Cube {
int up = 1;
int down = 6;
int left = 5;
int right = 2;
int front = 3;
int back = 4;
public void rollRight() { // 向右滚动
int t1 = 0, t2 = 0; // 临时变量,用于保存被覆盖的值
t1 = down;
down = right; // 底面由之前的右面替代
t2 = left;
left = t1; // 左面由之前的下面替代
t1 = up;
up = t2; // 上面由之前的左面替代
right = t1; // 右面由之前的上面替代
// 前面和后面都不会变
}
// 下面的滚动与上面的操作是类似的,不再注释
public void rollLeft() {
int t1 = 0, t2 = 0;
t1 = down;
down = left;
t2 = right;
right = t1;
t1 = up;
up = t2;
left = t1;
}
public void rollUp() {
int t1 = 0, t2 = 0;
t1 = down;
down = back;
t2 = front;
front = t1;
t1 = up;
up = t2;
back = t1;
}
public void rollDown() {
int t1 = 0, t2 = 0;
t1 = down;
down = front;
t2 = back;
back = t1;
t1 = up;
up = t2;
front = t1;
}
// 用于测试,方便打印立方体
@Override
public String toString() {
return "Cube [up=" + up + ", down=" + down + ", left=" + left + ", right=" + right + ", front=" + front
+ ", back=" + back + "]";
}
}
class Position { // 棋盘上坐标的抽象
int x = 0;
int y = 0;
Position(int x, int y) {
this.x = x;
this.y = y;
}
// 用于测试,方便打印位置
@Override
public String toString() {
return "Position [x=" + x + ", y=" + y + "]";
}
}
class Board { // 棋盘抽象
char[][] board; // 使用二维数组表示棋盘
boolean[][] visited; // 用于表示棋盘上的位置是否被访问过,visited[i][j]=true 表示坐标 (i,j) 被访问过,否则没访问过
// up:1
// down:2
// left:3
// right:4
short[][] nextDirection; // 棋盘上每个位置上的下一个滚动的方向,nextDirection[i][j]=1 表示在 (i,j) 时下一个方向要向上滚动
int dimension = 0; // 棋盘的维度
Board(int n) { // 初始化
board = new char[n][n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
board[i][j] = '.';
}
visited = new boolean[n][n];
nextDirection = new short[n][n];
dimension = n;
}
Position getStartPosition() { // 找出起始位置
for (int i = 0; i < dimension; i++) {
for (int j = 0; j < dimension; j++) {
if (board[i][j] == 'S') {
visited[i][j] = true;
return new Position(i, j);
}
}
}
throw new RuntimeException("invalid rolling path : no start");
}
Position getNextPosition(Position pos) { // 在位置 pos 时,其下一个滚动到的位置
int i = pos.x, j = pos.y;
Position resPosition = null;
// 检查 pos 的右侧是否是下一个位置
if (j < board.length - 1 && board[i][j + 1] != '.' && visited[i][j + 1] == false) {
nextDirection[i][j] = 4; // 当前位置 pos 的下一个方向就是向右
resPosition = new Position(i, j + 1);
} else if (j > 0 && board[i][j - 1] != '.' && visited[i][j - 1] == false) {
nextDirection[i][j] = 3;
resPosition = new Position(i, j - 1);
} else if (i < board.length - 1 && board[i + 1][j] != '.' && visited[i + 1][j] == false) {
nextDirection[i][j] = 2;
resPosition = new Position(i + 1, j);
} else if (i > 0 && board[i - 1][j] != '.' && visited[i - 1][j] == false) {
nextDirection[i][j] = 1;
resPosition = new Position(i - 1, j);
} else {
throw new RuntimeException("invalid rolling path");
}
visited[i][j] = true; // 标记当前位置 pos 被访问过
return resPosition;
}
void printBoard() { // 打印棋盘
for (int i = 0; i < dimension; i++) {
for (int j = 0; j < dimension; j++) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
}
}
public class RollingCube {
public static void main(String[] args) {
Cube cube = new Cube();
Board board;
Scanner in = new Scanner(System.in);
int n = in.nextInt(); // 棋盘维度从键盘输入获取
board = new Board(n);
// 将输入的路径记录在棋盘中
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
board.board[i][j] = in.next().charAt(0);
}
}
board.printBoard();
Position pos = board.getStartPosition(); // 找到起始位置
int x = pos.x, y = pos.y;
while (board.board[x][y] != 'E') { // 只要没到终点,一直滚动
board.board[x][y] = String.valueOf(cube.down).charAt(0); // 将立方体的下面(底面)的值记录到棋盘上
pos = board.getNextPosition(pos); // 下一个滚动位置
switch (board.nextDirection[x][y]) { // 下一个方向往哪滚动
case 1:
cube.rollUp();
break;
case 2:
cube.rollDown();
break;
case 3:
cube.rollLeft();
break;
case 4:
cube.rollRight();
break;
}
// 滚动到下一个位置
x = pos.x;
y = pos.y;
}
// 上面while循环跳出时,立方体在终点没有将底面的值记录到棋盘上
// 在这里记录
board.board[x][y] = String.valueOf(cube.down).charAt(0);
board.printBoard();
}
}
示例输入的结果:
6 2 1 5 .
. . . 3 .
1 2 . 2 6
. 4 . . 4
. 5 6 2 1
测试用例输入:
5
# # # # #
# . . . #
# . S # #
# . . . .
# # # # E
预期输出:
6 5 1 2 6
4 . . . 4
1 . 6 2 1
3 . . . .
6 5 1 2 6
程序输出:
6 5 1 2 6
4 . . . 4
1 . 6 2 1
3 . . . .
6 5 1 2 6