0
点赞
收藏
分享

微信扫一扫

任意阶拼图游戏及自动求解算法

程序猿不脱发2 2022-04-13 阅读 27
游戏算法

10号,不太舒服有点头疼。千万别感冒,补点水饺。

这是《最强大脑》里出现过的一个拼图游戏。这个游戏的自动拼图算法是一个N数码问题。原始图片被切割成n x n个小块,游戏可能出现的总状态数为 n平方的阶乘。

即使最简单的n=3,3阶分割也有(3*3)! = 362880个状态。4阶分割时,拼图状态数飙升到(4*4)! = 20922789888000。那么100阶分割呢,(100*100)! 绝对的天文数字。如何来实现任意阶的拼图算法呢?

 方案一:
我们很容易想到的方法,按打乱的顺序逆序还原,有点作弊之嫌。

方案二:
A*算法剪枝, 避免电脑出现一万年也算不完任务的情况。当阶数n足够大的时候效率仍然是堪忧的。

方案三:
本游戏采用的算法,模拟人脑的思路。100*100阶的拼图也能很快求解,而且可以分步执行,即一次只计算一步,很适合游戏ai。 此方法也有一个缺点,不是最优解,求解出来的步数有点长。

 算法:先将色块和空格移动到目标位置附近,然后执行相应的公式化步骤。

具体直接看源码吧

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Pintu/MiniGamePintu.h
//  @Brief:     MiniGamePintu
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================
 

#ifndef  __MiniGamePintu__H__
#define  __MiniGamePintu__H__

#include "Rpg/MiniGame.h"

//拼图1 空格移动
class MiniGameSlidingBlock:public MiniGame
{
public:
	struct Cell
	{
		int texID;
		int x,y;
	};
	struct CellMesh
	{
		vec3 vVertex[8];
		vec2 tVertex[8];
	};
	MiniGameSlidingBlock();
	virtual~MiniGameSlidingBlock();
	virtual bool Start();
	virtual bool Stop();
	virtual bool Render();
	virtual void RenderUI();
	virtual bool Update();
	virtual bool Free();
	virtual void OnSize();
	virtual bool KeepResource(bool once,int& circle,String& nextTip);

	//三种类型结构
	virtual MiniPlayer*  CreatePlayer();
	virtual MiniPlayer*  CreateRobot ();
	virtual MiniPlayer*  CreateRole  ();

	void  UpdateGameRect();
	bool  IsEnd();
	void  MoveEmpty(int key);
	bool  IsCellOK(int x,int y);
	bool  IsCellEmpty(int x,int y);
	Cell* GetCell(int texID);

	bool  AIMoveSrcUp(int srcX,int srcY,int tarX,int tarY,int empX,int empY);
	bool  AIMoveSrcDown(int srcX,int srcY,int tarX,int tarY,int empX,int empY);
	bool  AIMoveSrcLeft(int srcX,int srcY,int tarX,int tarY,int empX,int empY);
	bool  AIMoveSrcRight(int srcX,int srcY,int tarX,int tarY,int empX,int empY);

//protected:
	float m_accumeTime;
	TexturePtr  m_texBack;
	TexturePtr  m_texPic;
	TexturePtr  m_texFrame;
	TexturePtr  m_texFrame2;
	TexturePtr  m_texCloud;

	int         m_Level;

	RectF       m_gameRect;
	RectF       m_rectLevel;
	vec2I       m_cellNum;
	int         m_cellNumXY;
	vec2I       m_cellExtend;
		  
	Cell*       m_emptyCell;
	Cell*       m_cells;
	CellMesh*   m_cellMeshs;
		  
	Cell        m_movingCell;
	vec2        m_movingDir;
	float       m_movingTime;
		  
	bool        m_workingWithAI;
	Cell*       m_aiSrcCell;
	int         m_aiCompleteSize;
		  
	int         m_stepNum;
		  
	int         m_aiTryNum;
	int         m_aiTrys[64];

	//box 索引
	int         CellIndex[30];
};

extern MiniGameSlidingBlock* G_SlideBlockGame;

#endif
//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Pintu/MiniGamePintu.cpp
//  @Brief:     MiniGamePintu
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================

#include "General/Pch.h"
#include "General/General.h"
#include "General/StringUtil.h"
#include "General/Timer.h"
#include "General/Window.h"
#include "Gui/GuiMgr.h"
#include "Gui/RpgGuis.h"
#include "Gui/GuiControlMisc.h"
#include "Input/InputMgr.h"
#include "MiniGameSlidingBlock.h"
#include "Render/Camera.h"
#include "Render/Font.h"
#include "Render/RendDriver.h"
#include "Render/Terrain.h"
#include "Render/MC_MovieClip.h"
#include "Render/Shader.h"
#include "Sound/SoundManager.h"
#include "General/List.cpp"
#include "General/Pce.h"

//static float MovingTime = 0.001f;
static float MovingTime = 0.08f;
static float GameRectWidth2D    = 460; 
static float GameRectWidth3D    = 66; 

MiniGameSlidingBlock* G_SlideBlockGame;

