模擬立方體的滾動并記錄路徑

立方體滾動

一個立方體每個面都有一種顏色芹彬,顏色分別用 1,2,3,4,5,6 表示,立方體在一塊 n*n 的方格棋盤上滾動叉庐,棋盤上的格子會被立方體的底面染色舒帮,給出棋盤的維度大小及立方體在棋盤上的滾動路徑,輸出路徑上格子的顏色陡叠。

立方體初始狀態(tài)及下面示例的輸入對應路徑如下圖:

cube-roll.png

輸入:

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 
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市晌坤,隨后出現(xiàn)的幾起案子逢艘,更是在濱河造成了極大的恐慌,老刑警劉巖骤菠,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件它改,死亡現(xiàn)場離奇詭異,居然都是意外死亡商乎,警方通過查閱死者的電腦和手機央拖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鹉戚,“玉大人鲜戒,你說我怎么就攤上這事∧ǖ剩” “怎么了袍啡?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長却桶。 經(jīng)常有香客問我境输,道長,這世上最難降的妖魔是什么颖系? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任嗅剖,我火速辦了婚禮,結(jié)果婚禮上嘁扼,老公的妹妹穿的比我還像新娘信粮。我一直安慰自己,他們只是感情好趁啸,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布强缘。 她就那樣靜靜地躺著,像睡著了一般不傅。 火紅的嫁衣襯著肌膚如雪旅掂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天访娶,我揣著相機與錄音商虐,去河邊找鬼。 笑死,一個胖子當著我的面吹牛秘车,可吹牛的內(nèi)容都是我干的典勇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼叮趴,長吁一口氣:“原來是場噩夢啊……” “哼割笙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起眯亦,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤伤溉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后搔驼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谈火,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡侈询,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年舌涨,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扔字。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡囊嘉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出革为,到底是詐尸還是另有隱情扭粱,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布震檩,位于F島的核電站琢蛤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏抛虏。R本人自食惡果不足惜博其,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望迂猴。 院中可真熱鬧慕淡,春花似錦、人聲如沸沸毁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽息尺。三九已至携兵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間搂誉,已是汗流浹背眉孩。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浪汪。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓巴柿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親死遭。 傳聞我的和親對象是個殘疾皇子广恢,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348