这是一个带自动还原算法的魔方小游戏,标准的七步还原法。适合初学者,可以一步步执行,也可以输入公式执行。魔方的每个小面上附加了一些装饰模型,直接在3dsmax中做好导出即可很方便配置。
魔方笼统的分为两大类:
1,正阶魔方,正阶魔方最常见的是三阶魔方,有些看起来比较怪异的魔方比如镜面魔方和移楞魔方也属于正三阶魔方,因为转法是一样的。
2,异形魔方,比如SQ1,金字塔,五魔方。
图 镜面魔方
图 移楞魔方(用圆柱魔方代替,只不过是模型不同而已)
魔方标准解法:
正三阶魔方:七步还原法
1,底层十字
2,底层角块
3,第二层楞块 (五转四回公式).
4,顶层十字 (R'U'F' UFR + 小鱼公式)
5,顶层角块顶面(小鱼公式R'U'RU' R'U'U'R)
6,顶层角块侧面(公式LF'LBB L'FLBB LL)
7,顶层楞块侧面(FF ULR'FFL'R UFF)
正四阶魔方:仅需要比正三阶多记忆一个公式
1,将6个面的4个中心块拼成颜色一致。
2,将12条楞的中间2个棱块拼成颜色一致。(公式)
3,按正三阶魔方的方法完成接下来的工作。
SQ1魔方:
1,先还原到立方体(异形魔方的公式也是比较异形的)
2,还原颜色
金字塔魔方:
1,先还原4个角块
2,还原楞块(交叉拧底部两个角和楞)
五魔方:公式比较多,但是有些公式跟正三阶很像。
降群法还原魔方:kociemba,IDA*。
魔方最小步数解法:
正三阶魔方的上帝之数为20,意思是说任何正三阶魔方打乱状态都可以在20步之内还原。
也就是说用深度优先搜索算法求解时可以限制递归深度为20。
如果直接遍历搜索可能会需要很长时间,需要一些优化方法。
比如先列举N步内所能打乱的状态,在求解还原时只要找到这些列举状态中的一个即可,这样就把搜索的深度减少到了20-N。
网上有一些经过优化的算法可以达到在几十毫秒内搜索到二三十步还原的目标。
玩家基类:
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/MagicSquare/MagicSquare.h
// @Brief: MagicSquare
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#ifndef __MagicSquarePlayer__H__
#define __MagicSquarePlayer__H__
#include "Rpg/MiniGame.h"
namespace RendSys
{
class Frame;
}
struct AABB;
enum Axis{X,Y,Z};
enum ChunkIndex{NEGATIVE,MIDDLE,POSITIVE};
enum RotateDir{CLOCKWISE,COUNTERCLOCKWISE,NOROTATE};
//6个面
enum FaceDir{FRONT,BACK,LEFT,RIGHT,UP,DOWN,NOASPECT};
enum FaceColor
{
BLUE ,
GREEN ,
RED ,
ORANGE,
WHITE ,
YELLOW,
GRAY
};
//小面
class Facelet
{
public:
FaceDir asp;
int index;
FaceColor color;
Facelet()
:asp(NOASPECT),index(-1),color(GRAY)
{}
};
//棱块
class Edge
{
public:
Facelet faceletMain;
Facelet faceletSide;
};
//角块
//class Corner
//{
//public:
// Facelet faceletMain;
// Facelet facelet1;
// Facelet facelet2;
//};
class MagicSquareSolver
{
public:
MagicSquareSolver();
MagicSquareSolver(MagicSquareSolver& other);
virtual void Reset();
virtual void Random();
bool IsValidLayout();
void GetFacelet4(Facelet* facelet,FaceColor color);
Facelet GetNeighborEdgeFacelet(Facelet facelet);
void GetNeighborCornerFacelets(Facelet* neighbor2,Facelet facelet);
Edge GetEdge(FaceColor colorMain,FaceColor colorSide);
//第一层十字
bool IsCrossed();
void Cross();
//第一层角
bool IsFirstLayerCornerRestored();
void Layer1Corner();
//第二层棱
bool IsSecondLayerEdgeRestored();
void Layer2Edge();
//前两层
bool IsF2L();
void F2L();
//第三层十字
bool IsTopCrossed();
void TopCross();
//1:fewer formulas method
bool IsTopCrossMatched();
void MatchTopCross();
bool IsTopCornerBack();
bool IsTopCornerBack(Facelet f);
int HashCorner(FaceColor c1,FaceColor c2,FaceColor c3);
void BackTopCorner();
bool IsTopCornerRestored();
void RestoreTopCorner();
void MethodFewerFormula();
//2:standard cfop method
void HashOLL(char*);
bool IsTopFaceRestored();
void OLL();
void HashPLL(char*);//not finished
void PLL();
void CFOP();
typedef void (MagicSquareSolver::*RotateFun)(int flag);
static RotateFun RotateFunTable[3][3][2];
static const char* RotateFunNameTable[3][3][2];
//==================^_^
//look from positive to negative along axis to decide clockwise or not
virtual void rotateFullAspectCW(FaceDir asp, int* index);
virtual void rotateFullAspectACW(FaceDir asp, int* index);
virtual void rotateXLeftCW(int flag=3);
virtual void rotateXLeftACW(int flag=3);
virtual void rotateXRightCW(int flag=3);
virtual void rotateXRightACW(int flag=3);
virtual void rotateXMiddleCW(int flag=3);
virtual void rotateXMiddleACW(int flag=3);
virtual void rotateYDownCW(int flag=3);
virtual void rotateYDownACW(int flag=3);
virtual void rotateYUpCW(int flag=3);
virtual void rotateYUpACW(int flag=3);
virtual void rotateYMiddleCW(int flag=3);
virtual void rotateYMiddleACW(int flag=3);
virtual void rotateZFrontCW(int flag=3);
virtual void rotateZFrontACW(int flag=3);
virtual void rotateZBackCW(int flag=3);
virtual void rotateZBackACW(int flag=3);
virtual void rotateZMiddleCW(int flag=3);
virtual void rotateZMiddleACW(int flag=3);
//==================^_^
void F();
void Fr();
void B();
void Br();
void R();
void Rr();
void L();
void Lr();
void U();
void Ur();
void D();
void Dr();
//rotate middle layer along y axis
void E ();
void Er();
void E2();
//rotate middle layer along x axis
void M ();
void Mr();
void M2();
//rotate middle layer along z axis
void S ();
void Sr();
void S2();
void F2();
void B2();
void R2();
void L2();
void U2();
void D2();
//rotate whole cube along x axis
void x();
void xr();
void x2();
//rotate whole cube along y axis
void y();
void yr();
void y2();
//rotate whole cube along z axis
void z();
void zr();
void z2();
//rotate top two layer
void u();
void ur();
void u2();
//rotate right two layer
void r();
void rr();
void r2();
//rotate front two layer
void f();
void fr();
void f2();
//rotate down two layer
void d();
void dr();
void d2();
//rotate left two layer
void l();
void lr();
void l2();
//rotate back two layer
void b();
void br();
void b2();
void Execute(const char* cmd);
void SaveFromFile();
void LoadFromFile();
FaceColor m_blockColors[6][9];
//
char m_history[1024];
int m_historyNum;
};
//多阶正魔方很容易扩展,但自动求解算法比较难
//异形魔方 旋转面不再是AABB 旋转轴心 旋转的角度不再是90度 可能带绑定(限制转动)
//todo 3个观察镜面
class MagicSquarePlayer: public MiniPlayer,public MagicSquareSolver
{
public:
MagicSquarePlayer();
virtual ~MagicSquarePlayer();
virtual bool Start();
virtual bool Stop();
virtual void Update();
virtual void Render();
FaceDir GetAspect(const vec2I& point);
int GetSmallAspectIndex(FaceDir asp,const vec2I& point);
bool IsInThisRect(vec2I* pts,const vec2I& point);
virtual void Reset();
void OnRandom();
void OnSolution();
void OnExecute(const char* str);
void OnStopExecute();
typedef void (MagicSquarePlayer::*RotateFun)(int flag);
static RotateFun RotateFunTable[3][3][2];
//==================^_^
void AnimRotate(float ang);
void BackupFrame(const AABB& bound);
void RestoreFrame();
void rotate3D(const AABB& bound,const vec3& axis);
//look from positive to negative along axis to decide clockwise or not
virtual void rotateFullAspectCW(FaceDir asp, int* index);
virtual void rotateFullAspectACW(FaceDir asp, int* index);
virtual void rotateXLeftCW(int flag=3);
virtual void rotateXLeftACW(int flag=3);
virtual void rotateXRightCW(int flag=3);
virtual void rotateXRightACW(int flag=3);
virtual void rotateXMiddleCW(int flag=3);
virtual void rotateXMiddleACW(int flag=3);
virtual void rotateYDownCW(int flag=3);
virtual void rotateYDownACW(int flag=3);
virtual void rotateYUpCW(int flag=3);
virtual void rotateYUpACW(int flag=3);
virtual void rotateYMiddleCW(int flag=3);
virtual void rotateYMiddleACW(int flag=3);
virtual void rotateZFrontCW(int flag=3);
virtual void rotateZFrontACW(int flag=3);
virtual void rotateZBackCW(int flag=3);
virtual void rotateZBackACW(int flag=3);
virtual void rotateZMiddleCW(int flag=3);
virtual void rotateZMiddleACW(int flag=3);
//==================^_^
//private:
enum PlayerState
{
None,
DragRotating,
AnimRotating,
ExecuteRotating,
};
static const int BlockSize=30;
vec2I m_offset;
//indexes for small aspects in a big aspect is in the order shown in 3d version
vec2I blockVertexes[6][9][4];//小面
vec2I aspectVertexes[6][4]; //大面
TexturePtr m_texture;
RectF m_colorTexRects[8];
//
PlayerState m_state;
bool m_dragRotDecided;
MovieClip* m_dragStartMovie;
vec3 m_dragBeginRegularPos;
vec3 m_dragBeginRegularNormal;
vec2 m_dragBeginMousePos;
vec2 m_dragDecideMousePos;
char m_executeStr[1024];
//
float RotSpeed;
float m_rotAnimAng;//m_rotAnimAng!=0 be rotating
vec3 m_rotAxis;
float m_rotPlane;
MovieClip* m_movieCube3;
MovieClip* m_movieSelect;
MovieClip* m_movieOrnament;
#define BlockNum 26
#define OrnamentNum 54*2 //装饰
Frame* m_blockFrames;
MovieClip* m_movieBlocks[BlockNum];
bool m_bBlockRotating[BlockNum];
MovieClip* m_movieOrnamentBlocks[OrnamentNum];
bool m_bOrnamentRotating[OrnamentNum];
Frame* m_ornamentFrames;
int m_ornamentBlockNum;
};
#endif
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/MagicSquare/MagicSquare.cpp
// @Brief: MagicSquare
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#include "General/Pch.h"
#include "General/Window.h"
#include "Math/MathLibAdvance.h"
#include "MagicSquare/MagicSquarePlayer.h"
#include "MagicSquare/MiniGameMagicSquare.h"
#include "General/Timer.h"
#include "Rpg/SyncGameInfo.h"
#include "Sound/SoundManager.h"
#include "Packet/PacketMiniGame.h"
#include "Render/RendDriver.h"
#include "Render/MC_MovieClip.h"
#include "Render/MC_Misc.h"
#include "General/Pce.h"
static FaceColor AspectColorOri[6][9] =
{
//front
{BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE},
//back
{GREEN, GREEN, GREEN, GREEN, GREEN, GREEN, GREEN, GREEN, GREEN},
//left
{RED, RED, RED, RED, RED, RED, RED, RED, RED},
//right
{ORANGE, ORANGE, ORANGE, ORANGE, ORANGE, ORANGE, ORANGE, ORANGE, ORANGE},
//up
{WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE},
//down
{YELLOW, YELLOW, YELLOW, YELLOW, YELLOW, YELLOW, YELLOW, YELLOW, YELLOW}
};
//==================^_^==================^_^==================^_^==================^_^
MagicSquareSolver::MagicSquareSolver()
{
for (int i=0;i<6;i++)
{
for (int j=0;j<9;j++)
{
m_blockColors[i][j] = AspectColorOri[i][j];
}
}
memset(m_history,0,sizeof(m_history));
m_historyNum = 0;
}
MagicSquareSolver::MagicSquareSolver(MagicSquareSolver& other)
{
for (int i=0;i<6;i++)
{
for (int j=0;j<9;j++)
{
m_blockColors[i][j] = other.m_blockColors[i][j];
}
}
memset(m_history,0,sizeof(m_history));
m_historyNum = 0;
}
void MagicSquareSolver::Reset()
{
memcpy(m_blockColors, AspectColorOri, sizeof(AspectColorOri));
m_history[0] = '\0';
m_historyNum = 0;
}
void MagicSquareSolver::Random()
{
Reset();
char buf[128] = "";
int scrambleNumber = 30;
while(scrambleNumber-- > 0)
{
//有多态
RotateFun fun = RotateFunTable[rand() % 3][rand() % 2 * 2][rand() % 2];
(this->*fun)(3);
//strcat(ra)
}
}
MagicSquareSolver::RotateFun MagicSquareSolver::RotateFunTable[3][3][2] =
{
//x from negative to positive,i.e. from left to right
{
{&MagicSquareSolver::rotateXLeftCW , &MagicSquareSolver::rotateXLeftACW},
{&MagicSquareSolver::rotateXMiddleCW, &MagicSquareSolver::rotateXMiddleACW},
{&MagicSquareSolver::rotateXRightCW , &MagicSquareSolver::rotateXRightACW}
},
//y
{
{&MagicSquareSolver::rotateYDownCW , &MagicSquareSolver::rotateYDownACW},
{&MagicSquareSolver::rotateYMiddleCW, &MagicSquareSolver::rotateYMiddleACW},
{&MagicSquareSolver::rotateYUpCW , &MagicSquareSolver::rotateYUpACW}
},
//z
{
{&MagicSquareSolver::rotateZBackCW , &MagicSquareSolver::rotateZBackACW},
{&MagicSquareSolver::rotateZMiddleCW, &MagicSquareSolver::rotateZMiddleACW},
{&MagicSquareSolver::rotateZFrontCW , &MagicSquareSolver::rotateZFrontACW}
},
};
const char* MagicSquareSolver::RotateFunNameTable[3][3][2] =
{
//x from negative to positive,i.e. from left to right
{
{"L'" , "L"},
{"M'" , "M"},
{"R'" , "R"}
},
//y
{
{"D'" , "D"},
{"E'" , "E"},
{"U'" , "U"}
},
//z
{
{"B'" , "B"},
{"S'" , "S"},
{"F'" , "F"}
},
};
//==================^_^==================^_^==================^_^==================^_^
//look from positive to negative along axis to decide clockwise or not
void MagicSquareSolver::rotateFullAspectCW(FaceDir asp, int* index)
{
FaceColor t[2];
for(int i = 0; i < 2; i++)
{
t[i] = m_blockColors[asp][index[i + 6]];
}
for(int i = 7; i > 1; i--)
{
m_blockColors[asp][index[i]] = m_blockColors[asp][index[i - 2]];
}
for(int i = 0; i < 2; i++)
{
m_blockColors[asp][index[i]] = t[i];
}
}
void MagicSquareSolver::rotateFullAspectACW(FaceDir asp, int* index)
{
FaceColor t[2];
for(int i = 0; i < 2; i++)
{
t[i] = m_blockColors[asp][index[i]];
}
for(int i = 0; i < 6; i++)
{
m_blockColors[asp][index[i]] = m_blockColors[asp][index[i + 2]];
}
for(int i = 0; i < 2; i++)
{
m_blockColors[asp][index[i + 6]] = t[i];
}
}
void MagicSquareSolver::rotateXLeftCW(int flag)
{
int index[9] = {6, 7, 8, 5, 2, 1, 0, 3};
rotateFullAspectCW(LEFT, index);
//front ,down,back,up
for(int i = 0; i <= 6; i += 3)
{
FaceColor t = m_blockColors[FRONT][i];
m_blockColors[FRONT][i] = m_blockColors[DOWN][i];
m_blockColors[DOWN][i] = m_blockColors[BACK][6 - i];
m_blockColors[BACK][6 - i] = m_blockColors[UP][6 - i];
m_blockColors[UP][6 - i] = t;
}
}
void MagicSquareSolver::rotateXLeftACW(int flag)
{
int index[9] = {6, 7, 8, 5, 2, 1, 0, 3};
rotateFullAspectACW(LEFT, index);
//front ,up,back,down
for(int i = 0; i <= 6; i += 3)
{
FaceColor t = m_blockColors[FRONT][i];
m_blockColors[FRONT][i] = m_blockColors[UP][6 - i];
m_blockColors[UP][6 - i] = m_blockColors[BACK][6 - i];
m_blockColors[BACK][6 - i] = m_blockColors[DOWN][i];
m_blockColors[DOWN][i] = t;
}
}
void MagicSquareSolver::rotateXRightCW(int flag)
{
int index[9] = {6, 7, 8, 5, 2, 1, 0, 3};
rotateFullAspectCW(RIGHT, index);
//front ,down,back,up
for(int i = 0; i <= 6; i += 3)
{
FaceColor t = m_blockColors[FRONT][i + 2];
m_blockColors[FRONT][i + 2] = m_blockColors[DOWN][i + 2];
m_blockColors[DOWN][i + 2] = m_blockColors[BACK][6 - i + 2];
m_blockColors[BACK][6 - i + 2] = m_blockColors[UP][6 - i + 2];
m_blockColors[UP][6 - i + 2] = t;
}
}
void MagicSquareSolver::rotateXRightACW(int flag)
{
int index[9] = {6, 7, 8, 5, 2, 1, 0, 3};
rotateFullAspectACW(RIGHT, index);
//front ,up,back,down
for(int i = 0; i <= 6; i += 3)
{
FaceColor t = m_blockColors[FRONT][i + 2];
m_blockColors[FRONT][i + 2] = m_blockColors[UP][6 - i + 2];
m_blockColors[UP][6 - i + 2] = m_blockColors[BACK][6 - i + 2];
m_blockColors[BACK][6 - i + 2] = m_blockColors[DOWN][i + 2];
m_blockColors[DOWN][i + 2] = t;
}
}
void MagicSquareSolver::rotateXMiddleCW(int flag)
{
//front ,down,back,up
for(int i = 0; i <= 6; i += 3)
{
FaceColor t = m_blockColors[FRONT][i + 1];
m_blockColors[FRONT][i + 1] = m_blockColors[DOWN][i + 1];
m_blockColors[DOWN][i + 1] = m_blockColors[BACK][6 - i + 1];
m_blockColors[BACK][6 - i + 1] = m_blockColors[UP][6 - i + 1];
m_blockColors[UP][6 - i + 1] = t;
}
}
void MagicSquareSolver::rotateXMiddleACW(int flag)
{
//front ,up,back,down
for(int i = 0; i <= 6; i += 3)
{
FaceColor t = m_blockColors[FRONT][i + 1];
m_blockColors[FRONT][i + 1] = m_blockColors[UP][6 - i + 1];
m_blockColors[UP][6 - i + 1] = m_blockColors[BACK][6 - i + 1];
m_blockColors[BACK][6 - i + 1] = m_blockColors[DOWN][i + 1];
m_blockColors[DOWN][i + 1] = t;
}
}
void MagicSquareSolver::rotateYDownCW(int flag)
{
int index[9] = {6, 3, 0, 1, 2, 5, 8, 7};
rotateFullAspectCW(DOWN, index);
//front,right,back,left
for(int i = 0; i < 3; i++)
{
FaceColor t = m_blockColors[FRONT][i];
m_blockColors[FRONT][i] = m_blockColors[RIGHT][3 * (2 - i)];
m_blockColors[RIGHT][3 * (2 - i)] = m_blockColors[BACK][2 - i];
m_blockColors[BACK][2 - i] = m_blockColors[LEFT][i * 3];
m_blockColors[LEFT][i * 3] = t;
}
}
void MagicSquareSolver::rotateYDownACW(int flag)
{
int index[9] = {6, 3, 0, 1, 2, 5, 8, 7};
rotateFullAspectACW(DOWN, index);
//front,left,back,right
for(int i = 0; i < 3; i++)
{
FaceColor t = m_blockColors[FRONT][i];
m_blockColors[FRONT][i] = m_blockColors[LEFT][3 * i];
m_blockColors[LEFT][3 * i] = m_blockColors[BACK][2 - i];
m_blockColors[BACK][2 - i] = m_blockColors[RIGHT][(2 - i) * 3];
m_blockColors[RIGHT][(2 - i) * 3] = t;
}
}
void MagicSquareSolver::rotateYUpCW(int flag)
{
int index[9] = {6, 3, 0, 1, 2, 5, 8, 7};
rotateFullAspectCW(UP, index);
//front,right,back,left
for(int i = 0; i < 3; i++)
{
FaceColor t = m_blockColors[FRONT][6 + i];
m_blockColors[FRONT][6 + i] = m_blockColors[RIGHT][2 + 3 * (2 - i)];
m_blockColors[RIGHT][2 + 3 * (2 - i)] = m_blockColors[BACK][6 + 2 - i];
m_blockColors[BACK][6 + 2 - i] = m_blockColors[LEFT][2 + i * 3];
m_blockColors[LEFT][2 + i * 3] = t;
}
}
void MagicSquareSolver::rotateYUpACW(int flag)
{
int index[9] = {6, 3, 0, 1, 2, 5, 8, 7};
rotateFullAspectACW(UP, index);
//front,left,back,right
for(int i = 0; i < 3; i++)
{
FaceColor t = m_blockColors[FRONT][6 + i];
m_blockColors[FRONT][6 + i] = m_blockColors[LEFT][2 + 3 * i];
m_blockColors[LEFT][2 + 3 * i] = m_blockColors[BACK][6 + 2 - i];
m_blockColors[BACK][6 + 2 - i] = m_blockColors[RIGHT][2 + (2 - i) * 3];
m_blockColors[RIGHT][2 + (2 - i) * 3] = t;
}
}
void MagicSquareSolver::rotateYMiddleCW(int flag)
{
//front,right,back,left
for(int i = 0; i < 3; i++)
{
FaceColor t = m_blockColors[FRONT][3 + i];
m_blockColors[FRONT][3 + i] = m_blockColors[RIGHT][1 + 3 * (2 - i)];
m_blockColors[RIGHT][1 + 3 * (2 - i)] = m_blockColors[BACK][3 + 2 - i];
m_blockColors[BACK][3 + 2 - i] = m_blockColors[LEFT][1 + i * 3];
m_blockColors[LEFT][1 + i * 3] = t;
}
}
void MagicSquareSolver::rotateYMiddleACW(int flag)
{
//front,left,back,right
for(int i = 0; i < 3; i++)
{
FaceColor t = m_blockColors[FRONT][3 + i];
m_blockColors[FRONT][3 + i] = m_blockColors[LEFT][1 + 3 * i];
m_blockColors[LEFT][1 + 3 * i] = m_blockColors[BACK][3 + 2 - i];
m_blockColors[BACK][3 + 2 - i] = m_blockColors[RIGHT][1 + (2 - i) * 3];
m_blockColors[RIGHT][1 + (2 - i) * 3] = t;
}
}
void MagicSquareSolver::rotateZFrontCW(int flag)
{
int index[9] = {0, 3, 6, 7, 8, 5, 2, 1};
rotateFullAspectCW(FRONT, index);
FaceColor t = m_blockColors[UP][6];
m_blockColors[UP][6] = m_blockColors[UP][8];
m_blockColors[UP][8] = t;
t = m_blockColors[DOWN][6];
m_blockColors[DOWN][6] = m_blockColors[DOWN][8];
m_blockColors[DOWN][8] = t;
FaceColor tmp[3];
int size = 3 * sizeof(FaceColor);
memcpy(tmp, &m_blockColors[LEFT][6], size);
memcpy(&m_blockColors[LEFT][6], &m_blockColors[DOWN][6], size);
memcpy(&m_blockColors[DOWN][6], &m_blockColors[RIGHT][6], size);
memcpy(&m_blockColors[RIGHT][6], &m_blockColors[UP][6], size);
memcpy(&m_blockColors[UP][6], tmp, size);
}
void MagicSquareSolver::rotateZFrontACW(int flag)
{
int index[9] = {0, 3, 6, 7, 8, 5, 2, 1};
rotateFullAspectACW(FRONT, index);
FaceColor t = m_blockColors[LEFT][6];
m_blockColors[LEFT][6] = m_blockColors[LEFT][8];
m_blockColors[LEFT][8] = t;
t = m_blockColors[RIGHT][6];
m_blockColors[RIGHT][6] = m_blockColors[RIGHT][8];
m_blockColors[RIGHT][8] = t;
FaceColor tmp[3];
int size = 3 * sizeof(FaceColor);
memcpy(tmp, &m_blockColors[LEFT][6], size);
memcpy(&m_blockColors[LEFT][6], &m_blockColors[UP][6], size);
memcpy(&m_blockColors[UP][6], &m_blockColors[RIGHT][6], size);
memcpy(&m_blockColors[RIGHT][6], &m_blockColors[DOWN][6], size);
memcpy(&m_blockColors[DOWN][6], tmp, size);
}
void MagicSquareSolver::rotateZBackCW(int flag)
{
int index[9] = {0, 3, 6, 7, 8, 5, 2, 1};
rotateFullAspectCW(BACK, index);
FaceColor t = m_blockColors[UP][0];
m_blockColors[UP][0] = m_blockColors[UP][2];
m_blockColors[UP][2] = t;
t = m_blockColors[DOWN][0];
m_blockColors[DOWN][0] = m_blockColors[DOWN][2];
m_blockColors[DOWN][2] = t;
FaceColor tmp[3];
int size = 3 * sizeof(FaceColor);
memcpy(tmp, &m_blockColors[LEFT][0], size);
memcpy(&m_blockColors[LEFT][0], &m_blockColors[DOWN][0], size);
memcpy(&m_blockColors[DOWN][0], &m_blockColors[RIGHT][0], size);
memcpy(&m_blockColors[RIGHT][0], &m_blockColors[UP][0], size);
memcpy(&m_blockColors[UP][0], tmp, size);
}
void MagicSquareSolver::rotateZBackACW(int flag)
{
int index[9] = {0, 3, 6, 7, 8, 5, 2, 1};
rotateFullAspectACW(BACK, index);
FaceColor t = m_blockColors[LEFT][0];
m_blockColors[LEFT][0] = m_blockColors[LEFT][2];
m_blockColors[LEFT][2] = t;
t = m_blockColors[RIGHT][0];
m_blockColors[RIGHT][0] = m_blockColors[RIGHT][2];
m_blockColors[RIGHT][2] = t;
FaceColor tmp[3];
int size = 3 * sizeof(FaceColor);
memcpy(tmp, &m_blockColors[LEFT][0], size);
memcpy(&m_blockColors[LEFT][0], &m_blockColors[UP][0], size);
memcpy(&m_blockColors[UP][0], &m_blockColors[RIGHT][0], size);
memcpy(&m_blockColors[RIGHT][0], &m_blockColors[DOWN][0], size);
memcpy(&m_blockColors[DOWN][0], tmp, size);
}
void MagicSquareSolver::rotateZMiddleCW(int flag)
{
FaceColor t = m_blockColors[UP][3];
m_blockColors[UP][3] = m_blockColors[UP][5];
m_blockColors[UP][5] = t;
t = m_blockColors[DOWN][3];
m_blockColors[DOWN][3] = m_blockColors[DOWN][5];
m_blockColors[DOWN][5] = t;
FaceColor tmp[3];
int size = 3 * sizeof(FaceColor);
memcpy(tmp, &m_blockColors[LEFT][3], size);
memcpy(&m_blockColors[LEFT][3], &m_blockColors[DOWN][3], size);
memcpy(&m_blockColors[DOWN][3], &m_blockColors[RIGHT][3], size);
memcpy(&m_blockColors[RIGHT][3], &m_blockColors[UP][3], size);
memcpy(&m_blockColors[UP][3], tmp, size);
}
void MagicSquareSolver::rotateZMiddleACW(int flag)
{
FaceColor t = m_blockColors[LEFT][3];
m_blockColors[LEFT][3] = m_blockColors[LEFT][5];
m_blockColors[LEFT][5] = t;
t = m_blockColors[RIGHT][3];
m_blockColors[RIGHT][3] = m_blockColors[RIGHT][5];
m_blockColors[RIGHT][5] = t;
FaceColor tmp[3];
int size = 3 * sizeof(FaceColor);
memcpy(tmp, &m_blockColors[LEFT][3], size);
memcpy(&m_blockColors[LEFT][3], &m_blockColors[UP][3], size);
memcpy(&m_blockColors[UP][3], &m_blockColors[RIGHT][3], size);
memcpy(&m_blockColors[RIGHT][3], &m_blockColors[DOWN][3], size);
memcpy(&m_blockColors[DOWN][3], tmp, size);
}
//check whether the user edited cube is a valid cube
bool MagicSquareSolver::IsValidLayout(void)
{
return false;
}
//find the four facelets on edge for a color
void MagicSquareSolver::GetFacelet4(Facelet* facelet, FaceColor color)
{
int pointer = 0;
int index[4] = {1, 3, 5, 7}; //facelets numbered 1,3,5,7 is on edges
for(int i = 0; i < 6; i++)
{
for(int j = 0; j < 4; j++)
{
if(m_blockColors[i][index[j]] == color)
{
facelet[pointer].asp = (FaceDir)i;
facelet[pointer].index = index[j];
facelet[pointer].color = m_blockColors[facelet[pointer].asp][facelet[pointer].index];
pointer++;
if(pointer >= 4) //all have been found
{
return;
}
}
}
}
//ASSERT(pointer==4);
}
//find the other facelet on the same edge
Facelet MagicSquareSolver::GetNeighborEdgeFacelet(Facelet facelet)
{
Facelet faceletNeighbor;
switch(facelet.asp)
{
case FRONT:
faceletNeighbor.index = 7;
switch(facelet.index)
{
case 1:
faceletNeighbor.asp = DOWN;
break;
case 3:
faceletNeighbor.asp = LEFT;
break;
case 5:
faceletNeighbor.asp = RIGHT;
break;
case 7:
faceletNeighbor.asp = UP;
break;
default:
break;
}
break;
case BACK:
faceletNeighbor.index = 1;
switch(facelet.index)
{
case 1:
faceletNeighbor.asp = DOWN;
break;
case 3:
faceletNeighbor.asp = LEFT;
break;
case 5:
faceletNeighbor.asp = RIGHT;
break;
case 7:
faceletNeighbor.asp = UP;
break;
default:
break;
}
break;
case RIGHT:
faceletNeighbor.index = 5;
switch(facelet.index)
{
case 1:
faceletNeighbor.asp = BACK;
break;
case 3:
faceletNeighbor.asp = DOWN;
break;
case 5:
faceletNeighbor.asp = UP;
break;
case 7:
faceletNeighbor.asp = FRONT;
break;
default:
break;
}
break;
case LEFT:
faceletNeighbor.index = 3;
switch(facelet.index)
{
case 1:
faceletNeighbor.asp = BACK;
break;
case 3:
faceletNeighbor.asp = DOWN;
break;
case 5:
faceletNeighbor.asp = UP;
break;
case 7:
faceletNeighbor.asp = FRONT;
break;
default:
break;
}
break;
case UP:
switch(facelet.index)
{
case 1:
faceletNeighbor.asp = BACK;
faceletNeighbor.index = 7;
break;
case 3:
faceletNeighbor.asp = LEFT;
faceletNeighbor.index = 5;
break;
case 5:
faceletNeighbor.asp = RIGHT;
faceletNeighbor.index = 5;
break;
case 7:
faceletNeighbor.asp = FRONT;
faceletNeighbor.index = 7;
break;
default:
break;
}
break;
case DOWN:
switch(facelet.index)
{
case 1:
faceletNeighbor.asp = BACK;
faceletNeighbor.index = 1;
break;
case 3:
faceletNeighbor.asp = LEFT;
faceletNeighbor.index = 3;
break;
case 5:
faceletNeighbor.asp = RIGHT;
faceletNeighbor.index = 3;
break;
case 7:
faceletNeighbor.asp = FRONT;
faceletNeighbor.index = 1;
break;
default:
break;
}
break;
default:
break;
}
faceletNeighbor.color = m_blockColors[faceletNeighbor.asp][faceletNeighbor.index];
return faceletNeighbor;
}
//find the other two facelets on the same corner
void MagicSquareSolver::GetNeighborCornerFacelets(Facelet* neighbor2, Facelet facelet)
{
if(facelet.asp == FRONT)
{
switch(facelet.index)
{
case 0:
neighbor2[0].asp = LEFT;
neighbor2[0].index = 6;
neighbor2[1].asp = DOWN;
neighbor2[1].index = 6;
break;
case 2:
neighbor2[0].asp = DOWN;
neighbor2[0].index = 8;
neighbor2[1].asp = RIGHT;
neighbor2[1].index = 6;
break;
case 6:
neighbor2[0].asp = LEFT;
neighbor2[0].index = 8;
neighbor2[1].asp = UP;
neighbor2[1].index = 6;
break;
case 8:
neighbor2[0].asp = UP;
neighbor2[0].index = 8;
neighbor2[1].asp = RIGHT;
neighbor2[1].index = 8;
break;
default:
break;
}
}
else if(facelet.asp == BACK)
{
switch(facelet.index)
{
case 0:
neighbor2[0].asp = LEFT;
neighbor2[0].index = 0;
neighbor2[1].asp = DOWN;
neighbor2[1].index = 0;
break;
case 2:
neighbor2[0].asp = DOWN;
neighbor2[0].index = 2;
neighbor2[1].asp = RIGHT;
neighbor2[1].index = 0;
break;
case 6:
neighbor2[0].asp = UP;
neighbor2[0].index = 0;
neighbor2[1].asp = LEFT;
neighbor2[1].index = 2;
break;
case 8:
neighbor2[0].asp = UP;
neighbor2[0].index = 2;
neighbor2[1].asp = RIGHT;
neighbor2[1].index = 2;
break;
default:
break;
}
}
neighbor2[0].color = m_blockColors[neighbor2[0].asp][neighbor2[0].index];
neighbor2[1].color = m_blockColors[neighbor2[1].asp][neighbor2[1].index];
}
//find the edge contains the two given color ,in which first is color
//main face ,the second is color of side face
Edge MagicSquareSolver::GetEdge(FaceColor colorMain, FaceColor colorSide)
{
Edge edge;
Facelet facelets[4];
GetFacelet4(facelets, colorMain);
Facelet faceletOther;
for(int i = 0; i < 4; i++)
{
faceletOther = GetNeighborEdgeFacelet(facelets[i]);
if(faceletOther.color == colorSide)
{
edge.faceletMain = facelets[i];
edge.faceletSide = faceletOther;
return edge;
}
}
return edge;
}
//rotate cube to cross state,and the cross is built on down face
void MagicSquareSolver::Cross(void)
{
//two method to make cross:rule database or search
//rules are used here
/* for an edge which contained in the cross,there are 24 situations.
*but I categorize them into 3 kinds in a clear way which came up my
*mind in a sudden.Set front face is the face on which the cross will
*be built.colorMain on LEFT/RIGHT/BACK contains 12 situations,while
*colorSide on LEFT/RIGHT/BACK contains 12 situations too.
*4 situations was repetive.there 4 situations are on the front face.
*/
int testCount = 0;
while(!IsCrossed())
{
testCount++;
if(testCount > 3)
{
//CString filename="bug/Cross.ml";
//CFile fileout(filename.GetBuffer());
//fileout.Write(aspectColors,sizeof(aspectColors));
//fileout.Close();
//MessageBox("bug emerged in function:Cross,saved as Cross.ml");
break;
}
//record number of faces done
int numDone = 0;
//check whether there is a facelet is of same color with center on FRONT face
/*Facelet facelet;
facelet.asp=FRONT;
for (int i=1;i<9;i+=2){
if (aspectColors[FRONT][i]==aspectColors[FRONT][4]){
facelet.index=i;
facelet.color=aspectColors[FRONT][4];
break;
}
}*/
//it will work still,if this 'if' sentence does not exist.
//this is a special situation detection
//if (facelet.index>=0){//found
// //turn the facelet to left
// if (facelet.index==1){
// F();
// }else if (facelet.index==7){
// Fr();
// }else if (facelet.index==5){
// F2();
// }
// //get neighbor's color
// Facelet f=GetNeighborEdgeFacelet(facelet);
// //turn corresponding face to position
// if(aspectColors[3][4]==f.color){
// b2();
// }else if (aspectColors[4][4]==f.color){
// b();
// }else if (aspectColors[5][4]==f.color){
// br();
// }
// numDone=1;
// zr();
//}
while(numDone < 4)
{
//find edges
Edge edge = GetEdge(m_blockColors[FRONT][4], m_blockColors[UP][4]);
if(edge.faceletMain.asp == LEFT) //main facelet
{
//move main color to position 5 first
if(edge.faceletMain.index == 7)
{
Lr();
Ur();
}
else if(edge.faceletMain.index == 1)
{
/* numDone estimation is to check whether there is a need to
*turn side rotated back .this can reduce the steps needed to
*restore the cube.but is hindered optimization of program*/
L();
Ur();
if(numDone != 0)
{
Lr();
}
}
else if(edge.faceletMain.index == 3)
{
L2();
Ur();
if(numDone != 0)
{
L2();
}
}
else if(edge.faceletMain.index == 5) //5
{
Ur();
}
//then
//Ur();
}
else if(edge.faceletMain.asp == RIGHT)
{
//move main color to position 5 first
if(edge.faceletMain.index == 7)
{
R();
U();
}
else if(edge.faceletMain.index == 1)
{
Rr();
U();
if(numDone == 3)
{
R();
}
}
else if(edge.faceletMain.index == 3)
{
R2();
U();
if(numDone == 3)
{
R2();
}
}
else if(edge.faceletMain.index == 5) //5
{
U();
}
//then
//U();
}
else if(edge.faceletMain.asp == BACK && edge.faceletMain.index == 1)
{
//move main color to position 7 first
B2();
U2();
}
else if(edge.faceletMain.asp == BACK && edge.faceletMain.index == 7)
{
U2();
/*else if (edge.faceletMain.index==3){
Br();
}else if (edge.faceletMain.index==5){
B();
}*/
//then
//U2();
}
else if(edge.faceletSide.asp == LEFT) //side facelet
{
//move side color to position 1 first
if(edge.faceletSide.index == 3)
{
L();
Br();
if(numDone != 0)
{
Lr();
}
U2();
}
else if(edge.faceletSide.index == 5)
{
Lr();
Br();
if(numDone != 0)
{
L();
}
U2();
}
else if(edge.faceletSide.index == 7)
{
if(numDone == 0)
{
F();
}
else
{
L2();
Br();
if(numDone != 0)
{
L2();
}
U2();
}
}
else if(edge.faceletSide.index == 1)
{
Br();
U2();
}
//then
//U2();
}
else if(edge.faceletSide.asp == RIGHT)
{
//move side color to position 1 first
if(edge.faceletSide.index == 3)
{
Rr();
B();
if(numDone == 3)
{
R();
}
U2();
}
else if(edge.faceletSide.index == 5)
{
R();
B();
if(numDone == 3)
{
Rr();
}
U2();
}
else if(edge.faceletSide.index == 7)
{
if(numDone == 0)
{
Fr();
}
else
{
R2();
B();
if(numDone == 3)
{
R2();
}
U2();
}
}
else if(edge.faceletSide.index == 1)
{
Br();
U2();
}
//then
//U2();
}
else if(edge.faceletSide.asp == BACK && edge.faceletSide.index == 7)
{
//for the symmetry of code,I did not merge the code below
B();
L();
Ur();
if(numDone != 0)
{
Lr();
}
}/*else if (edge.faceletSide.index==3){
L();Ur();
if (numDone!=0){
Lr();
}
}*/else if(edge.faceletSide.asp == BACK && edge.faceletSide.index == 1)
{
B();
Rr();
U();
if(numDone == 3)
{
R();
}
/*else if (edge.faceletSide.index==5){
Rr();U();
if (numDone==3){
R();
}
}*/
}
else if(edge.faceletMain.asp == FRONT)
{
if(edge.faceletMain.index == 1) //special situations on FRONT face
{
if(numDone == 0)
{
F2();
}
else
{
D2();
B2();
U2();
}
}//else{
// //in correct position
//}
}
else if(edge.faceletSide.asp == FRONT)
{
if(edge.faceletSide.index == 1)
{
D();
Rr();
B();
U2();
if(numDone == 3)
{
R();
}
}
else //7
{
U();
Lr();
Br();
U2();
if(numDone != 0)
{
L();
}
}
}
zr();
numDone++;
}
}
}
//whether the cross has been built
bool MagicSquareSolver::IsCrossed()
{
for(int i = 1; i < 8; i += 2)
{
if(m_blockColors[FRONT][4] != m_blockColors[FRONT][i])
{
return false;
}
}
for(int i = 2; i <= 5; i++)
{
if(m_blockColors[i][4] != m_blockColors[i][7])
{
return false;
}
}
return true;
}
//whether corner of first layer is ready
bool MagicSquareSolver::IsFirstLayerCornerRestored()
{
if(m_blockColors[FRONT][0] == m_blockColors[FRONT][1] &&
m_blockColors[FRONT][2] == m_blockColors[FRONT][1] &&
m_blockColors[BACK][0] == m_blockColors[BACK][1] &&
m_blockColors[BACK][2] == m_blockColors[BACK][1] &&
m_blockColors[LEFT][0] == m_blockColors[LEFT][3] &&
m_blockColors[LEFT][6] == m_blockColors[LEFT][3] &&
m_blockColors[RIGHT][0] == m_blockColors[RIGHT][3] &&
m_blockColors[RIGHT][6] == m_blockColors[RIGHT][3])
{
bool allSame = true;
for(int i = 1; i < 9; i += 2)
{
if(m_blockColors[DOWN][i] != m_blockColors[DOWN][4])
{
allSame = false;
break;
}
}
if(allSame)
{
return true;
}
}
return false;
}
//restore corners of first layer
void MagicSquareSolver::Layer1Corner()
{
int testCount = 0;
while(!IsFirstLayerCornerRestored())
{
testCount++;
if(testCount > 20)
{
//MessageBox("bug emerged in function:RestoreFirstLayerCorner");
//CString filename="bug/RestoreFirstLayerCorner.ml";
//CFile fileout(filename.GetBuffer());
//fileout.Write(aspectColors,sizeof(aspectColors));
//fileout.Close();
return;
}
bool searchUp = true;
//search corners on top which should be on bottom
for(int i = 0; i < 4; i++)
{
bool found = false;
//find and adjust the correct corner block
if(m_blockColors[FRONT][6] == m_blockColors[DOWN][4]) //left
{
if(m_blockColors[UP][6] == m_blockColors[FRONT][4]) // UP FRONT
{
if(m_blockColors[LEFT][8] == m_blockColors[LEFT][4]) //LEFT LEFT
{
yr();
}
else //LEFT RIGHT
{
Ur();
}
}
else if(m_blockColors[UP][6] == m_blockColors[LEFT][4]) //UP LEFT
{
if(m_blockColors[LEFT][8] == m_blockColors[FRONT][4]) //LEFT FRONT
{
yr();
}
else //LEFT BACK
{
U();
y2();
}
}
else if(m_blockColors[LEFT][8] == m_blockColors[FRONT][4]) //LEFT FRONT
{
Ur();
}
else if(m_blockColors[LEFT][8] == m_blockColors[LEFT][4]) //LEFT LEFT
{
U();
y2();
}
else //left front corner should be on right back
{
U2();
y();
}
found = true;
}
else if(m_blockColors[FRONT][8] == m_blockColors[DOWN][4]) //right
{
if(m_blockColors[UP][8] == m_blockColors[FRONT][4]) // UP FRONT
{
if(m_blockColors[RIGHT][8] == m_blockColors[RIGHT][4]) //RIGHT RIGHT
{
//on correct position
}
else //RIGHT LEFT
{
//U();yr();
d();
}
}
else if(m_blockColors[UP][8] == m_blockColors[RIGHT][4]) //UP RIGHT
{
if(m_blockColors[RIGHT][8] == m_blockColors[FRONT][4]) //RIGHT FRONT
{
//on correct position
}
else //RIGHT BACK
{
//Ur();y();
dr();
}
}
else if(m_blockColors[RIGHT][8] == m_blockColors[FRONT][4]) //RIGHT FRONT
{
d();
}
else if(m_blockColors[RIGHT][8] == m_blockColors[RIGHT][4]) //RIGHT RIGHT
{
dr();
}
else //right front corner should be on left back
{
U2();
y2();
}
found = true;
}
if(found) //if found ,use formula to restore the corner
{
//the corner is on FRT corner
if(m_blockColors[FRONT][8] == m_blockColors[DOWN][4])
{
U();
R();
Ur();
Rr();
}
else
{
R();
U();
Rr();
}
searchUp = false;
break;/* for */
}
else //if not found,search next side
{
y();
}
}
//search top if target not found on sides
bool searchDown = false;
if(!searchUp)
{
continue;/* while */
}
else
{
bool found = true;
//search top and adjust
if(m_blockColors[UP][0] == m_blockColors[DOWN][4])
{
y2();
}
else if(m_blockColors[UP][2] == m_blockColors[DOWN][4])
{
y();
}
else if(m_blockColors[UP][6] == m_blockColors[DOWN][4])
{
yr();
}
else if(m_blockColors[UP][8] == m_blockColors[DOWN][4])
{
//correct
}
else
{
searchDown = true;
found = false;
}
if(found)
{
//adjustment
if(m_blockColors[FRONT][8] == m_blockColors[FRONT][4])
{
d();
}
else if(m_blockColors[RIGHT][8] == m_blockColors[RIGHT][4])
{
dr();
}
else
{
d2();
}
//formula
R();
U2();
Rr();
Ur();
//then to another situation
//R();U();Rr();
}
}
if(searchDown)
{
//search bottom and adjust
for(int i = 0; i < 4; i++)
{
bool found = true;
if(m_blockColors[FRONT][0] == m_blockColors[DOWN][4])
{
yr();
}
else if(m_blockColors[FRONT][2] == m_blockColors[DOWN][4])
{
//correct
}
else
{
if(m_blockColors[DOWN][6] == m_blockColors[DOWN][4] &&
m_blockColors[FRONT][0] != m_blockColors[FRONT][4])
{
R();
U();
Rr();
}
y();
found = false;
}
if(found)
{
//restore
if(m_blockColors[RIGHT][6] == m_blockColors[DOWN][4])
{
R();
U();
Rr();
U();
//then
//R();U();Rr();
}
else if(m_blockColors[FRONT][2] == m_blockColors[DOWN][4])
{
R();
Ur();
Rr();
//then
//U();R();Ur();Rr();
}
break;
}
}
}
}
}
//whether edges on second layer are restored
bool MagicSquareSolver::IsSecondLayerEdgeRestored(void)
{
if(m_blockColors[FRONT][4] == m_blockColors[FRONT][3] &&
m_blockColors[FRONT][4] == m_blockColors[FRONT][5] &&
m_blockColors[BACK][4] == m_blockColors[BACK][3] &&
m_blockColors[BACK][4] == m_blockColors[BACK][5] &&
m_blockColors[LEFT][4] == m_blockColors[LEFT][1] &&
m_blockColors[LEFT][4] == m_blockColors[LEFT][7] &&
m_blockColors[RIGHT][4] == m_blockColors[RIGHT][1] &&
m_blockColors[RIGHT][4] == m_blockColors[RIGHT][7])
{
return true;
}
return false;
}
//restore edges of second layer
void MagicSquareSolver::Layer2Edge()
{
//ASSERT(IsFirstLayerCornerRestored());
int testCount = 0;
while(!IsSecondLayerEdgeRestored())
{
testCount++;
if(testCount > 10)
{
//MessageBox("bug emerged in function:RestoreSecondLayerEdge");
//CString filename="bug/RestoreSecondLayerEdge.ml";
//CFile fileout(filename.GetBuffer());
//fileout.Write(aspectColors,sizeof(aspectColors));
//fileout.Close();
return;
}
bool found = false;
for(int i = 0; i < 4; i++)
{
if(m_blockColors[FRONT][7] != m_blockColors[UP][4] &&
m_blockColors[UP][7] != m_blockColors[UP][4]) //found
{
if(m_blockColors[FRONT][7] != m_blockColors[FRONT][4]) //front not matched
{
//rotate to match
if(m_blockColors[FRONT][7] == m_blockColors[LEFT][4])
{
d();
}
else if(m_blockColors[FRONT][7] == m_blockColors[RIGHT][4])
{
dr();
}
else if(m_blockColors[FRONT][7] == m_blockColors[BACK][4])
{
d2();
}
}
yr();//adjustment
//formula
if(m_blockColors[UP][5] == m_blockColors[FRONT][4]) //RIGHT FRONT
{
Rr();
Ur();
Rr();
Ur();
Rr();
U();
R();
U();
R();
}
else //RIGHT BACK
{
R();
U();
R();
U();
R();
Ur();
Rr();
Ur();
Rr();
}
found = true;
break;
}
y();
}
if(!found) //search middle layer
{
for(int i = 0; i < 4; i++)
{
if(m_blockColors[FRONT][5] != m_blockColors[FRONT][4])
{
Rr();
Ur();
Rr();
Ur();
Rr();
U();
R();
U();
R();
break;
}
y();
}
}
}
}
//whether F2L is done
bool MagicSquareSolver::IsF2L()
{
if(IsFirstLayerCornerRestored() &&
IsSecondLayerEdgeRestored())
{
return true;
}
return false;
}
//restore First 2 Layer
void MagicSquareSolver::F2L(void)
{
//make cross
Cross();
xr();
//restore corners of first layer
Layer1Corner();
//restore edges of second layer
Layer2Edge();
}
//==================^_^==================^_^==================^_^==================^_^
//method 1:ferwer formula
//reference:Meissen
//whether top cross is built
bool MagicSquareSolver::IsTopCrossed()
{
for(int i = 1; i < 9; i += 2)
{
if(m_blockColors[UP][i] != m_blockColors[UP][4])
{
return false;
}
}
return true;
}
//built cross on top
void MagicSquareSolver::TopCross()
{
//ASSERT(IsF2L());
int testCount = 0;
while(!IsTopCrossed())
{
testCount++;
if(testCount > 5)
{
//CString filename="bug/BuildTopCross.ml";
//CFile fileout(filename.GetBuffer());
//fileout.Write(aspectColors,sizeof(aspectColors));
//fileout.Close();
//MessageBox("bug emerged in function:BuildTopCross");
return;
}
if(m_blockColors[UP][3] == m_blockColors[UP][4] &&
m_blockColors[UP][5] == m_blockColors[UP][4]) //situation 1a
{
if(m_blockColors[FRONT][7] != m_blockColors[UP][4])
{
//adjustment
y2();
}
F();
R();
U();
Rr();
Ur();
Fr();
}
else if(m_blockColors[UP][1] == m_blockColors[UP][4] && //situation 1b
m_blockColors[UP][7] == m_blockColors[UP][4])
{
y();
if(m_blockColors[FRONT][7] != m_blockColors[UP][4])
{
//adjustment
y2();
}
F();
R();
U();
Rr();
Ur();
Fr();
}
else if(m_blockColors[UP][3] == m_blockColors[UP][4]) //situation 2a
{
bool isTwo = false;
if(m_blockColors[UP][7] == m_blockColors[UP][4])
{
y();
isTwo = true;
}
else if(m_blockColors[UP][1] == m_blockColors[UP][4])
{
isTwo = true;
}
if(isTwo)
{
F();
U();
R();
Ur();
Rr();
Fr();
}
}
else if(m_blockColors[UP][5] == m_blockColors[UP][4]) //situation 2b
{
bool isTwo = false;
if(m_blockColors[UP][7] == m_blockColors[UP][4])
{
y2();
isTwo = true;
}
else if(m_blockColors[UP][1] == m_blockColors[UP][4])
{
yr();
isTwo = true;
}
if(isTwo)
{
F();
U();
R();
Ur();
Rr();
Fr();
}
}
else //situation 3
{
for(int i = 0; i < 4; i++)
{
if(m_blockColors[FRONT][7] == m_blockColors[UP][4] &&
m_blockColors[RIGHT][5] == m_blockColors[UP][4])
{
F();
U();
R();
Ur();
Rr();
Fr();
//then
//F();R();U();Rr();Ur();Fr();
break;
}
y();
}
}
}
}
//
bool MagicSquareSolver::IsTopCrossMatched(void)
{
if(m_blockColors[FRONT][7] != m_blockColors[FRONT][4])
{
return false;
}
if(m_blockColors[BACK][7] != m_blockColors[BACK][4])
{
return false;
}
if(m_blockColors[LEFT][5] != m_blockColors[LEFT][4])
{
return false;
}
if(m_blockColors[RIGHT][5] != m_blockColors[RIGHT][4])
{
return false;
}
return true;
}
void MagicSquareSolver::MatchTopCross(void)
{
//ASSERT(IsTopCrossed());
int testCount = 0;
while(!IsTopCrossMatched())
{
testCount++;
if(testCount > 1)
{
//MessageBox("bug emerged in function:MatchTopCross,saved in MatchTopCross.ml");
//CString filename="bug/MatchTopCross.ml";
//CFile fileout(filename.GetBuffer());
//fileout.Write(aspectColors,sizeof(aspectColors));
//fileout.Close();
return;
}
//match edge first,then use formula
for(int jj = 0; jj < 4; jj++)
{
//match
for(int i = 0; i < 4; i++) //match Back
{
if(m_blockColors[BACK][4] != m_blockColors[BACK][7])
{
U();
}
else
{
break;
}
}
if(IsTopCrossMatched())
{
return;
}
//formula
if(m_blockColors[LEFT][4] == m_blockColors[LEFT][5]) //LEFT match
{
char* formula = "(RU2R')(U'RU'R')U'";
Execute(formula);
return;
}
else if(m_blockColors[FRONT][4] == m_blockColors[FRONT][7]) //RIGHT match
{
char* formula = "(RU2R')(U'RU'R')y(RU2R')(U'RU'R')U'";
Execute(formula);
return;
}
yr();
}
//MessageBox("special situation not recorded found,saved in file :MatchTopCross-special.ml");
//CString filename="MatchTopCross-special.ml";
//CFile fileout(filename.GetBuffer());
//fileout.Write(aspectColors,sizeof(aspectColors));
//fileout.Close();
}
}
bool MagicSquareSolver::IsTopCornerBack(void)
{
int cornerHashDst[4];//hash value of this corner should be
int cornerHashSrc[4];//hash value for current corners
//start from leftFront corner,counterclockwise
cornerHashDst[0] = HashCorner(m_blockColors[UP][4], m_blockColors[LEFT][4], m_blockColors[FRONT][4]);
cornerHashDst[1] = HashCorner(m_blockColors[UP][4], m_blockColors[FRONT][4], m_blockColors[RIGHT][4]);
cornerHashDst[2] = HashCorner(m_blockColors[UP][4], m_blockColors[RIGHT][4], m_blockColors[BACK][4]);
cornerHashDst[3] = HashCorner(m_blockColors[UP][4], m_blockColors[BACK][4], m_blockColors[LEFT][4]);
cornerHashSrc[0] = HashCorner(m_blockColors[UP][6], m_blockColors[LEFT][8], m_blockColors[FRONT][6]);
cornerHashSrc[1] = HashCorner(m_blockColors[UP][8], m_blockColors[FRONT][8], m_blockColors[RIGHT][8]);
cornerHashSrc[2] = HashCorner(m_blockColors[UP][2], m_blockColors[RIGHT][2], m_blockColors[BACK][8]);
cornerHashSrc[3] = HashCorner(m_blockColors[UP][0], m_blockColors[BACK][6], m_blockColors[LEFT][2]);
for(int i = 0; i < 4; i++)
{
if(cornerHashSrc[i] != cornerHashDst[i])
{
return false;
}
}
return true;
}
//calculate a hash value for a corner to differ from other corners
//according to its colors.there are various methods
int MagicSquareSolver::HashCorner(FaceColor c1, FaceColor c2, FaceColor c3)
{
return (c1 + 1) * (c2 + 1) * (c3 + 1);
}
void MagicSquareSolver::BackTopCorner(void)
{
//ASSERT(IsTopCrossMatched());
int testCount = 0;
while(!IsTopCornerBack())
{
testCount++;
if(testCount > 3)
{
//CString filename="bug/PutBackTopCorner.ml";
//CFile fileout(filename.GetBuffer());
//fileout.Write(aspectColors,sizeof(aspectColors));
//fileout.Close();
//MessageBox("bug emerged in function:PutBackTopCorner");
return;
}
int cornerHashDst[4];//hash value of this corner should be
int cornerHashSrc[4];//hash value for current corners
//start from leftFront corner,counterclockwise
cornerHashDst[0] = HashCorner(m_blockColors[UP][4], m_blockColors[LEFT][4], m_blockColors[FRONT][4]);
cornerHashDst[1] = HashCorner(m_blockColors[UP][4], m_blockColors[FRONT][4], m_blockColors[RIGHT][4]);
cornerHashDst[2] = HashCorner(m_blockColors[UP][4], m_blockColors[RIGHT][4], m_blockColors[BACK][4]);
cornerHashDst[3] = HashCorner(m_blockColors[UP][4], m_blockColors[BACK][4], m_blockColors[LEFT][4]);
cornerHashSrc[0] = HashCorner(m_blockColors[UP][6], m_blockColors[LEFT][8], m_blockColors[FRONT][6]);
cornerHashSrc[1] = HashCorner(m_blockColors[UP][8], m_blockColors[FRONT][8], m_blockColors[RIGHT][8]);
cornerHashSrc[2] = HashCorner(m_blockColors[UP][2], m_blockColors[RIGHT][2], m_blockColors[BACK][8]);
cornerHashSrc[3] = HashCorner(m_blockColors[UP][0], m_blockColors[BACK][6], m_blockColors[LEFT][2]);
//analysis
//find backed corner first
bool found = false;
for(int i = 0; i < 4; i++)
{
if(cornerHashDst[i] == cornerHashSrc[i])
{
found = true;
//analyze relative positions of the other three corners
RotateDir direction;
if(cornerHashDst[(i + 1) % 4] == cornerHashSrc[(i + 2) % 4]) //clockwise
{
direction = CLOCKWISE;
}
else if(cornerHashDst[(i + 2) % 4] == cornerHashSrc[(i + 1) % 4]) //clockwise
{
direction = COUNTERCLOCKWISE;
}
else
{
// MessageBox("something wrong with PutBackTopCorner");
return;
}
if(direction == COUNTERCLOCKWISE)
{
//adjust direction of the cube
if(i == 3)
{
yr();
}
else if(i == 2)
{
y2();
}
else if(i == 1)
{
y();
}
char* cmd = "RU'L'UR'U'LU";
Execute(cmd);
}
else
{
if(i == 3)
{
y2();
}
else if(i == 2)
{
y();
}
else if(i == 1)
{
yr();
}
char* cmd = "L'URU'LUR'U'";
Execute(cmd);
}
}
}
if(!found) //none of the four corners is in right position
{
char* cmd = "RU'L'UR'U'LUy";
Execute(cmd);
}
}
}
bool MagicSquareSolver::IsTopCornerRestored(void)
{
if(m_blockColors[UP][0] != m_blockColors[UP][4] ||
m_blockColors[UP][2] != m_blockColors[UP][4] ||
m_blockColors[UP][6] != m_blockColors[UP][4] ||
m_blockColors[UP][8] != m_blockColors[UP][4] ||
m_blockColors[LEFT][2] != m_blockColors[LEFT][4] ||
m_blockColors[LEFT][8] != m_blockColors[LEFT][4] ||
m_blockColors[RIGHT][2] != m_blockColors[RIGHT][4] ||
m_blockColors[RIGHT][8] != m_blockColors[RIGHT][4] ||
m_blockColors[FRONT][6] != m_blockColors[FRONT][4] ||
m_blockColors[FRONT][8] != m_blockColors[FRONT][4] ||
m_blockColors[BACK][6] != m_blockColors[BACK][4] ||
m_blockColors[BACK][8] != m_blockColors[BACK][4])
{
return false;
}
return true;
}
void MagicSquareSolver::RestoreTopCorner(void)
{
//TOP FRONT:RF'R'F twice
//TOP RIGHT:F'RFR' twice
ASSERT(IsTopCornerBack());
if(!IsTopCornerRestored())
{
//find a start corner
for(int i = 0; i < 4; i++)
{
if(m_blockColors[UP][8] != m_blockColors[UP][4])
{
break;
}
y();
}
int testCount = 0;
while(!IsTopCornerRestored())
{
testCount++;
if(testCount > 12)
{
//MessageBox("bug merged in function:RestoreTopCorner");
//CString filename="bug/RestoreTopCorner.ml";
//CFile fileout(filename.GetBuffer());
//fileout.Write(aspectColors,sizeof(aspectColors));
//fileout.Close();
return;
}
if(m_blockColors[UP][8] != m_blockColors[UP][4])
{
if(m_blockColors[FRONT][8] == m_blockColors[UP][4])
{
char* cmd = "RF'R'FRF'R'F";
Execute(cmd);
}
else
{
char* cmd = "F'RFR'F'RFR'";
Execute(cmd);
}
}
else
{
U();
}
}
//last step to restore
if(m_blockColors[FRONT][7] != m_blockColors[FRONT][4])
{
if(m_blockColors[BACK][7] != m_blockColors[FRONT][4])
{
U2();
}
else if(m_blockColors[LEFT][5] != m_blockColors[FRONT][4])
{
Ur();
}
else if(m_blockColors[RIGHT][5] != m_blockColors[FRONT][4])
{
U();
}
}
else
{
//bingo
}
}
}
void MagicSquareSolver::MethodFewerFormula()
{
F2L();
TopCross();
MatchTopCross();
BackTopCorner();
RestoreTopCorner();
}
//==================^_^==================^_^==================^_^==================^_^
//Method 2:cfop,not finished
//hash function for oll
void MagicSquareSolver::HashOLL(char* hashstr)
{
//start from left side,then front,right,back
//length of the hash string is 12,for 12 facelets around top face
memset(hashstr, '0', 12);
if(m_blockColors[LEFT][2] == m_blockColors[UP][4])
{
hashstr[0] = '1';
}
if(m_blockColors[LEFT][5] == m_blockColors[UP][4])
{
hashstr[1] = '1';
}
if(m_blockColors[LEFT][8] == m_blockColors[UP][4])
{
hashstr[2] = '1';
}
if(m_blockColors[FRONT][6] == m_blockColors[UP][4])
{
hashstr[3] = '1';
}
if(m_blockColors[FRONT][7] == m_blockColors[UP][4])
{
hashstr[4] = '1';
}
if(m_blockColors[FRONT][8] == m_blockColors[UP][4])
{
hashstr[5] = '1';
}
if(m_blockColors[RIGHT][8] == m_blockColors[UP][4])
{
hashstr[6] = '1';
}
if(m_blockColors[RIGHT][5] == m_blockColors[UP][4])
{
hashstr[7] = '1';
}
if(m_blockColors[RIGHT][2] == m_blockColors[UP][4])
{
hashstr[8] = '1';
}
if(m_blockColors[BACK][8] == m_blockColors[UP][4])
{
hashstr[9] = '1';
}
if(m_blockColors[BACK][7] == m_blockColors[UP][4])
{
hashstr[10] = '1';
}
if(m_blockColors[BACK][6] == m_blockColors[UP][4])
{
hashstr[11] = '1';
}
}
//whether top face is restored
bool MagicSquareSolver::IsTopFaceRestored(void)
{
for(int i = 0; i < 9; i++)
{
if(m_blockColors[UP][i] != m_blockColors[UP][4])
{
return false;
}
}
return true;
}
//Orientation the Last Layer
void MagicSquareSolver::OLL(void)
{
//BuildTopCross();
//I choose standard OLL method to restore top face,there are
//too many situations.A possible way is to hash them.This will
//highly reduce program complexity .
//length of the string is 12,for the sack of rotation,4 string
//is used,in yr rotation order,i.e. counterclockwise.
char hashstr[4][13] = {0};
HashOLL(hashstr[0]);
for(int i = 1; i < 4; i++)
{
int t = i * 3;
memcpy(hashstr[i], hashstr[0] + 12 - t, t);
memcpy(hashstr[i] + t, hashstr[0], 12 - t);
}
//hash of every situations
//if BuildTopCross function is used first,only first 7 ollHash
//strings are used.the second part are corresponding operations
static const char* ollHash[57][2] =
{
/* 01 */{"100100100000", "(RU'2)R'U'(RU'R')"},
/* 02 */{"000001001001", "RUR'URU2R'"}, //U'R'U2RUR'UR
/* 03 */{"101000101000", "(RUR'U)(RU'R'U)(RU2R')"}, // (RU'2)(R'U'RUR'U')(RU'R')
/* 04 */{"101001000100", "RU'2(R'2U')(R2U')(R'2U'2R"},
/* 05 */{"000100000001", "(rUR'U')(r'FRF')"},
/* 06 */{"000101000000", "(RUR'URU'2R')U(RU'2R'U'RU'R'"},
/* 07 */{"100001000000", "F'(rUR'U')(r'FR)"},
/* 08 */{"111010111010", "(RU'2)(R'2FRF')U2(R'FRF')"},
/* 09 */{"111011010110", "(FRUR'U'F')(fRUR'U'f')"},
/* 10 */{"011010011011", "(f R U R' U' f')U' (F R U R' U' F')"},
/* 11 */{"110110110010", "(fRUR'U'f')y(FRUR'U'F')"},
/* 12 */{"011010010110", "(RUR'U)(R'FRF')U2(R'FRF')"},
/* 13 */{"010010010111", "F(RUR'U)y'(R'U2)(R'FRF')"},
/* 14 */{"011010110010", "r'(RURUR'U')r(R'2FRF')"},
/* 15 */{"010010010010", "r'(RURUR'U')r2(R'2UR U')"},
/* 16 */{"101011000110", "f (R U R' U')2 f'"},
/* 17 */{"010100111001", "(R'U'RU'R'U)y'(R' URB)"},
/* 18 */{"101010101010", "(r U r')(U R U' R' ) 2 (r U' r')"},
/* 19 */{"111000111000", "(RU'U')(R'2U')(R U'R' U2)(F R F')"},
/* 20 */{"000011001011", "(rU'r'U')(rU r')y' (R' U R)"},
/* 21 */{"100110000110", "(R'FRUR' F'R) y'(R U' R')"},
/* 22 */{"001010001011", "(r' U' r)(R' U' R U)(r' U r)"},
/* 23 */{"100110100010", "(rUr')(RUR'U')(rU' r')"},
/* 24 */{"000110000011", "(RUR'U')(R'F R F')"},
/* 25 */{"101010000010", "F(R U R' U') F'"},
/* 26 */{"000010000010", "(RUR'U' r)(R'U R U') r'"},
/* 27 */{"000010010000", "(rUR'U')(r' RU)(R U' R')"},
/* 28 */{"000010100011", "(r U' r' U' r) y (R U R' f')"},
/* 29 */{"001010000110", "(R'F R U R' U') (F' U R)"},
/* 30 */{"001010100010", "(R'U' R U) y (r U R' U') r' R"},
/* 31 */{"010000111000", "(R'U')(R' F R F') (U R)"},
/* 32 */{"010110000001", "(R'U' F)(U R U' R' F' R)"},
/* 33 */{"010100000011", "(R U B'U')(R' U R B R')"},
/* 34 */{"000000111010", "x'U'F'R'FR U"},
/* 35 */{"111000000010", "f(RUR'U')f'"},
/* 36 */{"000110011000", "F(RU'R'U')(R U R' F')"},
/* 37 */{"010100001010", "R U'2(R'2FR F')(R U'2 R')"},
/* 38 */{"011000001011", "(r'U2)(R UR' U) r"},
/* 39 */{"110110100000", "(rU2)(R'U'R U') r'"},
/* 40 */{"000100110110", "r'U'R U'R'U2 r"},
/* 41 */{"000011011001", "rUR'UR U'2r'"},
/* 42 */{"010001001011", "r'(R2U)(R'U R) U'2 (R' U R')"},
/* 43 */{"010110100100", "r(R'2U')(RU'R') U2 (R U' R) r'"},
/* 44 */{"100110010100", "(R'U'R) y'x'(R U' R' F)(R U R')"},
/* 45 */{"001001010011", "(RUR'U)(R'FR F')(R U'2 R')"},
/* 46 */{"000111010101", "(r U2)(R' U' R U R' U')(R U' r')"},
/* 47 */{"101001010110", "B'(R'U'RU)2B"},
/* 48 */{"000101010111", "r' U2(R U R' U')(R U R' U) r"},
/* 49 */{"101011010100", "F(RU R'U')2 F'"},
/* 50 */{"000110111001", "R'FR2 B' R'2 F' R2 B R'"},
/* 51 */{"000100111011", "RB'R'2 F R2 B R'2 F' R"},
/* 52 */{"011000100010", "(R2U R' B')(R U' R'2 U)(R B R')"},
/* 53 */{"110010001000", "(RUR' U')(R U' R' F') U' (F R U R')"},
/* 54 */{"010010000101", "(R' U R U'2 R' U') y (L' U L U F)"},
/* 55 */{"010101000010", "(RU' R' U2 R U) y (R U' R' U' F')"},
/* 56 */{"000010110001", "(RU R' U)(R U' R' U')(R' F R F')"},
/* 57 */{"000100011010", "(R' U' R U')(R' U R U)(R B' R' B)"}
};
char buf[1024] = "";
for(int i = 0; i < 57; i++)
{
for(int j = 0; j < 4; j++)
{
if(strcmp(hashstr[j], ollHash[i][0]) == 0)
{
if(j == 1)
{
//yr();
strcat(buf,"y'");
}
else if(j == 2)
{
//y2();
strcat(buf,"yy");
}
else if(j == 3)
{
//y();
strcat(buf,"y");
}
Execute(ollHash[i][1]);
//strcat(buf,ollHash[i][1]);
if(!IsTopFaceRestored())
{
char errorInfo[100];
sprintf_s(errorInfo, 100, "something wrong with ollHash:%s\nnumber%d", ollHash[i][1], i);
}
return;
}
}
}
//MessageBox("special situation not recorded found,saved in file :OLLSpecialFound.ml");
//CString filename="OLLSpecialFound.ml";
//CFile fileout(filename.GetBuffer());
//fileout.Write(aspectColors,sizeof(aspectColors));
//fileout.Close();
}
//hash function for PLL
void MagicSquareSolver::HashPLL(char* hashstr)
{
//not finished
}
//Permutation the Last Layer
void MagicSquareSolver::PLL(void)
{
//ASSERT(IsTopFaceRestored());
char hashstr[4][13] = {0};
HashPLL(hashstr[0]);
for(int i = 1; i < 4; i++)
{
int t = i * 3;
memcpy(hashstr[i], hashstr[0] + 12 - t, t);
memcpy(hashstr[i] + t, hashstr[0], 12 - t);
}
//hash string here is different with oll hash,because one hash
//maybe correspond two situations
static const char* pllHash[18][3] = //0,1,14 are special
{
/* 0102 */{"101101101111", "(R2 U)(R U R' U')(R' U')(R' U R')", "(R U' R)(U R U R)(U' R' U' R2)"},
/* 0304 */{"110010010011", "(l U' R)D2(R' U R)D2 R2", "x' R2 D2(R' U' R)D2(R' U R')"},
/* 05 */{"101000000110", "(R'2 u' R U' R)(U R' u)(R2 f R' f')", ""},
/* 06 */{"101000110000", "(R U R')y'(R2' u' R U')(R' U R' u R2)", ""},
/* 07 */{"101011000000", "(R2 u)(R' U R' U')(R u') (R2' F' U F)", ""},
/* 08 */{"101000011000", "(R' d' F) (R2 u) (R' U) (R U' R u' R'2)", ""},
/* 09 */{"111100000011", "(R U R' F')(R U R' U')(R' F R2 U' R' U')", ""},
/* 10 */{"110000001111", "z (U' R D') (R2 U R' U' R2 U) z' (R U')", ""},
/* 11 */{"011101100010", "(R' U2)(R U2')(R' F)(R U R' U')(R' F' R2 U')", ""},
/* 12 */{"110010001101", "(R U'2 R' U2) (R B' R' U') (R U R B R'2 U) ", ""}, // x'(R2 u' R' u)R2 x' y'(R' U R' U')R2
/* 13 */{"101110000011", "(R U R' U')(R' F)(R2 U' R' U')(R U R' F')", ""},
/* 14 */{"000110011000", "F(R U' R' U')(R U R' F')(R U R' U')(R' F R F')", ""},
/* 15 */{"110001110001", "z (U' R D') (R2 U R' U')z'( R U R')z (R2 U R')z' (R U')", ""},
/* 16 */{"011100011100", "L U' R U'2 r' F r R' U' R U'2 r' F R' F", ""},
/* 1721 */{"101101101101", "(U R' U')(R U' R)(U R U')(R' U R U)(R2 U')(R' U)", "M'2 U' M'2 U2 M'2 U' M'2"},
/* 18 */{"011110001100", "(R' U R' U') y x2 (R' U R' U' R2) y x (R' U' R U R)", ""},
/* 19 */{"010010010010", "L x' (R U R')(D R U')(r' R' F) r D' r' F' ", ""}, //(R' U R' U')B' D B' D' B2 R' (B' R B R)
/* 20 */{"111100010001", "U'(R' U R U') R'2 F' z R' F R D z' x (U R' U' R2)", ""},
};
}
//I use CFOP method to restore the cube
void MagicSquareSolver::CFOP(void)
{
F2L();
OLL();
PLL();
}
void MagicSquareSolver::SaveFromFile()
{
/* CFileDialog fileDlg(false,NULL,NULL,4|2,"MagicCube Layout Files(*.ml)|*.ml||");
if (fileDlg.DoModal()==IDOK){
CString filename=fileDlg.GetPathName();
CString ext=fileDlg.GetFileExt();
if (ext!="ml"){
filename.Append(".ml");
}
CFile fileout(filename.GetBuffer());
fileout.Write(aspectColors,sizeof(aspectColors));
fileout.Close();
}*/
}
void MagicSquareSolver::LoadFromFile()
{
//CFileDialog fileDlg(true,NULL,NULL,4|2,"MagicCube Layout Files(*.ml)|*.ml||");
//if (fileDlg.DoModal()==IDOK){
// CString filename=fileDlg.GetPathName();
// CFile filein(filename.GetBuffer(),CFile::modeRead);
// filein.Read(aspectColors,sizeof(aspectColors));
// filein.Close();
//}
}
void MagicSquareSolver::Execute(const char* cmd)
{
//space,'(' and ')' can be filtered
//"'2" can be replaced by 2
while(*cmd)
{
switch(*cmd)
{
case ' ':
case '(':
case ')':
break;
case 'F':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
F2();
cmd++;
}
else
{
Fr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
F2();
cmd++;
}
else
{
F();
}
break;
case 'B':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
B2();
cmd++;
}
else
{
Br();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
B2();
cmd++;
}
else
{
B();
}
break;
case 'L':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
L2();
cmd++;
}
else
{
Lr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
L2();
cmd++;
}
else
{
L();
}
break;
case 'R':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
R2();
cmd++;
}
else
{
Rr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
R2();
cmd++;
}
else
{
R();
}
break;
case 'U':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
U2();
cmd++;
}
else
{
Ur();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
U2();
cmd++;
}
else
{
U();
}
break;
case 'D':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
D2();
cmd++;
}
else
{
Dr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
D2();
cmd++;
}
else
{
D();
}
break;
case 'x':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
x2();
cmd++;
}
else
{
xr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
x2();
cmd++;
}
else
{
x();
}
break;
case 'y':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
y2();
cmd++;
}
else
{
yr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
y2();
cmd++;
}
else
{
y();
}
break;
case 'z':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
z2();
cmd++;
}
else
{
zr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
z2();
cmd++;
}
else
{
z();
}
break;
case 'f':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
f2();
cmd++;
}
else
{
fr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
f2();
cmd++;
}
else
{
f();
}
break;
case 'b':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
b2();
cmd++;
}
else
{
br();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
b2();
cmd++;
}
else
{
b();
}
break;
case 'l':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
l2();
cmd++;
}
else
{
lr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
l2();
cmd++;
}
else
{
l();
}
break;
case 'r':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
r2();
cmd++;
}
else
{
rr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
r2();
cmd++;
}
else
{
r();
}
break;
case 'u':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
u2();
cmd++;
}
else
{
ur();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
u2();
cmd++;
}
else
{
u();
}
break;
case 'd':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
d2();
cmd++;
}
else
{
dr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
d2();
cmd++;
}
else
{
d();
}
break;
case 'E':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
E2();
cmd++;
}
else
{
Er();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
E2();
cmd++;
}
else
{
E();
}
break;
case 'M':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
M2();
cmd++;
}
else
{
Mr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
M2();
cmd++;
}
else
{
M();
}
break;
case 'S':
if(*(cmd + 1) == '\'')
{
if(*(cmd + 2) == '2') //E'2==E2
{
S2();
cmd++;
}
else
{
Sr();
}
cmd++;
}
else if(*(cmd + 1) == '2')
{
S2();
cmd++;
}
else
{
S();
}
break;
default:
break;
}
cmd++;
}
}
void MagicSquareSolver::b2()
{
b();
b();
}
void MagicSquareSolver::br()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'b';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateZMiddleCW();
rotateZBackCW();
}
void MagicSquareSolver::b()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'b';
m_history[m_historyNum] = '\0';
}
rotateZMiddleACW();
rotateZBackACW();
}
void MagicSquareSolver::l2()
{
l();
l();
}
void MagicSquareSolver::lr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'l';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateXMiddleCW();
rotateXLeftCW();
}
void MagicSquareSolver::l()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'l';
m_history[m_historyNum] = '\0';
}
rotateXMiddleACW();
rotateXLeftACW();
}
void MagicSquareSolver::d2()
{
d();
d();
}
void MagicSquareSolver::dr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'd';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
//(this->*RotateFunTable[Y][NEGATIVE][CLOCKWISE])(3);
rotateYDownCW();
rotateYMiddleCW();
}
void MagicSquareSolver::d()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'd';
m_history[m_historyNum] = '\0';
}
rotateYMiddleACW();
rotateYDownACW();
}
void MagicSquareSolver::f2()
{
f();
f();
}
void MagicSquareSolver::fr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'f';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateZFrontACW();
rotateZMiddleACW();
}
void MagicSquareSolver::f()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'f';
m_history[m_historyNum] = '\0';
}
rotateZFrontCW();
rotateZMiddleCW();
}
void MagicSquareSolver::r2()
{
r();
r();
}
void MagicSquareSolver::rr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'r';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateXRightACW();
rotateXMiddleACW();
}
void MagicSquareSolver::r()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'r';
m_history[m_historyNum] = '\0';
}
rotateXRightCW();
rotateXMiddleCW();
}
void MagicSquareSolver::u2()
{
u();
u();
}
void MagicSquareSolver::ur()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'u';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateYUpACW();
rotateYMiddleACW();
}
void MagicSquareSolver::u()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'u';
m_history[m_historyNum] = '\0';
}
rotateYUpCW();
rotateYMiddleCW();
}
void MagicSquareSolver::z2()
{
z();
z();
}
void MagicSquareSolver::zr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'z';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateZBackACW();
rotateZMiddleACW();
rotateZFrontACW();
}
void MagicSquareSolver::z()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'z';
m_history[m_historyNum] = '\0';
}
rotateZBackCW();
rotateZMiddleCW();
rotateZFrontCW();
}
void MagicSquareSolver::y2()
{
y();
y();
}
void MagicSquareSolver::yr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'y';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateYDownACW();
rotateYMiddleACW();
rotateYUpACW();
}
void MagicSquareSolver::y()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'y';
m_history[m_historyNum] = '\0';
}
rotateYDownCW();
rotateYMiddleCW();
rotateYUpCW();
}
void MagicSquareSolver::x2()
{
x();
x();
}
void MagicSquareSolver::xr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'x';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateXLeftACW();
rotateXMiddleACW();
rotateXRightACW();
}
void MagicSquareSolver::x()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'x';
m_history[m_historyNum] = '\0';
}
rotateXLeftCW();
rotateXMiddleCW();
rotateXRightCW();
}
void MagicSquareSolver::D2()
{
D();
D();
}
void MagicSquareSolver::U2()
{
U();
U();
}
void MagicSquareSolver::L2()
{
L();
L();
}
void MagicSquareSolver::R2()
{
R();
R();
}
void MagicSquareSolver::B2()
{
B();
B();
}
void MagicSquareSolver::F2()
{
F();
F();
}
void MagicSquareSolver::S2()
{
S();
S();
}
void MagicSquareSolver::Sr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'S';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateZMiddleCW();
}
void MagicSquareSolver::S()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'S';
m_history[m_historyNum] = '\0';
}
rotateZMiddleCW();
}
void MagicSquareSolver::M2()
{
E();
E();
}
void MagicSquareSolver::Mr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'M';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateXMiddleACW();
}
void MagicSquareSolver::M()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'M';
m_history[m_historyNum] = '\0';
}
rotateXMiddleCW();
}
void MagicSquareSolver::E2()
{
E();
E();
}
void MagicSquareSolver::Er()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'E';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateYMiddleACW();
}
void MagicSquareSolver::E()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'E';
m_history[m_historyNum] = '\0';
}
rotateYMiddleCW();
}
void MagicSquareSolver::Dr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'D';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateYDownCW();
}
void MagicSquareSolver::D()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'D';
m_history[m_historyNum] = '\0';
}
rotateYDownACW();
}
void MagicSquareSolver::Ur()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'U';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateYUpACW();
}
void MagicSquareSolver::U()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'U';
m_history[m_historyNum] = '\0';
}
rotateYUpCW();
}
void MagicSquareSolver::Lr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'L';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateXLeftCW();
}
void MagicSquareSolver::L()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'L';
m_history[m_historyNum] = '\0';
}
rotateXLeftACW();
}
void MagicSquareSolver::Rr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'R';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateXRightACW();
}
void MagicSquareSolver::R()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'R';
m_history[m_historyNum] = '\0';
}
rotateXRightCW();
}
void MagicSquareSolver::Br()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'B';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateZBackCW();
}
void MagicSquareSolver::B()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'B';
m_history[m_historyNum] = '\0';
}
rotateZBackACW();
}
void MagicSquareSolver::Fr()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'F';
m_history[m_historyNum++] = '\'';
m_history[m_historyNum] = '\0';
}
rotateZFrontACW();
}
void MagicSquareSolver::F()
{
if (m_historyNum<1024-8)
{
m_history[m_historyNum++] = 'F';
m_history[m_historyNum] = '\0';
}
rotateZFrontCW();
}
//==================^_^==================^_^==================^_^==================^_^
MagicSquarePlayer::RotateFun MagicSquarePlayer::RotateFunTable[3][3][2] =
{
//x from negative to positive,i.e. from left to right
{ {&MagicSquarePlayer::rotateXLeftCW , &MagicSquarePlayer::rotateXLeftACW},
{&MagicSquarePlayer::rotateXMiddleCW, &MagicSquarePlayer::rotateXMiddleACW},
{&MagicSquarePlayer::rotateXRightCW , &MagicSquarePlayer::rotateXRightACW}
},
//y
{ {&MagicSquarePlayer::rotateYDownCW , &MagicSquarePlayer::rotateYDownACW},
{&MagicSquarePlayer::rotateYMiddleCW, &MagicSquarePlayer::rotateYMiddleACW},
{&MagicSquarePlayer::rotateYUpCW , &MagicSquarePlayer::rotateYUpACW}
},
//z
{ {&MagicSquarePlayer::rotateZBackCW , &MagicSquarePlayer::rotateZBackACW},
{&MagicSquarePlayer::rotateZMiddleCW, &MagicSquarePlayer::rotateZMiddleACW},
{&MagicSquarePlayer::rotateZFrontCW , &MagicSquarePlayer::rotateZFrontACW}
},
};
MagicSquarePlayer::MagicSquarePlayer()
:m_movieCube3(NULL)
,m_movieOrnament(NULL)
,m_rotAnimAng(0)
,RotSpeed(HALFPI)
{
memset(m_executeStr,0,sizeof(m_executeStr));
m_blockFrames = new Frame[BlockNum];
m_ornamentFrames = new Frame[OrnamentNum];
float len = BlockSize * 0.707106f;
//vertexes for every aspect
//front
blockVertexes[FRONT][0][0] = vec2I();
blockVertexes[FRONT][0][1].x = 0;
blockVertexes[FRONT][0][1].y = - BlockSize;
blockVertexes[FRONT][0][2].x = BlockSize;
blockVertexes[FRONT][0][2].y = - BlockSize;
blockVertexes[FRONT][0][3].x = BlockSize;
blockVertexes[FRONT][0][3].y = 0;
for(int i = 1; i <= 2; i++)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[FRONT][i][ind].x = blockVertexes[FRONT][i - 1][ind].x + BlockSize;
blockVertexes[FRONT][i][ind].y = blockVertexes[FRONT][0][ind].y;
}
}
for(int i = 3; i <= 8; i++)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[FRONT][i][ind].x = blockVertexes[FRONT][i - 3][ind].x;
blockVertexes[FRONT][i][ind].y = blockVertexes[FRONT][i - 3][ind].y - BlockSize;
}
}
//back
vec2I v(int(BlockSize * 3 + int(len * 3)), int(- int(len * 3)));
blockVertexes[BACK][2][0] = v;
blockVertexes[BACK][2][1].x = v.x;
blockVertexes[BACK][2][1].y = v.y - BlockSize;
blockVertexes[BACK][2][2].x = v.x + BlockSize;
blockVertexes[BACK][2][2].y = v.y - BlockSize;
blockVertexes[BACK][2][3].x = v.x + BlockSize;
blockVertexes[BACK][2][3].y = v.y;
for(int i = 1; i >= 0; i--)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[BACK][i][ind].x = blockVertexes[BACK][i + 1][ind].x + BlockSize;
blockVertexes[BACK][i][ind].y = blockVertexes[BACK][2][ind].y;
}
}
for(int i = 3; i <= 8; i++)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[BACK][i][ind].x = blockVertexes[BACK][i - 3][ind].x;
blockVertexes[BACK][i][ind].y = blockVertexes[BACK][i - 3][ind].y - BlockSize;
}
}
//left
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[LEFT][0][ind].x = blockVertexes[FRONT][0][ind].x - BlockSize * 3;
blockVertexes[LEFT][0][ind].y = blockVertexes[FRONT][0][ind].y;
}
for(int i = 1; i <= 2; i++)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[LEFT][i][ind].y = blockVertexes[LEFT][i - 1][ind].y - BlockSize;
blockVertexes[LEFT][i][ind].x = blockVertexes[LEFT][0][ind].x;
}
}
for(int i = 3; i <= 8; i++)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[LEFT][i][ind].x = blockVertexes[LEFT][i - 3][ind].x + BlockSize;
blockVertexes[LEFT][i][ind].y = blockVertexes[LEFT][i - 3][ind].y;
}
}
//right
blockVertexes[RIGHT][0][3] = v;
blockVertexes[RIGHT][0][0].x = v.x - int(len);
blockVertexes[RIGHT][0][0].y = v.y + int(len);
blockVertexes[RIGHT][0][1].x = blockVertexes[RIGHT][0][0].x;
blockVertexes[RIGHT][0][1].y = blockVertexes[RIGHT][0][0].y - BlockSize;
blockVertexes[RIGHT][0][2].x = blockVertexes[RIGHT][0][3].x;
blockVertexes[RIGHT][0][2].y = blockVertexes[RIGHT][0][3].y - BlockSize;
for(int i = 1; i <= 2; i++)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[RIGHT][i][ind].y = blockVertexes[RIGHT][i - 1][ind].y - BlockSize;
blockVertexes[RIGHT][i][ind].x = blockVertexes[RIGHT][0][ind].x;
}
}
for(int i = 3; i <= 8; i++)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[RIGHT][i][ind].x = blockVertexes[RIGHT][i - 3][ind].x - int(len);
blockVertexes[RIGHT][i][ind].y = blockVertexes[RIGHT][i - 3][ind].y + int(len);
}
}
//up
v.x = int(len * 3);
v.y = - int(len * 3) - BlockSize * 3;
blockVertexes[UP][0][0].x = v.x - int(len);
blockVertexes[UP][0][0].y = v.y + int(len);
blockVertexes[UP][0][1] = v;
blockVertexes[UP][0][2].x = v.x + BlockSize;
blockVertexes[UP][0][2].y = v.y;
blockVertexes[UP][0][3].x = blockVertexes[UP][0][0].x + BlockSize;
blockVertexes[UP][0][3].y = blockVertexes[UP][0][0].y;
for(int i = 1; i <= 2; i++)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[UP][i][ind].x = blockVertexes[UP][i - 1][ind].x + BlockSize;
blockVertexes[UP][i][ind].y = blockVertexes[UP][0][ind].y;
}
}
for(int i = 3; i <= 8; i++)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[UP][i][ind].x = blockVertexes[UP][i - 3][ind].x - int(len);
blockVertexes[UP][i][ind].y = blockVertexes[UP][i - 3][ind].y + int(len);
}
}
//down
for(int i = 0; i < 9; i++)
{
for(int ind = 0; ind < 4; ind++)
{
blockVertexes[DOWN][i][ind].x = blockVertexes[FRONT][i][ind].x;
blockVertexes[DOWN][i][ind].y = blockVertexes[FRONT][i][ind].y + BlockSize * 3;
}
}
aspectVertexes[0][0] = blockVertexes[0][0][0];
aspectVertexes[0][1] = blockVertexes[0][6][1];
aspectVertexes[0][2] = blockVertexes[0][8][2];
aspectVertexes[0][3] = blockVertexes[0][2][3];
aspectVertexes[1][0] = blockVertexes[1][2][0];
aspectVertexes[1][1] = blockVertexes[1][8][1];
aspectVertexes[1][2] = blockVertexes[1][6][2];
aspectVertexes[1][3] = blockVertexes[1][0][3];
aspectVertexes[2][0] = blockVertexes[2][0][0];
aspectVertexes[2][1] = blockVertexes[2][2][1];
aspectVertexes[2][2] = blockVertexes[2][8][2];
aspectVertexes[2][3] = blockVertexes[2][6][3];
aspectVertexes[3][0] = blockVertexes[3][6][0];
aspectVertexes[3][1] = blockVertexes[3][8][1];
aspectVertexes[3][2] = blockVertexes[3][2][2];
aspectVertexes[3][3] = blockVertexes[3][0][3];
aspectVertexes[4][0] = blockVertexes[4][6][0];
aspectVertexes[4][1] = blockVertexes[4][0][1];
aspectVertexes[4][2] = blockVertexes[4][2][2];
aspectVertexes[4][3] = blockVertexes[4][8][3];
aspectVertexes[5][0] = blockVertexes[5][0][0];
aspectVertexes[5][1] = blockVertexes[5][6][1];
aspectVertexes[5][2] = blockVertexes[5][8][2];
aspectVertexes[5][3] = blockVertexes[5][2][3];
}
MagicSquarePlayer::~MagicSquarePlayer()
{
SafeDeleteArray(m_blockFrames);
SafeDeleteArray(m_ornamentFrames);
}
bool MagicSquarePlayer::Start()
{
MiniPlayer::Start();
G_TextureMgr->AddTexture(m_texture,"data/minigame/magicsquare/cube.png");
m_colorTexRects[BLUE ] = RectF(0.25f,0.0f,0.25f,0.5f);
m_colorTexRects[GREEN ] = RectF(0.25f,0.5f,0.25f,0.5f);
m_colorTexRects[RED ] = RectF(0.0f,0.0f,0.25f,0.5f);
m_colorTexRects[ORANGE] = RectF(0.0f,0.5f,0.25f,0.5f);
m_colorTexRects[WHITE ] = RectF(0.5f,0.5f,0.25f,0.5f);
m_colorTexRects[YELLOW] = RectF(0.5f,0.0f,0.25f,0.5f);
m_colorTexRects[GRAY ] = RectF(0.75f,0.5f,0.25f,0.5f);
//m_tileNum = vec3I(2, 3, 4);
//加载魔方
Frame frame;
if (m_movieCube3 == NULL)
{
LoadConfig loader(LoadConfig::GenDonotReShrinkBound, true, true);
m_movieCube3 = new RendSys::MovieClip;
m_movieCube3->LoadFromFile("data/minigame/magicsquare/cube.movie", &loader);
frame.SetPos(m_startPos);
m_movieCube3->SetProgramFrame(&frame);
m_movieCube3->Advance();
}
if (m_movieCube3->IsLoadComplete() == false)
{
return false;
}
//查找block
char buf[512];
for (int i=0;i<9;i++)
{
sprintf(buf,"block0%d",i+1);
m_movieBlocks[i] = m_movieCube3->GetMovieClip(buf);
}
for (int i=0;i<8;i++)
{
sprintf(buf,"block1%d",i+1);
m_movieBlocks[9+i] = m_movieCube3->GetMovieClip(buf);
}
for (int i=0;i<9;i++)
{
sprintf(buf,"block2%d",i+1);
m_movieBlocks[17+i] = m_movieCube3->GetMovieClip(buf);
}
//清除关键帧 设置位置
MC_Frame* frameMovie;
frame.m_matrix.Identity();
for (int i=0;i<BlockNum;i++)
{
frameMovie = dynamic_cast<MC_Frame*>(m_movieBlocks[i]);
frame.SetPos(frameMovie->GetFrameLine()->m_keyFrames[0].m_pos);
frameMovie->ZeroFrames();
frameMovie->SetProgramFrame(&frame);
}
//高亮movie
m_movieSelect = m_movieCube3->GetMovieClip("select1");
if (m_movieSelect)
{
m_movieSelect->SetPickable(false);
}
//装饰movie
if (m_movieOrnament == NULL)
{
LoadConfig loader(LoadConfig::DonotGenAABBTree, true, true);
m_movieOrnament = new RendSys::MovieClip;
m_movieOrnament->LoadFromFile("data/minigame/magicsquare/ornament.movie", &loader);
frame.m_matrix.Identity();
frame.SetPos(m_startPos);
m_movieOrnament->SetProgramFrame(&frame);
m_movieOrnament->Advance();
}
m_ornamentBlockNum = 0;
if (m_movieOrnament->IsLoadComplete())
{
//清除关键帧 设置位置
MovieThrough thtorgh(m_movieOrnament);
MovieClip* subMovie = thtorgh.GetFirst();
while (subMovie && m_ornamentBlockNum<OrnamentNum)
{
m_movieOrnamentBlocks[m_ornamentBlockNum++] = subMovie;
frameMovie = dynamic_cast<MC_Frame*>(subMovie);
if (frameMovie)
{
frame.SetPos(frameMovie->GetFrameLine()->m_keyFrames[0].m_pos);
frameMovie->ZeroFrames();
frameMovie->SetProgramFrame(&frame);
}
RendSys::MC_Particle* particleMovie = dynamic_cast<MC_Particle*>(subMovie);
if (particleMovie)
{
frame.SetPos(particleMovie->GetFrameLine()->m_keyFrames[0].m_pos);
particleMovie->ZeroFrames();
particleMovie->SetProgramFrame(&frame);
}
subMovie = thtorgh.GetNext();
}
}
//
m_rotAnimAng = 0;
m_state = None;
Reset();
return true;
}
bool MagicSquarePlayer::Stop()
{
SafeDelete(m_movieCube3);
MiniPlayer::Stop();
return true;
}
void MagicSquarePlayer::AnimRotate(float ang)
{
mat4 mat;
mat.FromAxisAngle(m_rotAxis,ang);
Frame frame;
//旋转动画
for (int i=0;i<BlockNum;i++)
{
if(m_bBlockRotating[i])
{
frame.m_matrix = mat * m_blockFrames[i].m_matrix;
m_movieBlocks[i]->SetProgramFrame(&frame);
}
}
for (int i=0;i<m_ornamentBlockNum;i++)
{
if(m_bOrnamentRotating[i])
{
frame.m_matrix = mat * m_ornamentFrames[i].m_matrix;
m_movieOrnamentBlocks[i]->SetProgramFrame(&frame);
}
}
}
void MagicSquarePlayer::BackupFrame(const AABB& bound)
{
for (int i=0;i<BlockNum;i++)
{
Frame* frame = m_movieBlocks[i]->GetProgramFrame();
if(TestPointAABB(frame->m_matrix.GetTranslate(),bound))
{
m_blockFrames[i] = *frame;
m_bBlockRotating[i] = true;
}
else
{
m_bBlockRotating[i] = false;
}
}
for (int i=0;i<m_ornamentBlockNum;i++)
{
Frame* frame = m_movieOrnamentBlocks[i]->GetProgramFrame();
if(TestPointAABB(frame->m_pos,bound))
{
m_ornamentFrames[i] = *frame;
m_bOrnamentRotating[i] = true;
}
else
{
m_bOrnamentRotating[i] = false;
}
}
}
void MagicSquarePlayer::RestoreFrame()
{
for (int i=0;i<BlockNum;i++)
{
if(m_bBlockRotating[i] == true)
{
m_movieBlocks[i]->SetProgramFrame(&m_blockFrames[i]);
}
}
for (int i=0;i<m_ornamentBlockNum;i++)
{
if(m_bOrnamentRotating[i] == true)
{
m_movieOrnamentBlocks[i]->SetProgramFrame(&m_ornamentFrames[i]);
}
}
}
void MagicSquarePlayer::rotate3D(const AABB& bound,const vec3& axis)
{
//若上次旋转动画未结束,结束之
if(m_state == AnimRotating && m_rotAnimAng<HALFPI)
{
AnimRotate(HALFPI);
}
//保存初始位置
m_state = AnimRotating;
m_rotAnimAng = 0;
m_rotAxis = axis;
BackupFrame(bound);
//
G_MagicSquareGame->PlaySound__("data/sound/gladiator/punchUnHit.wav");
}
void MagicSquarePlayer::Update()
{
MiniPlayer::Update();
if (m_state == AnimRotating)
{
//90度旋转动画
if (m_rotAnimAng < 0)
{
m_rotAnimAng = 0;
}
else if (m_rotAnimAng < HALFPI)
{
m_rotAnimAng += G_Timer->GetStepTimeLimited()*RotSpeed;
}
if (m_rotAnimAng >= HALFPI)
{
m_rotAnimAng = HALFPI; //模型规整到90度
if (m_executeStr[0]==0)
{
m_state = None;
}
else
{
m_state = ExecuteRotating;
}
}
//旋转动画
AnimRotate(m_rotAnimAng);
}
else if (m_state == DragRotating)
{
if (m_dragRotDecided)
{
//旋转动画
AnimRotate(m_rotAnimAng);
}
}
else if (m_state==ExecuteRotating)
{
if (m_executeStr[0]!=0)
{
char buf[4]={0,0,0,0};
buf[0] = m_executeStr[0];
buf[1] = m_executeStr[1];
if (buf[1]!='\'')
{
buf[1] = 0;
}
int len = strlen(m_executeStr)-strlen(buf);
if(len>0)
memmove(m_executeStr,m_executeStr+strlen(buf),len);
m_executeStr[len] = 0;
Execute(buf);
}
else
{
m_state = None;
}
}
if (m_movieOrnament)
{
m_movieOrnament->Advance();
}
if (m_movieCube3)
{
m_movieCube3->Advance();
}
}
void MagicSquarePlayer::Render()
{
G_RendDriver->EndUI();
if (m_movieCube3)
{
m_movieCube3->RendClip();
}
if (m_movieOrnament)
{
m_movieOrnament->RendClip();
}
G_RendDriver->BeginUI();
显示思考中
//if(G_MagicSquareGame->m_gameState==MS_Gamming
// &&G_MagicSquareGame->m_curSide == m_side)
//{
// //m_ctrlThink->SetVisible(true);
// int index = int(G_Timer->GetAccumTime()*10)%4;
// Texture* texture = G_MagicSquareGame->m_thinkTexture[index];
// texture->Bind();
// //if(m_screenPos == SP_Down)
// if(dynamic_cast<MagicSquarePlayerRole*>(this))
// {
// G_RendDriver->DrawTextureRect(vec2(G_Window->m_iWidth-G_MagicSquareGame->Offset.x , G_Window->m_iHeight- G_MagicSquareGame->Offset.y-texture->GetHeight()));
// }
// else
// {
// G_RendDriver->DrawTextureRect(vec2(G_Window->m_iWidth-G_MagicSquareGame->Offset.x , G_MagicSquareGame->Offset.y));
// }
//}
选中
//if(m_manSelected!=ID_MAN_NULL)
//{
// Texture* tex = m_side==SideRed?G_MagicSquareGame->m_textureSelectGreen:G_MagicSquareGame->m_textureSelectRed;
// tex->Bind();
// vec2I pos;
// G_MagicSquareGame->PointToScreen(G_MagicSquareGame->m_manPoint[m_manSelected],pos);
// G_RendDriver->DrawTextureRect(RectF(pos.x,pos.y,BoardCellWidth,BoardCellWidth));
//}
m_offset = vec2I(100,230);
G_RendDriver->BlendFunc(Blend_Filter);
//G_RendDriver->SetRenderStateEnable(RS_DEPTH_TEST, true);
G_RendDriver->SetRenderStateEnable(RS_TEXTURE_2D, true);
G_RendDriver->PushMatrix();
G_RendDriver->Translatef(m_offset.x,-m_offset.y,0);
m_texture->Bind();
for(int i = 0; i < 6; i++)
{
for(int asp = 0; asp < 9; asp++)
{
RectF tex = m_colorTexRects[m_blockColors[i][asp]];
vec2I* v = &blockVertexes[i][asp][0];
//G_RendDriver->DrawTextureRect(RectF(v->x,v->y,BlockSize,BlockSize),tex);
G_RendDriver->RendBegin(RS_QUADS);
G_RendDriver->TexCoord2f(tex.x,tex.y);
G_RendDriver->Vertex3f(v->s,G_Window->m_iHeight- v->y,0);
v++;
G_RendDriver->TexCoord2f(tex.x+tex.width,tex.y);
G_RendDriver->Vertex3f(v->s,G_Window->m_iHeight- v->y,0);
v++;
G_RendDriver->TexCoord2f(tex.x+tex.width,tex.y+tex.height);
G_RendDriver->Vertex3f(v->s,G_Window->m_iHeight- v->y,0);
v++;
G_RendDriver->TexCoord2f(tex.x,tex.y+tex.height);
G_RendDriver->Vertex3f(v->s,G_Window->m_iHeight- v->y,0);
G_RendDriver->RendEnd();
}
}
G_RendDriver->PopMatrix();
G_RendDriver->EndUI();
}
bool MagicSquarePlayer::IsInThisRect(vec2I* pts, const vec2I& point)
{
if(pts[0].x == pts[1].x)
{
if(pts[0].y == pts[3].y) //rectangle
{
if(point.x > pts[0].x && point.x < pts[3].x &&
point.y < pts[0].y && point.y > pts[1].y)
{
return true;
}
}
else //irregular quadrangle:3
{
int vdist = point.x - pts[0].x;
if(point.x > pts[0].x && point.x < pts[3].x &&
point.y < pts[0].y - vdist && point.y > pts[1].y - vdist)
{
return true;
}
}
}
else //irregular quadrangle:4
{
int vdist = pts[0].y - point.y;
if(point.y < pts[0].y && point.y > pts[1].y &&
point.x > pts[0].x + vdist && point.x < pts[3].x + vdist)
{
return true;
}
}
return false;
}
FaceDir MagicSquarePlayer::GetAspect(const vec2I& point)
{
for(int i = 0; i < 6; i++)
{
if(IsInThisRect(aspectVertexes[i], point))
{
return FaceDir(i);
}
}
return NOASPECT;
}
int MagicSquarePlayer::GetSmallAspectIndex(FaceDir asp, const vec2I& point)
{
for(int i = 0; i < 9; i++)
{
if(IsInThisRect(blockVertexes[asp][i], point))
{
return i;
}
}
return -1;
}
void MagicSquarePlayer::Reset()
{
m_executeStr[0] = 0;
MagicSquareSolver::Reset();
m_rotAnimAng = 0;
int snapAlign = 5;//10
//
mat4 mat;
for (int i=0;i<BlockNum;i++)
{
MovieClip* movie = m_movieBlocks[i];
Frame* frame = movie->GetProgramFrame();
mat = frame->m_matrix;
mat.SetTranslate(vec3());
mat.Inverse();
{
mat = mat * frame->m_matrix;
vec3 pos = mat.GetTranslate();
pos.x = floor(pos.x/snapAlign+0.5f)*snapAlign;
pos.y = floor(pos.y/snapAlign+0.5f)*snapAlign;
pos.z = floor(pos.z/snapAlign+0.5f)*snapAlign;
frame->m_matrix.Identity();
frame->SetPos(pos);
movie->SetProgramFrame(frame);
}
m_bBlockRotating[i] = false;
}
for (int i=0;i<m_ornamentBlockNum;i++)
{
MovieClip* movie = m_movieOrnamentBlocks[i];
Frame* frame = movie->GetProgramFrame();
mat = frame->m_matrix;
mat.SetTranslate(vec3());
mat.Inverse();
{
mat = mat * frame->m_matrix;
vec3 pos = mat.GetTranslate();
pos.x = floor(pos.x/snapAlign+0.5f)*snapAlign;
pos.y = floor(pos.y/snapAlign+0.5f)*snapAlign;
pos.z = floor(pos.z/snapAlign+0.5f)*snapAlign;
frame->m_matrix.Identity();
frame->SetPos(pos);
movie->SetProgramFrame(frame);
}
m_bOrnamentRotating[i] = false;
}
}
void MagicSquarePlayer::OnRandom()
{
Reset();
char buf[128] = "";
int scrambleNumber = 30;
while(scrambleNumber-- > 0)
{
strcat(buf,RotateFunNameTable[rand() % 3][rand() % 2 * 2][rand() % 2]);
}
OnExecute(buf);
}
void MagicSquarePlayer::OnSolution()
{
MagicSquareSolver tempSolver = *this;
tempSolver.MethodFewerFormula();
OnExecute(tempSolver.m_history);
}
void MagicSquarePlayer::OnExecute(const char* str)
{
//MagicSquareSolver::Execute(str);
if (m_state==None)
{
m_state = ExecuteRotating;
}
else if (m_state==DragRotating)
{
//等待结束后自动跳转
}
else if (m_state==AnimRotating)
{
//等待结束后自动跳转 否则模型没转到90度
}
strcpy_s(m_executeStr,str);
m_executeStr[sizeof(m_executeStr)-1] = 0;
}
void MagicSquarePlayer::OnStopExecute()
{
m_executeStr[0] = 0;
}
void MagicSquarePlayer::rotateFullAspectCW(FaceDir asp, int* index)
{
MagicSquareSolver::rotateFullAspectCW(asp, index);
}
void MagicSquarePlayer::rotateFullAspectACW(FaceDir asp, int* index)
{
MagicSquareSolver::rotateFullAspectACW(asp, index);
}
void MagicSquarePlayer::rotateXLeftCW(int flag)
{
//L'
//.x < -5
if (flag&2) rotate3D(AABB(vec3(-1000,-1000,-1000) ,vec3(-5,1000,1000)),vec3(-1,0,0));
MagicSquareSolver::rotateXLeftCW(flag);
}
void MagicSquarePlayer::rotateXLeftACW(int flag)
{
//L
//.x < -5
if (flag&2) rotate3D(AABB(vec3(-1000,-1000,-1000) ,vec3(-5,1000,1000)),vec3(1,0,0));
MagicSquareSolver::rotateXLeftACW(flag);
}
void MagicSquarePlayer::rotateXRightCW(int flag)
{
//R
//.x > 5
if (flag&2) rotate3D(AABB(vec3(5,-1000,-1000) ,vec3(1000,1000,1000)),vec3(-1,0,0));
MagicSquareSolver::rotateXRightCW(flag);
}
void MagicSquarePlayer::rotateXRightACW(int flag)
{
//R'
//.x > 5
if (flag&2) rotate3D(AABB(vec3(5,-1000,-1000) ,vec3(1000,1000,1000)),vec3(1,0,0));
MagicSquareSolver::rotateXRightACW(flag);
}
void MagicSquarePlayer::rotateXMiddleCW(int flag)
{
//
//-5 < .x < 5
if (flag&2) rotate3D(AABB(vec3(-5,-1000,-1000) ,vec3(5,1000,1000)),vec3(-1,0,0));
MagicSquareSolver::rotateXMiddleCW(flag);
}
void MagicSquarePlayer::rotateXMiddleACW(int flag)
{
//
//-5 < .x < 5
if (flag&2) rotate3D(AABB(vec3(-5,-1000,-1000) ,vec3(5,1000,1000)),vec3(1,0,0));
MagicSquareSolver::rotateXMiddleACW(flag);
}
void MagicSquarePlayer::rotateYDownCW(int flag)
{
//Dr
//.y < -5
if (flag&2) rotate3D(AABB(vec3(-1000,-1000,-1000) ,vec3(1000,-5,1000)),vec3(0,-1,0));
MagicSquareSolver::rotateYDownCW(flag);
}
void MagicSquarePlayer::rotateYDownACW(int flag)
{
//D
//.y < -5
if (flag&2) rotate3D(AABB(vec3(-1000,-1000,-1000) ,vec3(1000,-5,1000)),vec3(0,1,0));
MagicSquareSolver::rotateYDownACW(flag);
}
void MagicSquarePlayer::rotateYUpCW(int flag)
{
//U
//.y > 5
if (flag&2) rotate3D(AABB(vec3(-1000,5,-1000) ,vec3(1000,1000,1000)),vec3(0,-1,0));
MagicSquareSolver::rotateYUpCW(flag);
}
void MagicSquarePlayer::rotateYUpACW(int flag)
{
//U'
//.y > 5
if (flag&2) rotate3D(AABB(vec3(-1000,5,-1000) ,vec3(1000,1000,1000)),vec3(0,1,0));
MagicSquareSolver::rotateYUpACW(flag);
}
void MagicSquarePlayer::rotateYMiddleCW(int flag)
{
//
//-5 < .y < 5
if (flag&2) rotate3D(AABB(vec3(-1000,-5,-1000) ,vec3(1000,5,1000)),vec3(0,-1,0));
MagicSquareSolver::rotateYMiddleCW(flag);
}
void MagicSquarePlayer::rotateYMiddleACW(int flag)
{
//
//-5 < .y < 5
if (flag&2) rotate3D(AABB(vec3(-1000,-5,-1000) ,vec3(1000,5,1000)),vec3(0,1,0));
MagicSquareSolver::rotateYMiddleACW(flag);
}
void MagicSquarePlayer::rotateZFrontCW(int flag)
{
//F
//.z > 5
if (flag&2) rotate3D(AABB(vec3(-1000,-1000,5) ,vec3(1000,1000,1000)),vec3(0,0,-1));
MagicSquareSolver::rotateZFrontCW(flag);
}
void MagicSquarePlayer::rotateZFrontACW(int flag)
{
//F'
//.z > 5
if (flag&2) rotate3D(AABB(vec3(-1000,-1000,5) ,vec3(1000,1000,1000)),vec3(0,0,1));
MagicSquareSolver::rotateZFrontACW(flag);
}
void MagicSquarePlayer::rotateZBackCW(int flag)
{
//B'
//.z < -5
if (flag&2) rotate3D(AABB(vec3(-1000,-1000,-1000) ,vec3(1000,1000,-5)),vec3(0,0,-1));
MagicSquareSolver::rotateZBackCW(flag);
}
void MagicSquarePlayer::rotateZBackACW(int flag)
{
//B
//.z < -5
if (flag&2) rotate3D(AABB(vec3(-1000,-1000,-1000) ,vec3(1000,1000,-5)),vec3(0,0,1));
MagicSquareSolver::rotateZBackACW(flag);
}
void MagicSquarePlayer::rotateZMiddleCW(int flag)
{
//
//-5 < .z < 5
if (flag&2) rotate3D(AABB(vec3(-1000,-1000,-5) ,vec3(1000,1000,5)),vec3(0,0,-1));
MagicSquareSolver::rotateZMiddleCW(flag);
}
void MagicSquarePlayer::rotateZMiddleACW(int flag)
{
//
//-5 < .z < 5
if (flag&2) rotate3D(AABB(vec3(-1000,-1000,-5) ,vec3(1000,1000,5)),vec3(0,0,1));
MagicSquareSolver::rotateZMiddleACW(flag);
}
玩家自身:
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/MagicSquare/MagicSquare.cpp
// @Brief: MagicSquare
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#include "General/Pch.h"
#include "General/Window.h"
#include "MagicSquare/MagicSquareRole.h"
#include "MagicSquare/MiniGameMagicSquare.h"
#include "General/Timer.h"
#include "Rpg/SyncGameInfo.h"
#include "Sound/SoundManager.h"
#include "Packet/PacketMiniGame.h"
#include "Input/InputMgr.h"
#include "Render/Camera.h"
#include "Render/RendDriver.h"
#include "Render/MC_MovieClip.h"
#include "General/Pce.h"
#include "Math/MathLibAdvance.h"
MagicSquarePlayerRole::MagicSquarePlayerRole()
:m_colorSelected(BLUE)
{
m_workingWithAI = false;
}
MagicSquarePlayerRole::~MagicSquarePlayerRole()
{
}
bool MagicSquarePlayerRole::Start()
{
if(MagicSquarePlayerRobot::Start()==false)
return false;
m_colorSelected = BLUE;
return true;
}
void MagicSquarePlayerRole::Reset()
{
MagicSquarePlayerRobot::Reset();
m_colorSelected = BLUE;
}
vec3 NearestAxis(const vec3& dir)
{
float absX = (dir.x>0?dir.x:-dir.x);
float absY = (dir.y>0?dir.y:-dir.y);
float absZ = (dir.z>0?dir.z:-dir.z);
vec3 axis;
if (absX > absY && absX > absZ)
{
axis.x = (dir.x>0?1:-1);
}
else if (absY > absX && absY > absZ)
{
axis.y = (dir.y>0?1:-1);
}
else
{
axis.z = (dir.z>0?1:-1);
}
return axis;
}
void MagicSquarePlayerRole::Update()
{
if(m_workingWithAI)
{
return MagicSquarePlayerRobot::Update();
}
MagicSquarePlayer::Update();
if (G_Mouse->IsButtonDowning(MOUSE_LEFT))
{
vec2 pos = G_Mouse->GetMousePos();
OnLButtonDown(vec2I(pos.x,pos.y));
}
m_movieSelect->SetVisible(m_state==None || m_state==DragRotating,Recursive);
vec3 dir;
vec3 start;
G_Camera->GetMouseTray(start,dir);
vec3 end = start+10000*dir;
RayMovieCollideRes res(start,end);
if (m_state==None)
{
Frame frame;
int snapAlign = 10;
if(m_movieCube3->IntersectTray(res))
{
//pos
int flag = 0;
vec3 regularPos = res.resPos - m_startPos;
if (abs(res.resNorml.x)<0.5f)
{
regularPos.x = floor(regularPos.x/snapAlign+0.5f)*snapAlign;
flag++;
}
if (abs(res.resNorml.y)<0.5f)
{
regularPos.y = floor(regularPos.y/snapAlign+0.5f)*snapAlign;
flag++;
}
if (abs(res.resNorml.z)<0.5f)
{
regularPos.z = floor(regularPos.z/snapAlign+0.5f)*snapAlign;
flag++;
}
//rot
vec3 regularNormal = NearestAxis(res.resNorml);
if (abs(res.resNorml.x) < abs(res.resNorml.y)
&& abs(res.resNorml.x)<abs(res.resNorml.z))
{
frame.m_matrix.FromToDir(vec3(0,1,0),vec3(0,0,1),res.resNorml,vec3(res.resNorml.x,-res.resNorml.z,res.resNorml.y));
}
else if (abs(res.resNorml.y) < abs(res.resNorml.x)
&& abs(res.resNorml.y) < abs(res.resNorml.z))
{
frame.m_matrix.FromToDir(vec3(0,1,0),vec3(0,0,1),res.resNorml,vec3(-res.resNorml.z,res.resNorml.y,res.resNorml.x));
}
else
{
frame.m_matrix.FromToDir(vec3(0,1,0),vec3(0,0,1),res.resNorml,vec3(-res.resNorml.y,res.resNorml.x,res.resNorml.z));
}
frame.m_matrix .SetTranslate(regularPos);
if (G_Mouse->IsButtonDowning(MOUSE_LEFT)
&&flag==2
)
{
//已经选中初始 facelet 还未确定旋转方向
m_state = MagicSquarePlayer::DragRotating;
m_dragRotDecided = false;
m_dragStartMovie = res.resClip;
m_dragBeginRegularPos = regularPos;
m_dragBeginRegularNormal = regularNormal;
m_dragBeginMousePos = G_Mouse->GetMousePos();
m_rotAnimAng = 0;
}
}
else
{
frame.m_matrix .SetTranslate(vec3()-m_startPos);
}
m_movieSelect->SetProgramFrame(&frame);
}
else if (m_state==DragRotating)
{
if (G_Mouse->IsButtonPressed(MOUSE_LEFT))
{
if (m_dragRotDecided==false)
{
if(m_movieCube3->IntersectTray(res) && res.resClip!=m_dragStartMovie)
{
//开始确定方向
vec3 pos = res.resPos - m_startPos;
m_dragRotDecided = true;
m_rotAxis = m_dragBeginRegularNormal.Cross(pos-m_dragBeginRegularPos);
m_rotAxis = NearestAxis(m_rotAxis);
m_dragDecideMousePos = G_Mouse->GetMousePos();
m_rotAnimAng = 0;
pos = m_dragBeginRegularPos;
AABB bound;
if (abs(m_rotAxis.x) == 1)
{
bound.min = vec3(pos.x-2.0f,pos.y-1000,pos.z-1000);
bound.max = vec3(pos.x+2.0f,pos.y+1000,pos.z+1000);
}
else if (abs(m_rotAxis.y) == 1)
{
bound.min = vec3(pos.x-1000,pos.y-2.0f,pos.z-1000);
bound.max = vec3(pos.x+1000,pos.y+2.0f,pos.z+1000);
}
else
{
bound.min = vec3(pos.x-1000,pos.y-1000,pos.z-2.0f);
bound.max = vec3(pos.x+1000,pos.y+1000,pos.z+2.0f);
}
BackupFrame(bound);
//rotate3D(bound,m_rotAxis);
//m_state = DragRotating;
}
}
else
{
//已经确定旋转方向
vec2 dir = m_dragDecideMousePos - m_dragBeginMousePos;
dir.Normalize();
float dot = (G_Mouse->GetMousePos() - m_dragBeginMousePos).Dot(dir);
m_rotAnimAng = dot/400*HALFPI;
if (m_rotAnimAng>HALFPI)
{
m_rotAnimAng = HALFPI;
}
else if (m_rotAnimAng<-HALFPI)
{
m_rotAnimAng = -HALFPI;
}
//
mat4 mat;
mat.FromAxisAngle(m_rotAxis,m_rotAnimAng);
Frame frame;
vec3 normal = mat*m_dragBeginRegularNormal;
if (abs(normal.x) < abs(normal.y)
&& abs(normal.x)<abs(normal.z))
{
frame.m_matrix.FromToDir(vec3(0,1,0),vec3(0,0,1),normal,vec3(normal.x,-normal.z,normal.y));
}
else if (abs(normal.y) < abs(normal.x)
&& abs(normal.y) < abs(normal.z))
{
frame.m_matrix.FromToDir(vec3(0,1,0),vec3(0,0,1),normal,vec3(-normal.z,normal.y,normal.x));
}
else
{
frame.m_matrix.FromToDir(vec3(0,1,0),vec3(0,0,1),normal,vec3(-normal.y,normal.x,normal.z));
}
frame.m_matrix .SetTranslate(mat*m_dragBeginRegularPos);
m_movieSelect->SetProgramFrame(&frame);
}
}
else
{
//已经确定旋转方向
if (m_dragRotDecided==true )
{
if (abs(m_rotAnimAng)>_PI*0.1f)
{
//确定旋转
m_state = MagicSquarePlayer::AnimRotating;
if (m_rotAnimAng < 0)
{
m_rotAxis *= -1;
m_rotAnimAng *= -1;
}
G_MagicSquareGame->PlaySound__("data/sound/gladiator/punchUnHit.wav");
int axis;
int dir;
int chunk;
if (m_rotAxis.x==1)
{
axis = X;
dir = COUNTERCLOCKWISE;
}
else if (m_rotAxis.x==-1)
{
axis = X;
dir = CLOCKWISE;
}
else if (m_rotAxis.y==1)
{
axis = Y;
dir = COUNTERCLOCKWISE;
}
else if (m_rotAxis.y==-1)
{
axis = Y;
dir = CLOCKWISE;
}
else if (m_rotAxis.z==1)
{
axis = Z;
dir = COUNTERCLOCKWISE;
}
else if (m_rotAxis.z==-1)
{
axis = Z;
dir = CLOCKWISE;
}
if (m_dragBeginRegularPos[axis]<0)
{
chunk = NEGATIVE;
}
else if (m_dragBeginRegularPos[axis]>0)
{
chunk = POSITIVE;
}
else
{
chunk = MIDDLE;
}
RotateFun fun = RotateFunTable[axis][chunk][dir];
(this->*fun)(1);
}
else
{
//取消
m_state = MagicSquarePlayer::None;
RestoreFrame();
}
}
else
{
//取消
m_state = MagicSquarePlayer::None;
}
}
}
}
void MagicSquarePlayerRole::Render()
{
MagicSquarePlayerRobot::Render();
//
G_RendDriver->BlendFunc(Blend_Filter);
//G_RendDriver->SetRenderStateEnable(RS_DEPTH_TEST, true);
G_RendDriver->SetRenderStateEnable(RS_TEXTURE_2D, true);
//show selected color
RectF rc(m_offset.x,m_offset.y+100,BlockSize,BlockSize);
G_RendDriver->DrawTextureRect(rc,m_colorTexRects[m_colorSelected]);
G_RendDriver->Color3f(1,1,1);
char* text="Selected Color";
G_FontMgr->TextAtPos(vec2(rc.x-20,rc.y+rc.height+3),text);
G_RendDriver->EndUI();
}
void MagicSquarePlayerRole::OnLButtonDown(vec2I point)
{
point.x -= m_offset.x;
point.y -= m_offset.y;
FaceDir asp = GetAspect(point);
if(asp != NOASPECT)
{
int index = GetSmallAspectIndex(asp, point);
if(index >= 0)
{
if(index == 4)
{
m_colorSelected = m_blockColors[asp][index];
}
else
{
m_blockColors[asp][index] = m_colorSelected;
}
}
}
}
z