MiniGameSlidingBlock::MiniGameSlidingBlock()
:m_cells(NULL)
{
    G_SlideBlockGame = this;
	//m_Level = 0;
	m_Level = 4;
	//box 索引
	/*
	  0  1
	  2  3
	  4  5
	  6  7
	*/
	int indexs[30] = 
	{
		0,2,1,
		1,2,3,
		3,2,6,
		3,6,7,
		1,3,7,
		1,7,5,
		0,1,5,
		0,5,4,
		2,0,4,
		2,4,6
	};
	memcpy(CellIndex,indexs,sizeof(CellIndex));
}
MiniGameSlidingBlock::~MiniGameSlidingBlock()
{
    Free();
	G_SlideBlockGame = NULL;
}
bool MiniGameSlidingBlock::Start()
{
	//m_myRolePlayer = NULL;
    if(!MiniGame::Start())
        return false;

	m_gameState = MS_Gamming;
    m_accumeTime = 0;
	
    //进入miniplaygui,(选人、选关卡都已在房间里进行完毕)。
    if(GetStyle()) G_GuiMgr->PushGui(GetStyle()->playGUI.c_str(),GL_DIALOG);
	G_TextureMgr->AddTexture(m_texBack,    "data/minigame/Pintu/backframe.png");
	G_TextureMgr->AddTexture(m_texPic,     "data/minigame/Pintu/pic1.png");
	G_TextureMgr->AddTexture(m_texFrame,    "data/minigame/Pintu/frame.png");
	G_TextureMgr->AddTexture(m_texFrame2,   "data/minigame/Pintu/frame2.png");
	//G_TextureMgr->AddTexture(m_texCloud,    "data/environment/clouds/cloud2.png");
	G_TextureMgr->AddTexture(m_texCloud,    "data/environment/clouds/cloud_1.png");


	//
	if (m_movieScene == NULL)
	{
		LoadConfig loader(LoadConfig::GenDonotReShrinkBound, true, true);
		m_movieScene = new RendSys::MovieClip;
		m_movieScene->LoadFromFile("data/minigame/pintu/board.movie", &loader);

		Frame frame;
		frame.SetPos(m_startPos);
		m_movieScene->SetProgramFrame(&frame);
		m_movieScene->Advance();
	}

	if (m_movieScene->IsLoadComplete() == false)
	{
		m_gameState = MS_End;
		return false;
	}

	m_movieScene->GetMovieClip("preview")->ReAttachTexture(m_texPic);


	//m_cellNum.x = 6;
	//m_cellNum.y = 7;

	m_cellNum.x = 2+m_Level;
	m_cellNum.y = 2+m_Level;
	m_cellNumXY = m_cellNum.x*m_cellNum.y;

	UpdateGameRect();

	m_workingWithAI=FALSE;
	m_aiSrcCell = NULL;
	m_aiTryNum = 0;
	m_aiCompleteSize = -1;
	m_stepNum = 0;

	m_movingTime = 0;
	m_movingCell.texID = -1;


	//
	m_cells = new Cell[m_cellNumXY];
	for(int i=0;i<m_cellNumXY;i++)
	{
		m_cells[i].texID =i;
		m_cells[i].x =i%m_cellNum.x;
		m_cells[i].y =i/m_cellNum.x;
	}
	m_emptyCell = &m_cells[m_cellNumXY - 1];
	m_emptyCell->texID = -1;

	//
	int num = 0;
	for(int i=1;i<200;i++)
	{
		int ran1=Rand()%(m_cellNumXY-1);//empty不交换
		int ran2=Rand()%(m_cellNumXY-1);
		if(ran1!=ran2)
		{
			num++;
			Swap(m_cells[ran1].texID,m_cells[ran2].texID);
		}
	}
	if (num%2==1)
	{
		//必须交换偶数次
		Swap(m_cells[0].texID,m_cells[1].texID);
	}

	//
	/*
	  0  1
	  2  3
	  4  5
	  6  7
	*/
	m_cellMeshs = new CellMesh[m_cellNumXY];
	TerrainData terrain;
	//terrain.New(48,48,GameRectWidth3D/48,GameRectWidth3D/48);
	terrain.New(17,17,GameRectWidth3D/16,GameRectWidth3D/16);
	terrain.FillFractSurface(0,0,10,0.5f,false,0);
	Cell* cell;
	CellMesh* mesh;
	vec2 cellExtend3D;
	cellExtend3D.x = GameRectWidth3D/m_cellNum.x;
	cellExtend3D.y = GameRectWidth3D/m_cellNum.y;
	for(int i=0;i<m_cellNumXY;i++)
	{
		cell = &m_cells[i];
		float X0 = 0;
		float X1 = cellExtend3D.x;
		float Z0 = 0;
		float Z1 = cellExtend3D.y;
		float Y0 = 0;
		mesh = &m_cellMeshs[i];
		mesh->vVertex[0].x = X0;
		mesh->vVertex[0].y = terrain.GetHeight(cell->x,cell->y);
		mesh->vVertex[0].z = Z0;
		mesh->vVertex[4].x = X0;
		mesh->vVertex[4].y = Y0;
		mesh->vVertex[4].z = Z0;

		mesh->vVertex[1].x = X1;
		mesh->vVertex[1].y = terrain.GetHeight(cell->x+1,cell->y);
		mesh->vVertex[1].z = Z0;
		mesh->vVertex[5].x = X1;
		mesh->vVertex[5].y = Y0;
		mesh->vVertex[5].z = Z0;

		mesh->vVertex[2].x = X0;
		mesh->vVertex[2].y = terrain.GetHeight(cell->x,cell->y+1);
		mesh->vVertex[2].z = Z1;
		mesh->vVertex[6].x = X0;
		mesh->vVertex[6].y = Y0;
		mesh->vVertex[6].z = Z1;

		mesh->vVertex[3].x = X1;
		mesh->vVertex[3].y = terrain.GetHeight(cell->x+1,cell->y+1);
		mesh->vVertex[3].z = Z1;
		mesh->vVertex[7].x = X1;
		mesh->vVertex[7].y = Y0;
		mesh->vVertex[7].z = Z1;

		float TX0 = float(cell->x)/m_cellNum.x;
		float TX1 = float(cell->x+1)/m_cellNum.x;
		float TZ0 = float(cell->y)/m_cellNum.y;
		float TZ1 = float(cell->y+1)/m_cellNum.y;
		mesh->tVertex[0].x = TX0;
		mesh->tVertex[0].y = TZ0;
		mesh->tVertex[4].x = TX0;
		mesh->tVertex[4].y = TZ0;

		mesh->tVertex[1].x = TX1;
		mesh->tVertex[1].y = TZ0;
		mesh->tVertex[5].x = TX1;
		mesh->tVertex[5].y = TZ0;

		mesh->tVertex[2].x = TX0;
		mesh->tVertex[2].y = TZ1;
		mesh->tVertex[6].x = TX0;
		mesh->tVertex[6].y = TZ1;

		mesh->tVertex[3].x = TX1;
		mesh->tVertex[3].y = TZ1;
		mesh->tVertex[7].x = TX1;
		mesh->tVertex[7].y = TZ1;
	}
	//
	for(int i = 0; i < m_allPlayerNum; i++)
	{
		if(m_miniPlayer[i])
			m_miniPlayer[i]->Start();
	}

	//设置摄像机
	CameraCtrlerTarget* ctrler = new CameraCtrlerTarget;
	ctrler->SetDistToTar(60);
	ctrler->SetTarPos(m_startPos);
	G_Camera->PushCtrler(ctrler);	
	G_Camera->SetEuler(0, -60, 0);
	//片头摄像机
	PushIntroCamera();

    return true;
}

MiniPlayer* MiniGameSlidingBlock::CreatePlayer()
{
	return new MiniPlayer;
}

MiniPlayer* MiniGameSlidingBlock::CreateRobot()
{
	return new MiniPlayer;
}

MiniPlayer* MiniGameSlidingBlock::CreateRole()
{
	return new MiniPlayer;
}

bool MiniGameSlidingBlock::Stop()
{
//	char buf[256];
    G_GuiMgr->PopGui("MiPintu_PlayGui");
	
	{
		if (m_myPlayer && m_myPlayer->m_liveNum>0)
		{
			G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(true);
		}
		else
		{
			G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(false);
		}
		G_GuiMgr->PushGui("Rpg_ResultDialog",GL_DIALOGBOTTOM);
	}
    MiniGame::Stop();
    return true;
}

