05 魔方

1. 前言

这个题是当初要面试的时候,在一个网友的播客中看到的面试题, 当时也比较感兴趣, 于是 当时就把这个模拟的数据结构写好了
这个实际上写了已经很久了,所以可能注释, 代码风格等信息可能不是那么的好看

设计思路 : 这个不难模拟, 但是比较烦, 有兴趣的网友也可以试一下, 比较重视细节的, 稍不注意, 就要狠狠的找了

元素介绍
假设魔方的6个面为 顺时针 1, 3, 2, 4, 顶上为5, 底下为6
切换当前面的规律为[向四周的切换] 1, 2, 3, 4逆时针切换, [向上的切换]5逆时针切换, [向下的切换]6顺时针切换[turnXX方法]

上下左右的四个方向按钮为转动相应的方格的的行
右上角的四个方向按钮为调整视角的按钮

游戏画面 : 这里写图片描述

2. 基本的数据结构介绍

2.1 Cube : 核心的魔方Model, 主要包含了, 上下左右方向上的调整一整行/ 列, 以及调整用户的正面

    // 假设魔方的6个面为 顺时针 1, 3, 2, 4, 顶上为5, 底下为6
    // 切换当前面的规律为[向四周的切换] 1, 2, 3, 4逆时针切换, [向上的切换]5逆时针切换, [向下的切换]6顺时针切换[turnXX方法]
    static class Cube {
        // 魔方的面数, 每一面的网格数, 每一面的编程
        public static final int FACE_NUM = 6;
        public static final int GRID_NUM = 9;
        public static final int GRID_SIDE_LEN = (int) Math.sqrt(GRID_NUM);
        // 1 - 6 面  以及各个颜色
        public static final int ONE = 1;
        public static final int TWO = 2;
        public static final int THREE = 3;
        public static final int FOUR = 4;
        public static final int FIVE = 5;
        public static final int SIX = 6;
        public static final Color[] COLORS = {Color.GREEN, Color.BLUE, Color.RED, Color.ORANGE, Color.WHITE, Color.YELLOW };

        // 上下左右
        public static final int UP = 0;
        public static final int RIGHT = 1;
        public static final int LEFT = 2;
        public static final int DOWN = 3;

        // data存储各个面的各个方格的颜色, faceNow表示现在面向我们的一面
        // isHorizon表示得到当前这面是是通过水平旋转得到的
        // isClockWise表示得到当前这面是通过顺时针旋转得到的
        // lastFace得到当前这面的上一个faceNow
        Color[][] data;
        int faceNow;
        int faceRight;
        int faceUp;

        // 初始化
        public Cube() {
            init();
            faceNow = 0;
            faceRight = 2;
            faceUp = 4;
        }

        // 初始化data
        private void init() {
            data = new Color[FACE_NUM][GRID_NUM];
            for(int face=0; face<data.length; face++) {
                for(int grid=0; grid<data[0].length; grid++) {
                    data[face][grid] = COLORS[face];
                }
            }
        }

        // 打印信息
        public void print() {
            int[] dirs = new int[]{getNow(), getUp(), getRight(), getOpposite(), getLeft(), getDown() };
            for(int i=0; i<dirs.length; i++) {
                print(dirs[i], data[dirs[i]]);
            }
        }

        // assistMethod
        private void print(int face, Color[] colors2) {
            Log.log("the " + (face+1) + "th face : ");
            int idx = 0;
            for(int i=0; i<GRID_SIDE_LEN; i++) {
                for(int j=0; j<GRID_SIDE_LEN; j++) {
                    Log.logWithoutLn(colors2[idx++] + " ");
                }
                Log.enter();
            }
        }

        // 获取当前面的数据的坐标
        public int getNow() {
            return faceNow;
        }

        // 获取上面的数据的坐标
        public int getUp() {
            return faceUp;
        }

        // 获取右面的数据的坐标
        public int getRight() {
            return faceRight;
        }

        // 获取正对面的背面面的数据的坐标
        public int getOpposite() {
            return getOpposite(faceNow);
        }

        // 获取左面的数据的坐标
        public int getLeft() {
            return getOpposite(faceRight);
        }

        // 获取下面的数据的坐标
        public int getDown() {
            return getOpposite(faceUp);
        }

        // 返回该面的对面  三个相对的面依次为0 1, 2 3, 4 5, 所以可以以下方式求得
        private int getOpposite(int face) {
            int idx = -1;
            if((face & 1) != 0) {
                idx = face - 1;
            } else {
                idx = face + 1;
            }

            return idx;
        }

        // 向上转动画面  令下面正对我们
        public void turnUp() {
            int tmp = faceNow;
            faceNow = getOpposite(faceUp);
            faceUp = tmp;
        }

        // 向右转动画面  令左面正对我们
        public void turnRight() {
            int tmp = faceNow;
            faceNow = getOpposite(faceRight);
            faceRight = tmp;
        }

        // 向下转动画面  令上面正对我们
        public void turnDown() {
            int tmp = faceNow;
            faceNow = faceUp;
            faceUp = getOpposite(tmp);
        }

        // 向左转动画面  令右面正对我们
        public void turnLeft() {
            int tmp = faceNow;
            faceNow = faceRight;
            faceRight = getOpposite(tmp);
        }

        // 将 (col) 列向上转动
        public void rotateUp(int col) {
            Color[] tmp = null;
            tmp = getCol(getNow(), col);
            putCol(getNow(), col, getCol(getDown(), col) );
            putCol(getDown(), col, getCol(getOpposite(), col) );
            putCol(getOpposite(), col, getCol(getUp(), col) );
            putCol(getUp(), col, tmp );
        }

        // 将 (row) 行向右转动
        public void rotateRight(int row) {
            Color[] tmp = null;
            tmp = getRow(getNow(), row);
            putRow(getNow(), row, getRow(getLeft(), row) );
            putRow(getLeft(), row, getRow(getOpposite(), row) );
            putRow(getOpposite(), row, getRow(getRight(), row) );
            putRow(getRight(), row, tmp );
        }

        // 将 (col) 列向上转动
        public void rotateDown(int col) {
            Color[] tmp = null;
            tmp = getCol(getNow(), col);
            putCol(getNow(), col, getCol(getUp(), col) );
            putCol(getUp(), col, getCol(getOpposite(), col) );
            putCol(getOpposite(), col, getCol(getDown(), col) );
            putCol(getDown(), col, tmp );
        }

        // 将 (row) 行向左转动
        public void rotateLeft(int row) {
            Color[] tmp = null;
            tmp = getRow(getNow(), row);
            putRow(getNow(), row, getRow(getRight(), row) );
            putRow(getRight(), row, getRow(getOpposite(), row) );
            putRow(getOpposite(), row, getRow(getLeft(), row) );
            putRow(getLeft(), row, tmp );
        }

        // 获取某一面的数据[索引 : 0-8]
        public Color[] getByFace(int face) {
            Color[] faceNow = data[face];
            return faceNow;
        }

        // 获取第face面的row行的数据
        private Color[] getRow(int face, int row) {
            Color[] tmp = new Color[GRID_SIDE_LEN];
            Color[] faceNow = data[face];
            int idx = row * GRID_SIDE_LEN;
            for(int i=0; i<GRID_SIDE_LEN; i++) {
                tmp[i] = faceNow[idx ++];
            }

            return tmp;
        }

        // 设置第face面的row行的数据
        private void putRow(int to, int row, Color[] putData) {
            Color[] faceTo = data[to];
            int idx = row * GRID_SIDE_LEN;
            for(int i=0; i<GRID_SIDE_LEN; i++) {
                faceTo[idx ++] = putData[i];
            }
        }

        // 获取第face面的col列的数据
        private Color[] getCol(int face, int col) {
            Color[] tmp = new Color[GRID_SIDE_LEN];
            Color[] faceNow = data[face];
            int idx = col;
            for(int i=0; i<GRID_SIDE_LEN; i++) {
                tmp[i] = faceNow[idx];
                idx += GRID_SIDE_LEN;
            }

            return tmp;
        }

        // 设置第face面的col列的数据
        private void putCol(int to, int col, Color[] putData) {
            Color[] faceTo = data[to];
            int idx = col;
            for(int i=0; i<GRID_SIDE_LEN; i++) {
                faceTo[idx] = putData[i];
                idx += GRID_SIDE_LEN;
            }
        }

    }

2.2 Color : 各个颜色的枚举

    // 魔方颜色的 枚举 [红/ 绿/ 蓝/ 黄/ 橙/ 白]
    public enum Color {
        RED("red", java.awt.Color.RED), GREEN("green", java.awt.Color.GREEN), BLUE("blue", java.awt.Color.BLUE), YELLOW("yellow", java.awt.Color.YELLOW), ORANGE("orange", java.awt.Color.ORANGE), WHITE("white", java.awt.Color.WHITE);

        private String name;
        private java.awt.Color color;

        private Color(String name, java.awt.Color color) {
            this.name = name;
            this.color = color;
        }
    }

3 下载链接 [包含图片, 源码] :
http://download.csdn.net/detail/u011039332/9016445
这里写图片描述

运行时截图 :
ps : 因为截图软件的原因, 所以看起来并不符合常理, 但是真实能看见的是合理的
这里写图片描述
这里写图片描述

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值