www.gusucode.com > VC++开发的魔方游戏的源程序-源码程序 > VC++开发的魔方游戏的源程序-源码程序\code\Cube.cpp

    // Cube.cpp: implementation of the CCube class.
// Download by http://www.NewXing.com
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MxCubes.h"
#include "Cube.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


///////////////////////////////////////
const int CDirc::UP    = 0x00000001;
const int CDirc::DOWN  = 0x00000010;
const int CDirc::LEFT  = 0x00000100;
const int CDirc::RIGHT = 0x00001000;
const int CDirc::FRONT = 0x00010000;
const int CDirc::BACK  = 0x00100000;
///////////////////////////////////////


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

void CCube::InitCube()
{
	int n, k;
	for(n=0; n<6; n++)
	{
		for(k=0; k<9; k++)
		{
			m_Plane[n].block[k].color = COLOR[n];
			m_Plane[n].block[k].dirc.value  = CDirc::UP;
		}
	}
	m_nStep = 20;
}

CCube::CCube()
{
	COLOR[0] = RGB(255,0,0);
	COLOR[1] = RGB(0,255,0);
	COLOR[2] = RGB(0,0,255);
	COLOR[3] = RGB(255,255,0);
	COLOR[4] = RGB(0,255,255);
	COLOR[5] = RGB(255,0,255);
	InitCube();
}

CCube::~CCube()
{

}

void CCube::ShowCube(CDC *pDC, POINT Vertex0, int SideLength)
{
	// length unit by pixel
	double kkk = 0.7071067812;
	kkk = kkk*kkk;
	CPoint V = Vertex0;
	int blocksl; // block side length
	blocksl = SideLength/3;
	int blockslot; 
	blockslot = blocksl/10;
	if(blockslot<1) blockslot = 1;
	else if(blockslot>10) blockslot = 10;
	CPoint rgnp[4];
	int x,y,t;
	// front plane
	t = blocksl+blockslot-1;
	for(x=0; x<3; x++)
	for(y=0; y<3; y++)
	{
		pDC->FillRect(&CRect(CPoint(V.x+x*t,V.y+y*t),CSize(blocksl-1,blocksl-1)), \
			&CBrush(m_Plane[4].block[x*3+y].color));
	}
	for(y=0; y<3; y++)
	{
		rgnp[0] = CPoint(V.x,V.y+y*t);
		rgnp[1] = CPoint(V.x,rgnp[0].y+blocksl);
		rgnp[2] = CPoint(V.x+3*t,rgnp[1].y);
		rgnp[3] = CPoint(rgnp[2].x,rgnp[0].y);
		m_xClickOgram[y].Open(rgnp);
	}
	// right plane
	V.x = Vertex0.x+3*(blocksl+blockslot-1)+blockslot/2;
	V.y = Vertex0.y-int(blockslot*kkk); 
	t = (blocksl+blockslot-1);
	for(x=0; x<3; x++)
	for(y=0; y<3; y++)
	{
		rgnp[0] = CPoint(V.x+int(x*t*kkk),V.y+y*t-int(x*t*kkk));
		rgnp[1] = rgnp[0]+CSize(0, blocksl-1);
		int tt;
		tt = int((blocksl-1)*kkk);
		rgnp[2] = CPoint(rgnp[0].x+tt,rgnp[1].y-tt);
		rgnp[3] = rgnp[2]+CSize(0, 1-blocksl);
		CRgn rgn;
		rgn.CreatePolygonRgn(rgnp,4,ALTERNATE);
		pDC->FillRgn(&rgn,&CBrush(m_Plane[3].block[x*3+y].color));
	}
	for(x=0; x<3; x++)
	{
		rgnp[0] = V      +CSize(int(x*t*kkk),int(0.05*t)-int(x*blocksl*kkk));
		rgnp[1] = rgnp[0]+CSize(0,int(2.8*t));
		rgnp[2] = rgnp[1]+CSize(int(blocksl*kkk), -int(blocksl*kkk));
		rgnp[3] = rgnp[0]+rgnp[2]-rgnp[1];
		m_xClickOgram[3+x].Open(rgnp);
	}
	// up plane
	V.x = Vertex0.x; 
	V.y = Vertex0.y-blockslot;
	V.y = V.y-int((3*blocksl+2*blockslot-1)*kkk);
	V.x = V.x+int((3*blocksl+2*blockslot-1)*kkk);
	t = (blocksl+blockslot-1);
	for(x=0; x<3; x++)
	for(y=0; y<3; y++)
	{
		int tt,ttt;
		rgnp[0] = CPoint(V.x+x*t-int(y*t*kkk),V.y+int(y*t*kkk));
		ttt = int((blocksl-1)*kkk);
		rgnp[1] = rgnp[0]+CSize(-ttt,ttt);
		tt = int((blocksl-1)*kkk);
		rgnp[2] = CPoint(rgnp[1].x+(blocksl-1),rgnp[1].y);
		rgnp[3] = rgnp[2]+CSize(ttt,-ttt);
		CRgn rgn;
		rgn.CreatePolygonRgn(rgnp,4,ALTERNATE);
		pDC->FillRgn(&rgn,&CBrush(m_Plane[0].block[x*3+y].color));
	}
	for(x=0; x<3; x++)
	{
		rgnp[0] = V      +CSize(int(x*t),0);
		rgnp[1] = rgnp[0]+CSize(-int(3*t*kkk),int(3*t*kkk));
		rgnp[2] = rgnp[1]+CSize(int(blocksl), 0);
		rgnp[3] = rgnp[0]+rgnp[2]-rgnp[1];
		m_xClickOgram[6+x].Open(rgnp);
	}
}