bool MiniGameSlidingBlock::Render()
{
	if (m_3dMode)
	{
		G_RendDriver->EndUI();
		if(m_movieScene==NULL
			||m_movieScene->IsLoadComplete()==false)
			return false;

		G_RendDriver->SetRenderStateEnable(RS_DEPTH_TEST,true);
		m_movieScene->RendClip();

		画等级
		//m_rectLevel = RectF(BoardRect2D.x+623, BoardRect2D.y+24, 39, 23);
		//if(m_rectLevel.IsPointIn(G_Mouse->GetMousePos()))
		//{
		//	G_RendDriver->Color4f(1, 1, 0, 1);
		//}
		//else
		//{
		//	G_RendDriver->Color4f(1, 0, 0, 1);
		//}
		//m_texLcdNumber->Bind();
		//DrawLcd(3,m_Level+1, m_rectLevel);
		//G_RendDriver->Color4f(1, 1, 1, 1);

		画时间和得分
		//m_texLcdNumber->Bind();
		//G_RendDriver->Color4f(1, 0, 0, 1);
		//DrawLcd(3,m_gameTime, RectF(BoardRect2D.x +613, BoardRect2D.y+213, 39, 23));
		DrawLcd(3,m_life, RectF(m_uiOffset.x+623, m_uiOffset.y +52, 39, 23));
		//DrawLcd(4,m_stepNum, RectF(BoardRect2D.x+623, BoardRect2D.y +79, 52, 23));



		//
		G_RendDriver->Color4f(1.0f, 1.0f, 1.0f, 1.0f);
		G_RendDriver->SetRenderStateEnable(RS_TEXTURE_2D,true);
		m_texPic->Bind();
		//cell
		Cell* cell;
		CellMesh* mesh;
		for(int i = 0;i<m_cellNumXY;i++)
		{
			cell = &m_cells[i];
			if (cell->texID!=-1
				&&cell->texID!=m_movingCell.texID)
			{
				mesh = &m_cellMeshs[cell->texID];

				G_RendDriver->PushMatrix();
				G_RendDriver->Translatef(m_gameRect.x+cell->x *m_cellExtend.x,
					                     m_startPos.y+9,
										 m_gameRect.y+cell->y *m_cellExtend.y);
				G_RendDriver->RendTrigon(10,mesh->vVertex,mesh->tVertex,NULL,NULL,CellIndex,8);
				G_RendDriver->PopMatrix();
				


				//G_RendDriver->Color4f(0.0f, 0.0f, 0.0f, 0.5f);
				//G_RendDriver->DrawRect(RectF(dst.x+3,dst.y+3,20,20));
				//G_FontMgr->SetColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
				//sprintf(buf,"%d",cell->texID);
				//G_FontMgr->TextAtPos(dst,buf);
			}
		}

		//moving
		if (m_movingCell.texID!=-1)
		{
			vec2 pos;
			pos.x = m_movingCell.x *m_cellExtend.x;
			pos.y = m_movingCell.y *m_cellExtend.y;
			pos += m_movingDir*vec2(m_cellExtend.x,m_cellExtend.y)*(1-m_movingTime/MovingTime);
	
			mesh = &m_cellMeshs[m_movingCell.texID];

			G_RendDriver->PushMatrix();
			G_RendDriver->Translatef(m_gameRect.x+pos.x,
				m_startPos.y+9,
				m_gameRect.y+pos.y);
			G_RendDriver->RendTrigon(10,mesh->vVertex,mesh->tVertex,NULL,NULL,CellIndex,8);
			G_RendDriver->PopMatrix();

		//	G_RendDriver->Color4f(0.0f, 0.0f, 0.0f, 0.5f);
		//	G_RendDriver->DrawRect(RectF(dst.x+3,dst.y+3,20,20));
		//	sprintf(buf,"%d",m_movingCell.texID);
		//	G_FontMgr->SetColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
		//	G_FontMgr->TextAtPos(dst,buf);
		}

	}
	else
	{
		//G_RendDriver->ClearClipRect();
		G_RendDriver->BeginUI();

		//frame
		G_RendDriver->Color4f(1.0f, 1.0f, 1.0f, 1.0f);
		m_texBack->Bind();
		G_RendDriver->DrawTextureRect(BoardRect2D, RectF(0, 0, 1, 1));

		//
		G_RendDriver->PushMatrix();
		G_RendDriver->Translatef(m_gameRect.x,-m_gameRect.y,0);

		vec2 dst;
		//cell
		char buf[128];
		vec2I tex;
	
		//纹理排序后速度微小增加 
		//picture
		Cell* cell = m_cells;
		m_texPic->Bind();
		G_RendDriver->Color4f(1.0f, 1.0f, 1.0f, 1.0f);
		if (G_ShaderMgr&& G_ShaderMgr->m_curEffect)
		{
			G_ShaderMgr->MapChangeParm();
		}
		for(int i = 0;i<m_cellNumXY;i++,cell++)
		{
			if (cell->texID!=-1
				&&cell->texID!=m_movingCell.texID)
			{
				tex.x = cell->texID%m_cellNum.x;
				tex.y = cell->texID/m_cellNum.x;
				dst.x = cell->x *m_cellExtend.x;
				dst.y = cell->y *m_cellExtend.y;
				G_RendDriver->DrawTextureRect(RectF(dst.x,dst.y,m_cellExtend.x,m_cellExtend.y),
					RectF(float(tex.x)/m_cellNum.x,float(tex.y)/m_cellNum.y,1.0f/m_cellNum.x,1.0f/m_cellNum.y));
			}
		}

		//cloud
		cell = m_cells;
		m_texCloud->Bind();
		for(int i = 0;i<m_cellNumXY;i++,cell++)
		{
			if (cell->texID!=-1
				&&cell->texID!=m_movingCell.texID)
			{
				tex.x = cell->texID%m_cellNum.x;
				tex.y = cell->texID/m_cellNum.x;
				dst.x = cell->x *m_cellExtend.x;
				dst.y = cell->y *m_cellExtend.y;
				//
				G_RendDriver->DrawTextureRect(RectF(dst.x,dst.y,m_cellExtend.x,m_cellExtend.y),
					RectF(float(tex.x)/m_cellNum.x+m_gameTime*0.1f,float(tex.y)/m_cellNum.y,1.0f/m_cellNum.x,1.0f/m_cellNum.y));
			}
		}

		//frame
		cell = m_cells;
		m_texFrame->Bind();
		for(int i = 0;i<m_cellNumXY;i++,cell++)
		{
			if (cell->texID!=-1
				&&cell->texID!=m_movingCell.texID)
			{
				tex.x = cell->texID%m_cellNum.x;
				tex.y = cell->texID/m_cellNum.x;
				dst.x = cell->x *m_cellExtend.x;
				dst.y = cell->y *m_cellExtend.y;

				int t = 0;
				if (m_workingWithAI && cell==m_aiSrcCell)
				{
					t = 1;
					G_RendDriver->DrawTextureRect(RectF(dst.x,dst.y,m_cellExtend.x,m_cellExtend.y),RectF(t/10.0f,0,1/10.0f,1));
				}
				else
				{
					if (IsCellOK(cell->x,cell->y))
					{
						RectF frameRect(dst.x-2,dst.y-2,m_cellExtend.x+4,m_cellExtend.y+4);
						if (IsCellOK(cell->x-1,cell->y)==false)
						{
							t = 2;
							G_RendDriver->DrawTextureRect(frameRect,RectF(t/10.0f,0,1/10.0f,1));
						}
						if (IsCellOK(cell->x+1,cell->y)==false)
						{
							t = 3;
							G_RendDriver->DrawTextureRect(frameRect,RectF(t/10.0f,0,1/10.0f,1));
						}
						if (IsCellOK(cell->x,cell->y-1)==false)
						{
							t = 4;
							G_RendDriver->DrawTextureRect(frameRect,RectF(t/10.0f,0,1/10.0f,1));
						}
						if (IsCellOK(cell->x,cell->y+1)==false)
						{
							t = 5;
							G_RendDriver->DrawTextureRect(frameRect,RectF(t/10.0f,0,1/10.0f,1));
						}
					}
					else
					{
						if (IsCellOK(cell->x,cell->y+1)==false)
						{
							t = 0;
							G_RendDriver->DrawTextureRect(RectF(dst.x,dst.y,m_cellExtend.x,m_cellExtend.y),RectF(t/10.0f,0,1/10.0f,1));
						}
					}
				}
			}
		}
		//text
		cell = m_cells;
		m_texLcdNumber->Bind();
		for(int i = 0;i<m_cellNumXY;i++,cell++)
		{
			if (cell->texID!=-1
				&&cell->texID!=m_movingCell.texID)
			{
				tex.x = cell->texID%m_cellNum.x;
				tex.y = cell->texID/m_cellNum.x;
				dst.x = cell->x *m_cellExtend.x;
				dst.y = cell->y *m_cellExtend.y;

				DrawLcd(3,cell->texID, RectF(dst.x+3,dst.y+3,20,10));

				//slow
				//G_RendDriver->Color4f(0.0f, 0.0f, 0.0f, 0.5f);
				//G_RendDriver->DrawRect(RectF(dst.x+3,dst.y+3,20,20));
				//G_FontMgr->SetColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
				//sprintf(buf,"%d",cell->texID);
				//G_FontMgr->TextAtPos(dst,buf);
			}
		}

		//moving
		if (m_movingCell.texID!=-1)
		{
			tex.x = m_movingCell.texID%m_cellNum.x;
			tex.y = m_movingCell.texID/m_cellNum.x;
			dst.x = m_movingCell.x *m_cellExtend.x;
			dst.y = m_movingCell.y *m_cellExtend.y;
			dst += m_movingDir*vec2(m_cellExtend.x,m_cellExtend.y)*(1-m_movingTime/MovingTime);
			G_RendDriver->Color4f(1.0f, 1.0f, 1.0f, 1.0f);
			m_texPic->Bind();
			G_RendDriver->DrawTextureRect(RectF(dst.x,dst.y,m_cellExtend.x,m_cellExtend.y),
				RectF(float(tex.x)/m_cellNum.x,float(tex.y)/m_cellNum.y,1.0f/m_cellNum.x,1.0f/m_cellNum.y));

			m_texFrame->Bind();
			if (IsCellOK(m_movingCell.x,m_movingCell.y))
			{
				Cell* cell = &m_movingCell;
				RectF frameRect(dst.x-2,dst.y-2,m_cellExtend.x+4,m_cellExtend.y+4);
				int t = 0;
				if (IsCellOK(cell->x-1,cell->y)==false)
				{
					t = 2;
					G_RendDriver->DrawTextureRect(frameRect,RectF(t/10.0f,0,1/10.0f,1));
				}
				if (IsCellOK(cell->x+1,cell->y)==false)
				{
					t = 3;
					G_RendDriver->DrawTextureRect(frameRect,RectF(t/10.0f,0,1/10.0f,1));
				}
				if (IsCellOK(cell->x,cell->y-1)==false)
				{
					t = 4;
					G_RendDriver->DrawTextureRect(frameRect,RectF(t/10.0f,0,1/10.0f,1));
				}
				if (IsCellOK(cell->x,cell->y+1)==false)
				{
					t = 5;
					G_RendDriver->DrawTextureRect(frameRect,RectF(t/10.0f,0,1/10.0f,1));
				}
			}
			else
			{
				int t = 0;
				if (m_workingWithAI && m_aiSrcCell && m_movingCell.texID==m_aiSrcCell->texID)
					t = 1;
				G_RendDriver->DrawTextureRect(RectF(dst.x,dst.y,m_cellExtend.x,m_cellExtend.y),RectF(t/10.0f,0,1/10.0f,1));
			}

			G_RendDriver->Color4f(0.0f, 0.0f, 0.0f, 0.5f);
			G_RendDriver->DrawRect(RectF(dst.x+3,dst.y+3,20,20));
			sprintf(buf,"%d",m_movingCell.texID);
			G_FontMgr->SetColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
			G_FontMgr->TextAtPos(dst,buf);
		}

		G_RendDriver->PopMatrix();

		//preview
		G_RendDriver->Color4f(1.0f, 1.0f, 1.0f, 1.0f);
		RectF previewRect(BoardRect2D.x+517,BoardRect2D.y+306,175,175.0f/m_texPic->GetWidth()*m_texPic->GetHeight());
		m_texPic->Bind();
		G_RendDriver->DrawTextureRect(previewRect, RectF(0, 0, 1, 1));
	}


	//
	if (m_3dMode)
	{
		G_RendDriver->PushMatrix();
		G_RendDriver->MultMatrix(mat2Dto3D);
	}
	//画等级
	m_rectLevel = RectF(BoardRect2D.x+633, BoardRect2D.y+36, 39, 23);
	if(m_rectLevel.IsPointIn(G_Mouse->GetMousePos()))
	{
		G_RendDriver->Color4f(1, 1, 0, 1);
	}
	else
	{
		G_RendDriver->Color4f(1, 0, 0, 1);
	}
	m_texLcdNumber->Bind();
	DrawLcd(3,m_Level+1, m_rectLevel);
	G_RendDriver->Color4f(1, 1, 1, 1);

	//画时间和得分
	m_texLcdNumber->Bind();
	G_RendDriver->Color4f(1, 0, 0, 1);
	DrawLcd(3,m_gameTime, RectF(BoardRect2D.x +623, BoardRect2D.y+223, 39, 23));
	DrawLcd(4,m_stepNum, RectF(BoardRect2D.x+633, BoardRect2D.y +89, 52, 23));
	if (m_3dMode)
	{
		G_RendDriver->PopMatrix();
	}

    return true;
}

