立方體滾動
一個立方體每個面都有一種顏色芹彬,顏色分別用 1,2,3,4,5,6
表示,立方體在一塊 n*n
的方格棋盤上滾動叉庐,棋盤上的格子會被立方體的底面染色舒帮,給出棋盤的維度大小及立方體在棋盤上的滾動路徑,輸出路徑上格子的顏色陡叠。
立方體初始狀態(tài)及下面示例的輸入對應路徑如下圖:
輸入:
5
S # # # .
. . . # .
E # . # #
. # . . #
. # # # #
說明:
第一行輸入一個整數(shù)
n
玩郊,代表棋盤的維度是n*n
之后有
n
行輸入,表示棋盤上的占位符枉阵,各符號有如下含義:
S
译红,表示起點#
,表示立方體經(jīng)過該格子.
兴溜,表示棋盤上其他的格子(不在立方體路徑上)
注意:由于只用字符表示路徑上的位置临庇,并不知道滾動位置的先后順序,故必須對輸入有要求:只能夠由輸入推斷得到一條路徑昵慌,不能產(chǎn)生歧義假夺,否則視為不合法的輸入
代碼:
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; // 使用二維數(shù)組表示棋盤
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 的右側(cè)是否是下一個位置
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循環(huán)跳出時穿稳,立方體在終點沒有將底面的值記錄到棋盤上
// 在這里記錄
board.board[x][y] = String.valueOf(cube.down).charAt(0);
board.printBoard();
}
}
示例輸入的結(jié)果:
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