<1>Cube.h
#ifndef __JNTest__Cube__
#define __JNTest__Cube__
#include "cocos2d.h"
USING_NS_CC;
typedef enum CubeType{
CubeType_Red, //红
CubeType_Blue, //蓝
CubeType_White, //白
CubeType_Green, //绿
CubeType_Yellow, //黄
CubeType_Count
}CubeType;
class Cube : public Node
{
public:
Cube();
~Cube();
bool init(CubeType cubeType, int row, int col);
static Cube* create(CubeType cubeType, int row, int col);
Rect getCubeBoundingBox();
private:
CC_SYNTHESIZE(int, _row, Row);
CC_SYNTHESIZE(int, _col, Col);
CC_SYNTHESIZE(CubeType, _cubeType, CubeType); //方块数字
CC_SYNTHESIZE(LayerColor*, _bgLayerColor, BgLayerColor); //背景颜色
};
#endif /* defined(__JNTest__Cube__) */
<2>Cube.cpp
#include "Cube.h"
Cube::Cube(): _bgLayerColor(NULL){
}
Cube::~Cube(){
}
bool Cube::init(CubeType cubeType, int row, int col){
_row = row;
_col = col;
_cubeType = cubeType;
Color4B color;
switch (cubeType) {
case CubeType_Red:
color = Color4B::RED;
break;
case CubeType_Blue:
color = Color4B::BLUE;
break;
case CubeType_White:
color = Color4B::WHITE;
break;
case CubeType_Green:
color = Color4B::GREEN;
break;
case CubeType_Yellow:
color = Color4B::YELLOW;
break;
}
//背景颜色
_bgLayerColor = LayerColor::create(color, 60, 90);
_bgLayerColor->ignoreAnchorPointForPosition(false);
this->addChild(_bgLayerColor);
return true;
}
Cube* Cube::create(CubeType cubeType, int row, int col){
Cube* cube = new Cube();
if(cube && cube->init(cubeType, row, col)){
cube->autorelease();
return cube;
}
CC_SAFE_DELETE(cube);
return NULL;
}
Rect Cube::getCubeBoundingBox(){
Rect rect;
Vec2 pt = this->getPosition();
rect.size.width = 60;
rect.size.height = 90;
rect.origin.x = pt.x - 30;
rect.origin.y = pt.y - 45;
return rect;
}
<3>GameScene.h
#ifndef __JNTest__GameScene__
#define __JNTest__GameScene__
#include "cocos2d.h"
USING_NS_CC;
#include "Cube.h"
#include <vector>
using namespace std;
#define MAP_WIDTH 10
#define MAP_HEIGHT 10
struct PT
{
PT(int row, int col):_row(row), _col(col){}
PT& operator = (const PT& other){
this->_row = other._row;
this->_col = other._col;
return *this;
}
bool operator == (const PT& other){
return this->_row == other._row && this->_col == other._col;
}
int _row;
int _col;
};
class GameScene : public Layer
{
public:
GameScene();
~GameScene();
static Scene* scene();
virtual bool init();
CREATE_FUNC(GameScene);
public:
bool onTouchBegan(Touch *touch, Event *unused); //触摸
Vec2 getPositionByRowAndCol(int row, int col); //根据行列得到方块应该摆放的位置
Cube* getClickCubeByPoint(Vec2 clickPoint); //根据点击点获取点击到的方块
Cube* getCubeByPT(const PT& pt); //根据行列获取方块
void judgeTwoCube(Cube* cube1, Cube* cube2); //判断2个方块是否相同
void findPath(PT ptBegin, PT ptEnd, int turns, vector<PT> ptVecPath, vector<PT>& bestVecPath); //回溯法查找路径
bool isTurn(const vector<PT>& vectPath, const PT& ptNow); //是否有拐点
void removeTwoCube(Cube* cube1, Cube* cube2); //移除2个方块
void tipNode(Node* node); //在方块上添加闪烁提示
void removeTipNode(Node* node); //移除提示
bool isNear(Cube* cube1, Cube* cube2); //两个方块是否是相邻
void printDepth(vector<PT>& vecPath); //打印vector中的路径信息
PT findOneKongPT(); //返回一个空位置的PT
bool isGameOver(); //游戏是否结束
Cube* _firstClickCube; //第一次点击的Cube
Cube* _secondClickCube; //第二次点击的Cube
private:
Cube** _matrixCube;
};
#endif /* defined(__JNTest__GameScene__) */
<4>GameScene.cpp
#include "GameScene.h"
//上下左右四个方向
PT dir[4] = {
{1, 0},
{-1, 0},
{0, -1},
{0, 1}
};
//是否访问过
bool vis[10][10] = {0};
//设置所有及诶单都没有访问过
void setAllNotVisit(){
for(int i = 0; i < 10; i++)
for(int j = 0; j < 10; j++){
vis[i][j] = false;
}
}
GameScene::GameScene():_firstClickCube(NULL), _secondClickCube(NULL){
srand((unsigned)time(NULL));
}
GameScene::~GameScene(){
}
Scene* GameScene::scene(){
Scene* scene = Scene::create();
GameScene* layer = GameScene::create();
scene->addChild(layer);
return scene;
}
bool GameScene::init(){
if(!Layer::init()){
return false;
}
EventListenerTouchOneByOne* touchListener = EventListenerTouchOneByOne::create();
touchListener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchBegan, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
int size = sizeof(Cube*) * MAP_WIDTH * MAP_HEIGHT;
_matrixCube = (Cube**)malloc(size);
memset((void*)_matrixCube, 0, size);
//设置所有及诶单都没有访问过
setAllNotVisit();
//初始化地图
PT pt = findOneKongPT();
int row, col;
while(pt._row != -1){
CubeType cubeType = (CubeType)(rand() % CubeType_Count);
row = pt._row;
col = pt._col;
Cube* cube = Cube::create(cubeType, row, col);
cube->setPosition(getPositionByRowAndCol(row, col));
_matrixCube[row * MAP_WIDTH + col] = cube;
this->addChild(cube);
pt = findOneKongPT();
row = pt._row;
col = pt._col;
cube = Cube::create(cubeType, row, col);
cube->setPosition(getPositionByRowAndCol(row, col));
_matrixCube[row * MAP_WIDTH + col] = cube;
this->addChild(cube);
pt = findOneKongPT();
}
return true;
}
bool GameScene::onTouchBegan(Touch *touch, Event *unused){
Vec2 clickPoint = touch->getLocation();
Cube* clickCube = getClickCubeByPoint(clickPoint);
if(clickCube && !_firstClickCube){
_firstClickCube = clickCube;
tipNode(_firstClickCube);
}else if (clickCube && _firstClickCube && clickCube != _firstClickCube){
_secondClickCube = clickCube;
tipNode(_secondClickCube);
judgeTwoCube(_firstClickCube, _secondClickCube);
}
return true;
}
Vec2 GameScene::getPositionByRowAndCol(int row, int col){
return Vec2(col * 64 + 32, row * 96 + 48);
}
Cube* GameScene::getClickCubeByPoint(Vec2 clickPoint){
for(int row = 1; row < MAP_HEIGHT - 1; row++){
for(int col = 1; col < MAP_WIDTH - 1; col++){
Cube* cube = _matrixCube[row * MAP_WIDTH + col];
if(cube && cube->getCubeBoundingBox().containsPoint(clickPoint)){
return cube;
}
}
}
return NULL;
}
Cube* GameScene::getCubeByPT(const PT& pt){
return _matrixCube[pt._row * MAP_WIDTH + pt._col];
}
void GameScene::judgeTwoCube(Cube* cube1, Cube* cube2) {
removeTipNode(_firstClickCube);
removeTipNode(_secondClickCube);
_firstClickCube = NULL;
_secondClickCube = NULL;
if(cube1->getCubeType() != cube2->getCubeType()){
return;
}
vector<PT> ptVec;
ptVec.push_back(PT(cube1->getRow(), cube1->getCol())); //把当前的节点添加进来
vector<PT> bestPath = ptVec;
findPath(PT(cube1->getRow(), cube1->getCol()), PT(cube2->getRow(), cube2->getCol()), 0, ptVec, bestPath);
printDepth(bestPath);
if(bestPath.size() > 1){
removeTwoCube(cube1, cube2);
}
if(isGameOver()){
Director::getInstance()->replaceScene(TransitionFade::create(1.0f, GameScene::scene()));
}
}
void GameScene::findPath(PT ptBegin, PT ptEnd, int turns, vector<PT> ptVecPath, vector<PT>& bestVecPath){
if(ptBegin == ptEnd && turns <= 2){ //成功
if(ptVecPath.size() < bestVecPath.size() || bestVecPath.size() == 1){
bestVecPath = ptVecPath;
}
return;
}
if(ptBegin._row < 0 || ptBegin._col < 0 || ptBegin._row > MAP_WIDTH - 1 || ptBegin._col > MAP_HEIGHT || turns > 2){ //失败
return;
}
for(int i = 0; i < 4; i++){ //四个方向查找
int oldRow = ptBegin._row;
int oldCol = ptBegin._col;
int newRow = ptBegin._row + dir[i]._row;
int newCol = ptBegin._col + dir[i]._col;
if(!vis[newRow][newCol] && (!getCubeByPT(PT(newRow, newCol)) || PT(newRow, newCol) == ptEnd)){
vis[newRow][newCol] = true;
ptBegin = PT(newRow, newCol);
ptVecPath.push_back(ptBegin);
if(isTurn(ptVecPath, ptBegin)){
turns = turns + 1;
}
findPath(ptBegin, ptEnd, turns, ptVecPath, bestVecPath);
if(isTurn(ptVecPath, ptBegin)){
turns = turns - 1;
}
ptVecPath.pop_back();
ptBegin = PT(oldRow, oldCol);
vis[newRow][newCol] = false;
}
}
}
bool GameScene::isTurn(const vector<PT>& vecPath, const PT& ptNow){
if(vecPath.size() < 3){
return false;
}
PT ptPrevious = vecPath[vecPath.size() - 3];
if(ptPrevious._row != ptNow._row && ptPrevious._col != ptNow._col){
return true;
}
return false;
}
void GameScene::removeTwoCube(Cube* cube1, Cube* cube2){
_matrixCube[cube1->getRow() * MAP_WIDTH + cube1->getCol()] = NULL;
cube1->removeFromParent();
cube1 = NULL;
_matrixCube[cube2->getRow() * MAP_WIDTH + cube2->getCol()] = NULL;
cube2->removeFromParent();
cube2 = NULL;
}
void GameScene::tipNode(Node* node){
Sequence* seq = Sequence::create(ScaleTo::create(0.5f, 0.8f), ScaleTo::create(0.8f, 1.2f), ScaleTo::create(0.4f, 1.0f), NULL);
RepeatForever* repeat = RepeatForever::create(seq);
node->runAction(repeat);
}
void GameScene::removeTipNode(Node* node){
node->setScale(1.0f);
node->stopAllActions();
}
bool GameScene::isNear(Cube* cube1, Cube* cube2){
if(abs(cube1->getRow() - cube2->getRow()) == 1 && cube1->getCol() == cube2->getCol()){
return true;
}
if(abs(cube1->getCol() - cube2->getCol()) == 1 && cube1->getRow() == cube2->getRow()){
return true;
}
return false;
}
void GameScene::printDepth(vector<PT>& vecPath){
do{
if(vecPath.size() == 1){
break;
}
for(vector<PT>::iterator iter = vecPath.begin(); iter != vecPath.end(); iter++){
PT pt = (*iter);
Sequence* seq = Sequence::create(Blink::create(1.2f, 4), RemoveSelf::create(), NULL); //
Label* labTip = Label::createWithSystemFont("*", "Arial", 80);
labTip->ignoreAnchorPointForPosition(false);
labTip->setPosition(getPositionByRowAndCol(pt._row, pt._col));
this->addChild(labTip);
labTip->runAction(seq);
}
}while (0);
}
PT GameScene::findOneKongPT(){
vector<PT> vPt;
for(int row = 1; row < MAP_HEIGHT - 1; row++){
for(int col = 1; col < MAP_WIDTH - 1; col++){
Cube* cube = _matrixCube[row * MAP_WIDTH + col];
if(cube){
continue;
}
vPt.push_back(PT(row, col));
}
}
if(vPt.size() == 0){
return PT(-1, -1);
}
return vPt[rand() % (vPt.size())];
}
bool GameScene::isGameOver(){
for(int row = 1; row < MAP_HEIGHT - 1; row++){
for(int col = 1; col < MAP_WIDTH - 1; col++){
Cube* cube = _matrixCube[row * MAP_WIDTH + col];
if(cube){ //如果还有方块没有消除,则游戏就没有结束.
return false;
}
}
}
return true;
}