void MiniGameSlidingBlock::RenderUI()
{
	Render();
	G_RendDriver->BeginUI();
}

void MiniGameSlidingBlock::UpdateGameRect()
{
	float width__  = m_texBack->GetWidth(); 
	float height_  = m_texBack->GetHeight(); 
	SetBoardRect(RectF((G_Window->m_iWidth-width__)/2,(G_Window->m_iHeight-height_)/2,width__,height_), 
		RectF(m_startPos.x-50,m_startPos.z-33,100,66),
		m_startPos.y+10.1f);


	if (m_3dMode)
	{
		m_gameRect = RectF(m_startPos.x-38, m_startPos.z-GameRectWidth3D/2, GameRectWidth3D,GameRectWidth3D);
	}
	else
	{
		m_gameRect = RectF(BoardRect2D.x + 26, BoardRect2D.y + 22, GameRectWidth2D,GameRectWidth2D);
	}

	m_cellExtend.x = m_gameRect.width/m_cellNum.x;
	m_cellExtend.y = m_gameRect.height/m_cellNum.y;

	//取整
	if (m_3dMode==false)
	{
		m_gameRect.width  = m_cellExtend.x*m_cellNum.x;
		m_gameRect.height = m_cellExtend.y*m_cellNum.y;
	}
}

