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;
}
完