void CCube::RgnClicked(int nRgn)
{
	NextPlane(m_Plane, nRgn);
}

void CParallelogram::Open(CPoint *pv)
{
	xLB = pv[1];
	for(int n=0; n<4; n++)
	{
		vt[n] = pv[n]-xLB;
	}
}

BOOL CParallelogram::PtInOgram(CPoint pt)
{
	pt = pt-xLB;
	if(pt.x<0 || pt.x>vt[3].x || pt.y>0 || pt.y<vt[3].y) return FALSE;
	int type = 0;
	if(vt[0].x == vt[1].x && vt[0].y == vt[3].y) type = 0;
	else if(vt[0].x == vt[1].x) type = 1;
	else type = 2;
	switch(type)
	{
	case 0:
		return TRUE;
	case 1:
		if(pt.y>-pt.x+vt[0].y && pt.y<-pt.x) return TRUE;
		break;
	case 2:
		if(pt.x>-pt.y && pt.x<-pt.y+vt[2].x) return TRUE;
		break;
	}
	return FALSE;
}

int CCube::Rotate(int n)
{
	int y = -1;
	if(n<0 || n>8) return -1;
	switch(n)
	{
	case 0:
		y = 6;
		break;
	case 1:
		y = 3;
		break;
	case 2:
		y = 0;
		break;
	case 3:
		y = 7;
		break;
	case 4:
		y = 4;
		break;
	case 5:
		y = 1;
		break;
	case 6:
		y = 8;
		break;
	case 7:
		y = 5;
		break;
	case 8:
		y = 2;
		break;
	}
	return y;
}

int CCube::Rot(int n, int time)
{
	if(time<0) return -1;
	time = time%4;
	while(time--)
	{
		n = Rotate(n);
	}
	return n;
}

void CCube::Turnto(int nDirc)
{
//	if(nDirc<0 || nDirc>3) return;
	int n,k;
	// 0~3: left right up down	switch(nDirc)
	switch(nDirc)
	{
	case 0:
		for(n=0; n<3; n++)
		{
			for(k=0; k<3; k++)
			{
				RgnClicked(n);
			}
		}
		break;
	case 1:
		for(n=0; n<3; n++)
		{
			RgnClicked(n);
		}
		break;
	case 2:
		for(n=6; n<9; n++)
		{
			for(k=0; k<3; k++)
			{
				RgnClicked(n);
			}
		}
		break;
	case 3:
		for(n=6; n<9; n++)
		{
			RgnClicked(n);
		}
		break;
	}
}