bool MiniGameSlidingBlock::Update()
{
    MiniGame::Update();
	m_movieScene->Advance();
	UpdateGameRect();

	if (m_movingCell.texID!=-1)
	{
		m_movingTime += G_Timer->GetStepTimeLimited();
		if (m_movingTime>MovingTime)
		{
			m_movingTime = MovingTime;
		}
	}

	if (G_SlideBlockGame->IsButtonDowning(MOUSE_LEFT))
	{
		int click = 0;
		if (m_3dMode)
		{
			vec3 dir;
			vec3 start;
			G_Camera->GetMouseTray(start,dir);
			RayMovieCollideRes res;
			res.vStart = start;
			res.vEnd = start+PICKLEN*dir;
			res.justBond = false;
			if(m_movieScene->GetMovieClip("board")->IntersectTray(res))
			{
				vec2 point(res.resPos.x- m_gameRect.x,res.resPos.z- m_gameRect.y);
				click = int(point.x/m_cellExtend.x) + int(point.y/m_cellExtend.y)*m_cellNum.x;
			}


		}
		else
		{
			vec2 point = G_Mouse->GetMousePos()-m_gameRect.GetPos();
			click = int(point.x/m_cellExtend.x) + int(point.y/m_cellExtend.y)*m_cellNum.x;
		}
		int empty = (m_emptyCell->x) + (m_emptyCell->y)*m_cellNum.x;
		if(click - empty == 1)
		{
			MoveEmpty(DIK_RIGHT);
		}
		else if(click - empty == -1)
		{
			MoveEmpty(DIK_LEFT);
		}
		else if(click - empty == m_cellNum.x)
		{
			MoveEmpty(DIK_DOWN);
		}
		else if(click - empty == -m_cellNum.x)
		{
			MoveEmpty(DIK_UP);
		}
		else
		{
			PlaySound__("data/sound/poker/cannot.wav");
		}

		if(m_rectLevel.IsPointIn(G_Mouse->GetMousePos()))
		{
			//重新开始
			m_Level++;
			m_Level%=10;
			//Start();
		}

	}


	if (G_SlideBlockGame->IsKeyDowning(KeyLeft))
	{
		MoveEmpty(DIK_LEFT);
	}
	else if (G_SlideBlockGame->IsKeyDowning(KeyRight))
	{
		MoveEmpty(DIK_RIGHT);
	}	
	else if (G_SlideBlockGame->IsKeyDowning(KeyUp))
	{
		MoveEmpty(DIK_UP);
	}	
	else if (G_SlideBlockGame->IsKeyDowning(KeyDown))
	{
		MoveEmpty(DIK_DOWN);
	}


	//算法优化:毗邻后可以不断的移位大循环圈 而不是小循环圈, 这样可以在大循环圈内构造长的正确序列一起移位 正确序列越长加速效果越好

	if (m_workingWithAI
		&&IsEnd()==false
		&&(m_movingCell.texID==-1||m_movingTime>=MovingTime)
		)
	{
		if (m_aiTryNum)
		{
			m_aiTryNum--;
			MoveEmpty(m_aiTrys[m_aiTryNum]);
		}
		else
		{
			//将块srcTexID挪动到tarX,tarY
			int empX = m_emptyCell->x;
			int empY = m_emptyCell->y;

			//最后两排两列
			if (m_aiCompleteSize>=m_cellNum.x-2-1
				&&m_aiCompleteSize>=m_cellNum.y-2-1)
			{
				//找要匹配的色块
				m_aiSrcCell = NULL;
				int srcTexID = -1;
				int aiCompleteSizeX = -1;
				//底面两排
				for(int size = 0;size<m_cellNum.x-2;size++)
				{
					if(IsCellOK(size,m_cellNum.y-2)
						&&IsCellOK(size,m_cellNum.y-1)
						)
					{
						aiCompleteSizeX = size;
						continue;
					}
					int index1 = (m_cellNum.y-2)*m_cellNum.x+size;
					int index2 = index1 + m_cellNum.x;

					//正好颠倒,特殊处理避免死循环
					/*
					|index2 |any   |
					|index1 |empty |
					*/
					if(m_cells[index2].texID==index1
						&&m_cells[index1].texID==index2
						)
					{
						//
						if (empY<m_cellNum.y-1)
						{
							m_aiTrys[m_aiTryNum++] = DIK_DOWN;
							break;
						}
						if (empX>size+1)
						{
							m_aiTrys[m_aiTryNum++] = DIK_LEFT;
							break;
						}
						
						m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
						m_aiTrys[m_aiTryNum++] = DIK_DOWN;
						m_aiTrys[m_aiTryNum++] = DIK_LEFT;
						m_aiTrys[m_aiTryNum++] = DIK_UP;
						m_aiTrys[m_aiTryNum++] = DIK_LEFT;
						m_aiTrys[m_aiTryNum++] = DIK_DOWN;
						m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
						m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
						m_aiTrys[m_aiTryNum++] = DIK_UP;
						m_aiTrys[m_aiTryNum++] = DIK_LEFT;
						m_aiTrys[m_aiTryNum++] = DIK_UP;
						m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
						m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
						m_aiTrys[m_aiTryNum++] = DIK_DOWN;
						m_aiTrys[m_aiTryNum++] = DIK_LEFT;
						m_aiTrys[m_aiTryNum++] = DIK_UP;

						//先移动倒叙插入
						//for (int i=m_cellNum.y-1-empY;i>0;i--)
						//{
						//	m_aiTrys[m_aiTryNum++] = DIK_DOWN;
						//}
						//for (int i=empX-size-1;i>0;i--)
						//{
						//	m_aiTrys[m_aiTryNum++] = DIK_LEFT;
						//}
						break;
					}
					//特殊处理避免死循环
					/*
					|empty  |index2 |
					|index1 |any    |
					*/
					if(m_cells[index2].texID==index1
						&&m_cells[index1].texID==-1
						&&m_cells[index1+m_cellNum.x].texID==index2
						)
					{
						//变成
						/*
						|index2 |any   |
						|index1 |empty |
						*/
						MoveEmpty(DIK_DOWN);
						break;
					}

					if(m_cells[m_cellNumXY-m_cellNum.x+size].texID==index1)//先将index1挪到左下角,再将index2挪到左下角时index1自动归位
					{
						/*
						|empty  |any   |
						|index1 |index2|  index2归位时index1自动归位
						*/
						srcTexID = index2;
					}
					else
					{
						srcTexID = index1;
					}

					//找到色块位置
					m_aiSrcCell = GetCell(srcTexID);

					int srcX = m_aiSrcCell->x;
					int srcY = m_aiSrcCell->y;

					int tarX = aiCompleteSizeX+1;
					int tarY = m_cellNum.y-1;

					//先毗邻
					if (abs(empX-srcX)>1 || abs(empY-srcY)>1)
					{
						if (empY<m_cellNum.y-2)
						{
							//先毗邻y
							if (empY>srcY+1)
							{
								MoveEmpty(DIK_UP);
							} 
							else if (empY<=srcY-1)
							{
								MoveEmpty(DIK_DOWN);
							}
							else if (empX>srcX+1)
							{
								MoveEmpty(DIK_LEFT);
							}
							else if (empX<=srcX-1)
							{
								MoveEmpty(DIK_RIGHT);
							}  
						} 
						else
						{
							//先毗邻x (空白从底面两排毗邻到右面两排)
							if (empX>srcX+1)
							{
								MoveEmpty(DIK_LEFT);
							}
							else if (empX<=srcX-1)
							{
								MoveEmpty(DIK_RIGHT);
							} 
							else if (empY>srcY+1)
							{
								MoveEmpty(DIK_UP);
							} 
							else if (empY<=srcY-1)
							{
								MoveEmpty(DIK_DOWN);
							}
						}
					}
					else
					{
						//先挪到底部
						if (srcY<m_cellNum.y-1)
						{
							AIMoveSrcDown(srcX,srcY,tarX,tarY,empX,empY);
						} 
						else if (srcX>tarX)
						{
							//挪到左边
							AIMoveSrcLeft(srcX,srcY,tarX,tarY,empX,empY);
						}
					}
					break;
				}

				//右面两排
				int aiCompleteSizeY = -1;
				if (aiCompleteSizeX>=m_cellNum.x-2-1)
				{
					for(int size = 0;size<m_cellNum.y-2;size++)
					{
						if(IsCellOK(m_cellNum.x-2,size)
							&&IsCellOK(m_cellNum.x-1,size)
							)
						{
							aiCompleteSizeY = size;
							continue;
						}
						int index1 = size*m_cellNum.x+(m_cellNum.x-2);
						int index2 = index1 + 1;

						//正好颠倒,特殊处理避免死循环
						/*
						|index2 |index1|
						|any    |empty |
						*/
						if(m_cells[index2].texID==index1
							&&m_cells[index1].texID==index2
							)
						{
							//
							if (empX<m_cellNum.x-1)
							{
								m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
								break;
							}
							if (empY>size+1)
							{
								m_aiTrys[m_aiTryNum++] = DIK_UP;
								break;
							}

							m_aiTrys[m_aiTryNum++] = DIK_DOWN;
							m_aiTrys[m_aiTryNum++] = DIK_LEFT;
							m_aiTrys[m_aiTryNum++] = DIK_UP;
							m_aiTrys[m_aiTryNum++] = DIK_UP;
							m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
							m_aiTrys[m_aiTryNum++] = DIK_DOWN;
							m_aiTrys[m_aiTryNum++] = DIK_LEFT;
							m_aiTrys[m_aiTryNum++] = DIK_DOWN;
							m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
							m_aiTrys[m_aiTryNum++] = DIK_UP;
							m_aiTrys[m_aiTryNum++] = DIK_UP;
							m_aiTrys[m_aiTryNum++] = DIK_LEFT;
							m_aiTrys[m_aiTryNum++] = DIK_DOWN;
							m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
							m_aiTrys[m_aiTryNum++] = DIK_DOWN;
							m_aiTrys[m_aiTryNum++] = DIK_LEFT;
							m_aiTrys[m_aiTryNum++] = DIK_UP;

							//先移动倒叙插入
							//for (int i=m_cellNum.x-1-empX;i>0;i--)
							//{
							//	m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
							//}
							//for (int i=empY-size-1;i>0;i--)
							//{
							//	m_aiTrys[m_aiTryNum++] = DIK_UP;
							//}
							break;
						}

						//特殊处理避免死循环
						/*
						|empty |index1|
						|index2|any   |
						*/
						if(m_cells[index2].texID==index1
							&&m_cells[index1].texID==-1
							&&m_cells[index1+m_cellNum.x].texID==index2
							)
						{
							//变成
							/*
							|index2 |index1|
							|any    |empty |
							*/
							MoveEmpty(DIK_DOWN);
							break;
						}

						if(m_cells[index2].texID==index1)//先将index1挪到右上角,再讲index2挪到右上角时index1自动归位
						{
							srcTexID = index2;
						}
						else
						{
							srcTexID = index1;
						}

						//找到色块位置
						m_aiSrcCell = GetCell(srcTexID);

						int srcX = m_aiSrcCell->x;
						int srcY = m_aiSrcCell->y;

						int tarX = m_cellNum.x-1;
						int tarY = aiCompleteSizeY+1;

						//先毗邻
						if (abs(empX-srcX)>1 || abs(empY-srcY)>1)
						{
							if (empY<m_cellNum.y-2)
							{
								//先毗邻y
								if (empY>srcY+1)
								{
									MoveEmpty(DIK_UP);
								} 
								else if (empY<=srcY-1)
								{
									MoveEmpty(DIK_DOWN);
								}
								else if (empX>srcX+1)
								{
									MoveEmpty(DIK_LEFT);
								}
								else if (empX<=srcX-1)
								{
									MoveEmpty(DIK_RIGHT);
								}  
							} 
							else
							{
								//先毗邻x
								if (empX>srcX+1)
								{
									MoveEmpty(DIK_LEFT);
								}
								else if (empX<=srcX-1)
								{
									MoveEmpty(DIK_RIGHT);
								} 
								else if (empY>srcY+1)
								{
									MoveEmpty(DIK_UP);
								} 
								else if (empY<=srcY-1)
								{
									MoveEmpty(DIK_DOWN);
								}
							}
						}
						else
						{
							//先挪到右部
							if (srcX<m_cellNum.x-1)
							{
								AIMoveSrcRight(srcX,srcY,tarX,tarY,empX,empY);
							} 
							else if (srcY>tarY)
							{
								//挪到上边
								AIMoveSrcUp(srcX,srcY,tarX,tarY,empX,empY);
							}
						}
						break;
					}
				}

				//最后四个
				if (aiCompleteSizeY>=m_cellNum.y-2-1)
				{
					//没结束就顺时针转
					if(empY==m_cellNum.y-2)
					{
						if (empX==m_cellNum.x-2)
						{
							MoveEmpty(DIK_RIGHT);
						}
						else
						{
							MoveEmpty(DIK_DOWN);
						}
					}
					else
					{
						if (empX==m_cellNum.x-2)
						{
							MoveEmpty(DIK_UP);
						}
						else
						{
							MoveEmpty(DIK_LEFT);
						}
					}
					//if(m_emptyCell->x==m_cellNum.x-2)
					//{
					//	MoveEmpty(DIK_RIGHT);
					//}
					//else if(m_emptyCell->y==m_cellNum.y-2)
					//{
					//	MoveEmpty(DIK_DOWN);
					//}
				}
			}
			//先拼左上角
			else
			{
				//找到不匹配的色块
				m_aiSrcCell = NULL;
				int srcTexID = -1;
				//for(int i = 0;i<m_cellNumXY-1;i++)
				//{
				//	if(m_cells[i].texID !=-1
				//		&& m_cells[i].texID != i)
				//	{
				//		srcTexID = i;
				//		break;
				//	}
				//}
				m_aiCompleteSize = -1;
				int maxSize = max(m_cellNum.x,m_cellNum.y);
				for(int size = 0;size<maxSize;size++)
				{
					int index = 0;
					for(int i = 0;i<size;i++)
					{
						index = size*m_cellNum.x+i;
						if(IsCellOK(i,size)==false)
						{
							srcTexID = index;
							break;
						}
						if(size>=m_cellNum.y-2 )  //最下面两排另拼
						{
							break;
						}
					}
					if (srcTexID!=-1)
					{
						break;
					}
					for(int j = 0;j<=size;j++)
					{
						index = j*m_cellNum.x+size;
						if(IsCellOK(size,j)==false)
						{
							srcTexID = index;
							break;
						}
						if(size>=m_cellNum.x-2)      //最右面两排另拼
						{
							break;
						}
					}
					if (srcTexID!=-1)
					{
						break;
					}
					m_aiCompleteSize = size;
				}



				//找到色块位置
				m_aiSrcCell = GetCell(srcTexID);

				int srcX = m_aiSrcCell->x;
				int srcY = m_aiSrcCell->y;

				//
				int tarX = m_aiSrcCell->texID%m_cellNum.x;
				int tarY = m_aiSrcCell->texID/m_cellNum.x;

				if (abs(empX-srcX)>1 || abs(empY-srcY)>1)
				{
					//先毗邻
					if (empY<srcY || 
						(empX>=empY && empX>srcX))
					{
						//先毗邻y
						if (empY>srcY+1)
						{
							MoveEmpty(DIK_UP);
						} 
						else if (empY<=srcY-1)
						{
							MoveEmpty(DIK_DOWN);
						}
						else if (empX>srcX+1)
						{
							MoveEmpty(DIK_LEFT);
						}
						else if (empX<=srcX-1)
						{
							MoveEmpty(DIK_RIGHT);
						}  
					}
					else
					{
						//先毗邻x
						if (empX>srcX+1)
						{
							MoveEmpty(DIK_LEFT);
						}
						else if (empX<=srcX-1)
						{
							MoveEmpty(DIK_RIGHT);
						} 
						else if (empY>srcY+1)
						{
							MoveEmpty(DIK_UP);
						} 
						else if (empY<=srcY-1)
						{
							MoveEmpty(DIK_DOWN);
						}
					}
				}
				else
				{
					if (srcX>srcY)
					{
						//先y
						if(tarY<srcY)
						{
							AIMoveSrcUp(srcX,srcY,tarX,tarY,empX,empY);
						}
						else if(tarY>srcY)
						{
							AIMoveSrcDown(srcX,srcY,tarX,tarY,empX,empY);
						}

						else if(tarX>srcX)
						{
							AIMoveSrcRight(srcX,srcY,tarX,tarY,empX,empY);
							return true;
						}
						else if(tarX<srcX)
						{
							AIMoveSrcLeft(srcX,srcY,tarX,tarY,empX,empY);
							return true;
						}
					}
					else
					{
						//先x
						if(tarX>srcX)
						{
							AIMoveSrcRight(srcX,srcY,tarX,tarY,empX,empY);
							return true;
						}
						else if(tarX<srcX)
						{
							AIMoveSrcLeft(srcX,srcY,tarX,tarY,empX,empY);
							return true;
						}
						else if(tarY<srcY)
						{
							AIMoveSrcUp(srcX,srcY,tarX,tarY,empX,empY);
						}
						else if(tarY>srcY)
						{
							AIMoveSrcDown(srcX,srcY,tarX,tarY,empX,empY);
						}
					}
				}
			}
		}
	}

	IsEnd();

    return true;
}

