带自动还原魔方游戏源码

这是一个带自动还原算法的魔方小游戏,标准的七步还原法。适合初学者,可以一步步执行,也可以输入公式执行。魔方的每个小面上附加了一些装饰模型,直接在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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值