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, 所以请大家指出!