bool MiniGameSlidingBlock::AIMoveSrcUp(int srcX,int srcY,int tarX,int tarY,int empX,int empY)
{
	//将空格转到上侧 
	//倒叙插入移动
	m_aiTrys[m_aiTryNum++] = DIK_DOWN;
	//第1排
	if(empX==srcX-1 && empY==srcY-1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
	}
	else if(empX==srcX+1 && empY==srcY-1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
	}
	//第2排
	else if(empX==srcX-1 && empY==srcY)
	{
		if (IsCellOK(empX,empY-1)==false)
		{
			//不会破坏已经拼好的
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
		}
		else
		{
			if (srcY<m_cellNum.y-1)
			{
				//下面绕过去
				m_aiTrys[m_aiTryNum++] = DIK_LEFT;
				m_aiTrys[m_aiTryNum++] = DIK_UP;
				m_aiTrys[m_aiTryNum++] = DIK_UP;
				m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
				m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
				m_aiTrys[m_aiTryNum++] = DIK_DOWN;
			}
			else
			{
				//上面绕过去
				m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
				m_aiTrys[m_aiTryNum++] = DIK_UP;
			}
		}
	}
	else if(empX==srcX+1 && empY==srcY)
	{
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
		m_aiTrys[m_aiTryNum++] = DIK_UP;
	}
	//第3排
	else if(empX==srcX-1 && empY==srcY+1)
	{
		if (srcX<m_cellNum.x-1)
		{
			//首选右面绕过去
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
		}
		else
		{
			//左面绕过去
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
		}
	}
	else if(empX==srcX && empY==srcY+1)
	{
		if (srcX<m_cellNum.x-1)
		{
			//首选右面绕过去
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
		}
		else
		{
			//左面绕过去
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
		}
	}
	else if(empX==srcX+1 && empY==srcY+1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
		m_aiTrys[m_aiTryNum++] = DIK_UP;
		m_aiTrys[m_aiTryNum++] = DIK_UP;
	}
	return true;
}