void CCube::Randomize(int nStep)
{
	CTime now;
	if(nStep<1 || nStep>100) return;
//	m_nStep = nStep;
	InitCube();
	now = CTime::GetCurrentTime();
	int n = now.GetYear()*10000+now.GetDay()*100+now.GetSecond();
	int t,m,k;
	srand(n);
	int STEP;
	STEP = rand();
	if(STEP<0) STEP = -STEP;
	STEP = STEP%nStep+1;
	for(n=0; n<STEP; n++)
	{
		t = rand();
		if(t<0) t = -t;
		t = t%4;
		m = rand();
		if(m<0) m = -m;
		m = m%9;
		for(k=0; k<3/*t*/; k++)
		{
			RgnClicked(m);
		}
	}
	char msg[100];
	sprintf(msg, "实际打乱的步长是%d", STEP);
	m_nStep = STEP;
	AfxMessageBox(msg);
}

BOOL CCube::IsOK()
{
	return IsOK(m_Plane);
}

BOOL CCube::Restore(int* pnPath, int& nStepCnt)
{
	nStepCnt = 0;
	return Find(m_Plane,pnPath,nStepCnt);
}

BOOL CCube::Find(CPlane *plane, int *pnPath, int& nStepCnt)
{
	CPlane tp[6];
	if(nStepCnt>=m_nStep) return FALSE;
	int n,k;
	for(n=0; n<9; n++)
	{
		for(k=0; k<6; k++)
		{
			tp[k] = plane[k];
		}
		NextPlane(tp, n);
		pnPath[nStepCnt++] = n;
		if(IsOK(tp)) return TRUE;
		if(Find(tp, pnPath, nStepCnt)) return TRUE;
		nStepCnt--;
	}
	return FALSE;
}

void CCube::NextPlane(CPlane *plane, int nRgn)
{
	CBlock xt;
	int n;
	switch(nRgn)
	{
	case 0:
	case 1:
	case 2: // 4 2 5 3
		nRgn = nRgn%3;
		for(n=nRgn; n<9; n+=3)
		{
			xt = plane[4].block[n];
			plane[4].block[n] = plane[2].block[n];
			plane[2].block[n] = plane[5].block[n];
			plane[5].block[n] = plane[3].block[n];
			plane[3].block[n] = xt;
		}
		break;
	case 3:
	case 4:
	case 5: // 3 0 2 1
		nRgn = nRgn%3;
		for(n=3*nRgn; n<3*nRgn+3; n+=1)
		{
			xt = plane[3].block[n];
			plane[3].block[n] = plane[0].block[Rot(n,3)];
			plane[0].block[Rot(n,3)] = plane[2].block[Rot(n,2)];
			plane[2].block[Rot(n,2)] = plane[1].block[Rot(n,1)];
			plane[1].block[Rot(n,1)] = xt;
		}
		break;
	case 6:
	case 7:
	case 8: // 0 5 1 4
		nRgn = nRgn%3;
		for(n=3*nRgn; n<3*nRgn+3; n+=1)
		{
			xt = plane[0].block[n];
			plane[0].block[n] = plane[5].block[Rot(n,2)];
			plane[5].block[Rot(n,2)] = plane[1].block[Rot(n,2)];
			plane[1].block[Rot(n,2)] = plane[4].block[Rot(n,0)];
			plane[4].block[Rot(n,0)] = xt;
		}
		break;
	default:
		return;
	}
}

BOOL CCube::IsOK(CPlane *plane)
{
	int n, k;
	COLORREF cl;
	for(n=0; n<6; n++)
	{
		cl = plane[n].block[0].color;
		for(k=1; k<9; k++)
		{
			if(plane[n].block[k].color != cl)
				return FALSE;
//			plane[n].block[k].dirc.value  = CDirc::UP;
		}
	}
	return TRUE;
}