bool MiniGameSlidingBlock::AIMoveSrcDown(int srcX,int srcY,int tarX,int tarY,int empX,int empY)
{
	//将空格转到下侧 
	//倒叙插入移动
	m_aiTrys[m_aiTryNum++] = DIK_UP;
	//第1排
	if(empX==srcX-1 && empY==srcY-1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
	}
	else if(empX==srcX && empY==srcY-1)
	{
		if (srcX<m_cellNum.x-1)
		{
			//首选右面绕过去
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
		}
		else
		{
			//左面绕过去
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
		}
	}
	else if(empX==srcX+1 && empY==srcY-1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
	}
	//第2排
	else if(empX==srcX-1 && empY==srcY)
	{
		m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
	}
	else if(empX==srcX+1 && empY==srcY)
	{
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
	}
	//第3排
	else if(empX==srcX-1 && empY==srcY+1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
	}
	else if(empX==srcX+1 && empY==srcY+1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
	}
	return true;
}

bool MiniGameSlidingBlock::AIMoveSrcLeft(int srcX,int srcY,int tarX,int tarY,int empX,int empY)
{
	//将空格转到左侧 
	//倒叙插入移动
	m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
	//第1排
	if(empX==srcX-1 && empY==srcY-1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
	}
	else if(empX==srcX && empY==srcY-1)
	{
		if (IsCellOK(empX-1,empY)==false
			|| srcX>= m_cellNum.x-1) //没法从右绕
		{
			//不会破坏已经拼好的
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
		}
		else
		{
			m_aiTrys[m_aiTryNum++] = DIK_UP;
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
		}
	}
	else if(empX==srcX+1 && empY==srcY-1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_UP;
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
	}
	//第2排
	else if(empX==srcX+1 && empY==srcY)
	{
		if (srcY<m_cellNum.y-1)
		{
			//首选下面绕过去
			m_aiTrys[m_aiTryNum++] = DIK_UP;
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
		}
		else
		{
			//上面绕过去
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
			m_aiTrys[m_aiTryNum++] = DIK_LEFT;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
		}
	}
	//第3排
	else if(empX==srcX+1 && empY==srcY+1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_UP;
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
	}
	else if(empX==srcX && empY==srcY+1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_UP;
		m_aiTrys[m_aiTryNum++] = DIK_LEFT;
	}
	else if(empX==srcX-1 && empY==srcY+1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_UP;
	}
	return true;
}

bool MiniGameSlidingBlock::AIMoveSrcRight(int srcX,int srcY,int tarX,int tarY,int empX,int empY)
{
	//将空格转到右侧 
	//倒叙插入移动
	m_aiTrys[m_aiTryNum++] = DIK_LEFT;
	//第1排
	if(empX==srcX-1 && empY==srcY-1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
		m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
		m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
	}
	else if(empX==srcX && empY==srcY-1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
		m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
	}
	else if(empX==srcX+1 && empY==srcY-1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_DOWN;
	}
	//第2排
	else if(empX==srcX-1 && empY==srcY)
	{
		if (srcY<m_cellNum.y-1)
		{
			//首选下面绕过去
			m_aiTrys[m_aiTryNum++] = DIK_UP;
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
		}
		else
		{
			//上面绕过去
			m_aiTrys[m_aiTryNum++] = DIK_DOWN;
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
			m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
			m_aiTrys[m_aiTryNum++] = DIK_UP;
		}
	}
	//第3排
	else if(empX==srcX-1 && empY==srcY+1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_UP;
		m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
		m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
	}
	else if(empX==srcX && empY==srcY+1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_UP;
		m_aiTrys[m_aiTryNum++] = DIK_RIGHT;
	}
	else if(empX==srcX+1 && empY==srcY+1)
	{
		m_aiTrys[m_aiTryNum++] = DIK_UP;
	}
	return true;
}

bool MiniGameSlidingBlock::Free()
{
	MiniGame::Free();
	SafeDeleteArray(m_cellMeshs);
	SafeDeleteArray(m_cells);
    return true;
}


void MiniGameSlidingBlock::OnSize()
{
}

bool MiniGameSlidingBlock::KeepResource(bool once, int& circle, String& nextTip)
{
    return true;
}

void MiniGameSlidingBlock::MoveEmpty(int key) 
{
	m_stepNum++;
	Cell* srcCell;
	Cell* tarCell = m_emptyCell;
	bool sucess = false;
	switch(key)
	{
	case DIK_LEFT:
		if(m_emptyCell->x>0)
		{
			srcCell =  m_emptyCell-1;
			sucess = true;
		}
		break;
	case DIK_RIGHT:
		if(m_emptyCell->x<m_cellNum.x-1)
		{
			srcCell =  m_emptyCell+1;			
			sucess = true;
		}
		break;
	case DIK_UP:
		if(m_emptyCell->y>0)
		{
			srcCell = m_emptyCell - m_cellNum.x;
			sucess = true;
		}
		break;
	case DIK_DOWN:
		if(m_emptyCell->y<m_cellNum.y-1)
		{
			srcCell = m_emptyCell + m_cellNum.x;
			sucess = true;
		}
		break;
	}

	if (sucess)
	{
		m_movingDir = vec2(srcCell->x-m_emptyCell->x,srcCell->y-m_emptyCell->y);

		if (srcCell==m_aiSrcCell)
		{
			m_aiSrcCell = m_emptyCell;
		}
		m_movingCell.x = m_emptyCell->x;
		m_movingCell.y = m_emptyCell->y;
		m_movingCell.texID = srcCell->texID;
		m_movingTime = 0;

		Swap(tarCell->texID,srcCell->texID);
		m_emptyCell = srcCell;
		if (IsCellOK(tarCell->x,tarCell->y))
		{
			PlaySound__("data/sound/event_equip.wav");
		}
		else
		{
			PlaySound__("data/sound/ui_click.wav");
		}
	}
	else
	{
		PlaySound__("data/sound/poker/cannot.wav");
	}
}

bool MiniGameSlidingBlock::IsEnd()
{
	//if (m_gameState==MS_End)
	//{
	//	return true;
	//}
	int lastState = m_gameState;
	if (m_cells[m_cellNumXY-1].texID!=-1)
	{
		return false;
	}
	for(int i = 0;i<m_cellNumXY-1;i++)
	{
		if(m_cells[i].texID != i)
			return false;
	}
	m_gameState = MS_End;
	if (lastState!=MS_End)
	{
		m_Level++;
		m_Level %= 10;
	}
	return true;
}

bool MiniGameSlidingBlock::IsCellOK(int x,int y)
{
	if (x<0||x>m_cellNum.x-1
		||y<0||y>m_cellNum.y-1)
	{
		return false;
	}
	int index = y*m_cellNum.x+x;
	if(m_cells[index].texID != index)
		return false;
	return true;
}

bool MiniGameSlidingBlock::IsCellEmpty(int x,int y)
{
	int index = y*m_cellNum.x+x;
	if(m_cells[index].texID != -1)
		return false;
	return true;
}

MiniGameSlidingBlock::Cell* MiniGameSlidingBlock::GetCell(int texID)
{
	//找到色块位置
	for(int i = 0;i<m_cellNumXY;i++)
	{
		if(m_cells[i].texID == texID)
		{
			return &m_cells[i];
		}
	}
	return NULL;
}



 

举报

相关推荐

0 条评论