cocos2d-x写的跨平台象棋网络版

cocos2d-x写的跨平台象棋网络版_第1张图片
cocos2d-x写的跨平台象棋网络版_第2张图片
cocos2d-x写的跨平台象棋网络版_第3张图片
cocos2d-x写的跨平台象棋网络版_第4张图片
cocos2d-x写的跨平台象棋网络版_第5张图片
cocos2d-x写的跨平台象棋网络版_第6张图片



cocos2d-x写的跨平台象棋网络版_第7张图片

改BUG改了三夜都是凌晨5点才睡,,累,,泪
目录
APP:
https://yunpan.cn/Oc6iaETF6fqxdK 访问密码 64b2

AppDelegate.cpp

#include "AppDelegate.h"
#include "Common.h"
#include "SceneStart.h"

USING_NS_CC;

AppDelegate::AppDelegate() {

}

AppDelegate::~AppDelegate() 
{
}

bool AppDelegate::applicationDidFinishLaunching() {
    // initialize director
    CCDirector* pDirector = CCDirector::sharedDirector();
    CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();

    pDirector->setOpenGLView(pEGLView);
    //设置分别率
    pEGLView->setDesignResolutionSize(800, 450, kResolutionExactFit);

    // turn on display FPS
    pDirector->setDisplayStats(false);

    // set FPS. the default value is 1.0/60 if you don't call this
    pDirector->setAnimationInterval(1.0 / 60);

    // create a scene. it's an autorelease object
    CCScene *pScene = CreateScene(SceneStart::create());

    // run
    pDirector->runWithScene(pScene);

    return true;
}

// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground() {
    CCDirector::sharedDirector()->stopAnimation();

    // if you use SimpleAudioEngine, it must be pause
    // SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
}

// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground() {
    CCDirector::sharedDirector()->startAnimation();

    // if you use SimpleAudioEngine, it must resume here
    // SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
}

AppDelegate.h
#ifndef  _APP_DELEGATE_H_
#define  _APP_DELEGATE_H_

#include "cocos2d.h"

/**
@brief    The cocos2d Application.

The reason for implement as private inheritance is to hide some interface call by CCDirector.
*/
class  AppDelegate : private cocos2d::CCApplication
{
public:
    AppDelegate();
    virtual ~AppDelegate();

    /**
    @brief    Implement CCDirector and CCScene init code here.
    @return true    Initialize success, app continue.
    @return false   Initialize failed, app terminate.
    */
    virtual bool applicationDidFinishLaunching();

    /**
    @brief  The function be called when the application enter background
    @param  the pointer of the application
    */
    virtual void applicationDidEnterBackground();

    /**
    @brief  The function be called when the application enter foreground
    @param  the pointer of the application
    */
    virtual void applicationWillEnterForeground();
};

#endif // _APP_DELEGATE_H_

Common.h

#ifndef __COMMON_H__
#define __COMMON_H__
#include "cocos2d.h"
USING_NS_CC;

#define winSize CCDirector::sharedDirector()->getWinSize()

static inline CCScene* CreateScene(CCLayer* layer)
{
    CCScene* s = CCScene::create();
    s->addChild(layer);
    return s;
}

#endif


Game.cpp

#include "Game.h"
#include "SceneGame.h"
#include "Net.h"
#include "backMusic.h"
#include "SimpleAudioEngine.h"

bool Game::_redStart;//定义   .h文件中是申明
bool Game::_redTurn;
void Game::onEnter()
{
    CCLayer::onEnter();
    _steps = CCArray::create();//没有加入到任何子节点中,下一帧自动清除
    _steps->retain();//所以保存
    CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("backMusic.mp3", true);
}
void Game::onExit()
{
    CCLayer::onExit();
    _steps->release();//retain 之后一定要 release 
    CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();
}

bool Game::init()
{
    CCLayer::init();

    //添加自己照片。。哈哈
    CCSprite* sprite = CCSprite::create("3.jpg");
    sprite->setPosition(ccp(630, 200));
    sprite->setScale(0.4);
    addChild(sprite);

    //添加音乐
    backMusic* music = backMusic::create();
    addChild(music);

    //把棋盘放到Game中
    _plate = Plate::create();
    addChild(_plate);
    //摆好棋子
    Stone::_myWidth = winSize.height / 10;
    for (size_t i = 0; i < 32; i++)
    {
        _stone[i] = Stone::create(i);
        addChild(_stone[i]);
    }

    //启动触摸
    setTouchEnabled(true);
    setTouchMode(kCCTouchesOneByOne);

    //初始化按钮
    initItem();

    //设置关闭按钮
    CCMenuItem* closeItem = CCMenuItemImage::create("CloseNormal.png", "CloseSelected.png", this, menu_selector(Game::closeGame));
    closeItem->setPosition(ccp(370, -200));
    menu->addChild(closeItem);

    //初始化选中时的精灵
    _selectFlag = CCSprite::create("selected.png");
    addChild(_selectFlag);
    _selectFlag->setVisible(false);

    //一开始没有任何棋子被选中
    _selectid = -1;

    //悔棋标志为false
    bool regretFlag = false;

    _redTurn = true;

    //启动定时器
    scheduleUpdate();

    return true;
}

bool Game::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
    return true;
}
void Game::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
    int clickid = getClickStone(pTouch);//根据触摸点获取棋子,如果这个点没有棋子返回 -1
    if (_selectid == -1)//如果还没有棋子被选中
        selectStone(clickid);
    else//走棋
        moveStone(clickid,pTouch->getLocation());
}
//选择棋子
void Game::selectStone(int clickid)
{
    if (clickid != -1 && _redTurn == _redStart && _redTurn == _stone[clickid]->_red)//如果1.点击到棋子  2.轮到这我方走  3.是我方的棋子
    {
        doSelectStone(clickid);

        sendSelectStoneToNet();
    }
}
//移动棋子
void Game::moveStone(int clickid,CCPoint pos)
{
    if (clickid != -1)//首先判断点中的位置是不是棋子
    {
        if (_stone[clickid]->_red == _stone[_selectid]->_red)//如果是己方的棋子再次选中
        {
            doSelectStone(clickid);

            sendSelectStoneToNet();
            return;
        }
    }
    //棋子走动
    int row, col;
    if (!getRowColByPos(row, col,pos))//看能否获得行列
        return;
    if (!canMove(_selectid, row, col, clickid))//每个棋子有自己固定的走法,必须经过审核才能走
        return;

    //向对方发送信息
    sendMoveStoneToNet(row, col);

    //走棋                                注意这里两个selectid  一个是发送过来的_selectid 一个是自己方点击的 _selectid
    doMoveStone(_selectid, row, col);//两个功能,1.对方发信息来走棋(需要ID和目标位置)2.自己方走棋(需要选中的棋和目标位置)
}
//发送选棋信息
void Game::sendSelectStoneToNet()
{
    char buf[2];
    buf[0] = 1;//命令字1  表示选择棋子
    buf[1] = _selectid;
    Net::getInstance()->Send(buf, 2);
}
//发送走棋信息
void Game::sendMoveStoneToNet(int row, int col)
{
    char buf[4];
    buf[0] = 2;
    buf[1] = _selectid;
    buf[2] = 9 - row;
    buf[3] = 8 - col;
    Net::getInstance()->Send(buf, 4);
}

//用于接收数据
void Game::update(float)
{
    if (_redStart == _redTurn && !regretFlag)//此时不接受消息
        return;

    char buf;
    char id;
    char row;
    char col;
    if (Net::getInstance()->Recv(&buf, 1) != 1)
        return;

    switch (buf)
    {
    case 1://接收对方选择棋子的命令
        Net::getInstance()->Recv(&id, 1);
        doSelectStone(id);//把对方选择棋子显示出来
        break;
    case 2:
        Net::getInstance()->Recv(&id, 1);
        Net::getInstance()->Recv(&row, 1);
        Net::getInstance()->Recv(&col, 1);
        doMoveStone(id, row, col);
        break;
    case 3:
        judgeRegret();
        break;
    case 'y': 
        waitRegretYes();
        break;
    case 'n':
        waitRegretNo();
        break;
    case 9:
        CCDirector::sharedDirector()->replaceScene(CreateScene(Game::create()));
    }
}
void Game::initItem()
{
    menu = CCMenu::create();
    addChild(menu);

    //创建悔棋按钮
    initRegretButton();

    //其他按钮
    regretTextItem = CCMenuItemImage::create("huiqikuang.png", "huiqikuang2.png");
    yesItem = CCMenuItemImage::create("tongyi.png", "tongyi2.png");
    noItem = CCMenuItemImage::create("butongyi.png", "butongyi2.png");
    giveMyItem = CCMenuItemImage::create("shenqing2.png", "huiqikuang2.png");
    giveMyItemYes = CCMenuItemImage::create("duifangtongyi2.png", "duifangtongyi.png");
    giveMyItemNo = CCMenuItemImage::create("duifangbutongyi2.png", "duifangbutongyi.png");
    menu->addChild(regretTextItem);
    menu->addChild(yesItem);
    menu->addChild(noItem);
    menu->addChild(giveMyItem);
    menu->addChild(giveMyItemYes);
    menu->addChild(giveMyItemNo);

    regretTextItem->setVisible(false);
    yesItem->setVisible(false);
    noItem->setVisible(false);
    giveMyItem->setVisible(false);
    giveMyItemYes->setVisible(false);
    giveMyItemNo->setVisible(false);

    moveBy(ccp(-180, 120), regretTextItem);//设置位置
    moveBy(ccp(-280, -100), yesItem);//设置位置
    moveBy(ccp(-80, -100), noItem);//设置位置
    moveBy(ccp(-180, 120), giveMyItem);//设置位置
    moveBy(ccp(-180, 120), giveMyItemYes);//设置位置
    moveBy(ccp(-180, 120), giveMyItemNo);//设置位置

    yesItem->setTarget(this, menu_selector(Game::yesregret));
    noItem->setTarget(this, menu_selector(Game::noregret));
    giveMyItemYes->setTarget(this, menu_selector(Game::waitYes));
    giveMyItemNo->setTarget(this, menu_selector(Game::waitNo));
}
void Game::judgeRegret()
{
    regretTextItem->setVisible(true);
    yesItem->setVisible(true);
    noItem->setVisible(true);
}

//显示出 选择的棋子
void Game::doSelectStone(int clickid)
{
    //如果有棋子被点中,,就让【】 图形在那个位置显示
    _selectFlag->setPosition(_stone[clickid]->getPosition());
    _selectFlag->setVisible(true);
    _selectid = clickid;
}
//用于把一个id从当前位置,移动到 指定位置
void Game::doMoveStone(int selectid, int row, int col)
{
    int killid = getStoneIdByRowCol(row, col);
    //记录走棋信息
    Step* step = Step::create(selectid, _stone[selectid]->_row, _stone[selectid]->_col, row, col, killid);
    _steps->addObject(step);//加入到数组中

    //走棋
    _stone[_selectid]->move(row, col);
    _selectFlag->setVisible(false);

    _selectid = -1;//走完后一定要设置,不然会一直选中

    if (killid != -1)
    {
        _stone[killid]->_dead = true;
        _stone[killid]->setVisible(false);

        //检查游戏是否结束
        checkGameOver(killid);
    }
    _redTurn = !_redTurn;
}
void Game::checkGameOver(int killid)
{
    Stone* s = _stone[killid];
    if (s->_type == SHUAI)//游戏结束 如果这次杀死的是帅或将,那么就打印
    {
        CCMenu* menu = CCMenu::create();
        addChild(menu);
        if (s->_red == Game::_redStart)//开始选的棋和杀死的棋一样,,那么是输了
        {
            CCMenuItem* item1 = CCMenuItemImage::create("shuijiemian.png", "shuijiemian.png");
            menu->addChild(item1);
            item1->setPosition(ccp(-150, 50));
        }
        else//赢了
        {
            CCMenuItem* item1 = CCMenuItemImage::create("yingjiemian.png", "yingjiemian.png");
            menu->addChild(item1);
            item1->setPosition(ccp(-150, 50));

            CCMenuItem* item = CCMenuItemImage::create("new.jpg", "new2.jpg");
            menu->addChild(item);
            item->setTarget(this, menu_selector(Game::gameOverCallback));
            item->setPosition(ccp(-150, -150));
        }
        regretItem->setEnabled(false);

        // 红旗黑棋位置对调
        Game::_redStart = !Game::_redStart;
    }
}
void  Game::gameOverCallback(CCObject*)
{
    char buf = 9;
    Net::getInstance()->Send(&buf, 1);
    CCDirector::sharedDirector()->replaceScene(CreateScene(Game::create()));
}
//获取 点中 的棋子的id
int Game::getClickStone(CCTouch* touch)
{
    int row, col;
    if (!getRowColByPos(row, col, touch->getLocation()))
        return -1;
    return getStoneIdByRowCol(row, col);
}
//通过坐标转化成行列
bool Game::getRowColByPos(int &row, int &col, CCPoint pt)
{
    for (row = 0; row < 10; row++)
        for (col = 0; col < 9; col++)
        {
            //获取棋盘上点的世界坐标
            CCPoint ptStone = getPosByRowCol(row, col);
            //判断世界坐标上的点。。是否和触摸点的距离小于  棋子宽度的一半
            if (ptStone.getDistance(pt) < Stone::_myWidth / 2)
                return true;
        }
    return false;
}
//通过行列。看是否能找到某个棋子
int Game::getStoneIdByRowCol(int row, int col)
{
    for (int i = 0; i < 32; i++)
    {
        if (_stone[i]->_row == row && _stone[i]->_col == col && !_stone[i]->_dead)
            return i;
    }
    return -1;
}

//行列 转换成 世界坐标
CCPoint Game::getPosByRowCol(int row, int col)
{
    float x = col*Stone::_myWidth;
    float y = row*Stone::_myWidth;
    return ccp(x, y) + Stone::_ptOff;
}

bool  Game::canMove(int moveid, int row, int col, int killid)
{
    switch (_stone[moveid]->_type)
    {
    case CHE:
        return canMoveChe(moveid, row, col, killid);
    case MA:
        return canMoveMa(moveid, row, col, killid);
    case XIANG:
        return canMoveXiang(moveid, row, col, killid);
    case SHI:
        return canMoveShi(moveid, row, col, killid);
    case SHUAI:
        return canMoveShuai(moveid, row, col, killid);
    case PAO:
        return canMovePao(moveid, row, col, killid);
    case BING:
        return canMoveBing(moveid, row, col, killid);
    default:
        break;
    }
    return false;
}
int Game::getStoneCountInLine(int row1, int col1, int row2, int col2)
{
    if (row1 != row2 &&col1 != col2)
        return -1;
    int t = 0;
    if (row1 == row2)
    {
        int min = col1 > col2 ? col2 : col1;
        int max = col1 + col2 - min;
        for (int col = min + 1; col < max; col++)
        {
            int id = getStoneIdByRowCol(row1, col);
            if (id != -1)
                t++;
        }
    }
    else
    {
        int min = row1 > row2 ? row2 : row1;
        int max = row1 + row2 - min;
        for (int row = min + 1; row < max; row++)
        {
            int id = getStoneIdByRowCol(row,col1);
            if (id != -1)//如果有棋子
                t++;
        }
    }
    return t;
}

bool Game::canMoveChe(int moveid, int row, int col, int killid)//moveid 是 上次选中的棋子 killid是这次点击的棋子
{
    if (getStoneCountInLine(row, col, _stone[moveid]->_row, _stone[moveid]->_col) == 0)
        return true;
    return false;
}
bool Game::canMoveMa(int moveid, int row, int col, int killid)
{
    int r = _stone[moveid]->_row;
    int c = _stone[moveid]->_col;
    int d = abs(r - row) * 10 + abs(c - col);
    if (d != 12 && d != 21)
        return false;
    //判断马腿
    if (d == 21)//列相差1,航相差2
    {
        int mr = (r + row) / 2;
        int mc = c;
        if (getStoneIdByRowCol(mr, mc)!=-1)//说明这个位置有棋子
            return false;
    }
    else
    {
        int mr = r;
        int mc = (c + col) / 2;
        if (getStoneIdByRowCol(mr, mc) != -1)//说明这个位置有棋子
            return false;
    }
    return true;
}
bool Game::canMoveXiang(int moveid, int row, int col, int killid)
{
    if (_stone[moveid]->_red == _redStart)//只要动的棋子和开局选的棋子一样,那么就可以在下方动
    {
        if (row > 4)
        return false;
    }
    else
    {
        if (row < 5)
            return false;
    }
    int r = _stone[moveid]->_row;
    int c = _stone[moveid]->_col;
    int d = abs(r - row) * 10 + abs(c - col);
    if (d != 22)
        return false;

    int mr = (row + r) / 2;
    int mc = (col + c) / 2;
    int id = getStoneIdByRowCol(mr, mc);
    if (id != -1)
        return false;
    return true;
}
bool Game::canMoveShi(int moveid, int row, int col, int killid)
{
    if (_stone[moveid]->_red == _redStart)//只要动的棋子和开局选的棋子一样,那么就可以在下方动
    {
        if (row > 2)
        return false;
    }
    else
    {
        if (row < 7)
            return false;
    }
    if (col < 3 || col>5)
        return false;

    int r = _stone[moveid]->_row;
    int c = _stone[moveid]->_col;
    int d = abs(r - row) * 10 + abs(c - col);
    if (d == 11)//行相等,那么列只能差值为1
        return true;
    return false;
}
bool Game::canMoveShuai(int moveid, int row, int col, int killid)
{
    //老蒋照面
    if (killid != -1 && _stone[killid]->_type == SHUAI)
        return canMoveChe(moveid, row, col, killid);

    //开局选的棋子一定在下方
    if (_stone[moveid]->_red == _redStart)//只要动的棋子和开局选的棋子一样,那么就可以在下方动
    {
        if (row > 2)
            return false;
    }
    else//如果动的棋子,和开局选的棋子不一样,那么就动上面的棋子
    {
        if (row < 7)
            return false;
    }
    if (col < 3 || col>5)
        return false;

    int r = _stone[moveid]->_row;
    int c = _stone[moveid]->_col;
    int d = abs(r - row) * 10 + abs(c - col);
    if (d == 1 || d == 10)//行相等,那么列只能差值为1
        return true;
    return false;
}
bool Game::canMovePao(int moveid, int row, int col, int killid)
{
    if (killid == -1)//说明没有点中棋子
        return canMoveChe(moveid, row, col, killid);//和车一样的使用
    //点中棋子后,中间必须隔一个才能走
    int count = getStoneCountInLine(row, col, _stone[moveid]->_row, _stone[moveid]->_col);
    return  count == 1;//跑中间只能隔一个
}
bool Game::canMoveBing(int moveid, int row, int col, int killid)
{
    int r = _stone[moveid]->_row;
    int c = _stone[moveid]->_col;
    int d = abs(r - row) * 10 + abs(c - col);
    if (d != 1 && d != 10)//行相等,那么列只能差值为1
        return false;

    if (_stone[moveid]->_red == _redStart)//只要动的棋子和开局选的棋子一样,那么就可以在下方动
    {
        //不能后退
        if (row < r)//将要走的行 大于 现在的行
            return false;
        //没过河不能平移
        if (r <= 4 && col != c)
            return false;
    }
    else
    {
        //不能后退
        if (row > r)//将要走的行 大于 现在的行
            return false;
        //没过河不能平移
        if (r >= 5  && col != c)
            return false;
    }
    return true;
}

void Game::yesregret(CCObject*)
{
    char buf = 'y';
    Net::getInstance()->Send(&buf, 1);
    regret();
    yesItem->setVisible(false);
    noItem->setVisible(false);
    regretTextItem->setVisible(false);
}
void Game::noregret(CCObject*)
{
    char buf = 'n';
    Net::getInstance()->Send(&buf, 1);
    yesItem->setVisible(false);
    noItem->setVisible(false);
    regretTextItem->setVisible(false);
}
void Game::waitRegretYes()
{
    giveMyItem->setVisible(false);

    giveMyItemYes->setVisible(true);
    regret();
}
void Game::waitRegretNo()
{
    giveMyItem->setVisible(false);

    giveMyItemNo->setVisible(true);
}
void Game::waitYes(CCObject*)
{
    giveMyItemYes->setVisible(false);
    //打开触摸
    setTouchEnabled(true);
    //悔棋标记消失
    regretFlag = false;
}
void Game::waitNo(CCObject*)
{
    giveMyItemNo->setVisible(false);
    //打开触摸
    setTouchEnabled(true);
    //悔棋标记消失
    regretFlag = false;
}
//在悔棋之前进行判断,对方走时,自己不能悔棋
void Game::preregret(CCObject*)
{
    if (Game::_redStart != Game::_redTurn)
        return;

    //发消息给对方
    char buf = 3;
    Net::getInstance()->Send(&buf, 1);
    giveMyItem->setVisible(true);

    //屏蔽自己的触摸
    setTouchEnabled(false);

    //可以接收消息
    regretFlag = true;
 }
void Game::regret()
{
    for (size_t i = 0; i < 2; i++)
    {
        if (_steps->count() == 0)
            return;
        //取出上一次的棋子 的位置
        CCObject* obj = _steps->lastObject();
        Step* step = (Step*)obj;

        //将这个棋子,恢复到原来位置
        Stone* sMove = _stone[step->_moveid];//获取上一个棋子的id
        sMove->move(step->_rowFrom, step->_colFrom);

        //如果有死掉的棋子,应该复活
        if (step->_killid != -1)
        {
            Stone* sKill = _stone[step->_killid];
            sKill->_dead = false;//不死
            sKill->setVisible(true);//再显现出来
        }

        //初始化一些和移动相关的变量
        _selectid = -1;
        _selectFlag->setVisible(false);
        _redTurn = !_redTurn;

        //把Array里面最后一个对象删除
        _steps->removeLastObject();
    }
}

//创建悔棋按钮
void Game::initRegretButton()
{
    regretItem = CCMenuItemImage::create("regret.png", "regret2.png");
    menu->addChild(regretItem);
    regretItem->setTarget(this, menu_selector(Game::preregret));//设置触发函数
    moveBy(ccp(120, 0), regretItem);//设置位置
}

void Game::moveBy(CCPoint pt, CCNode* node)
{
    node->setPosition(pt + node->getPosition());
}

void Game::closeGame(CCObject*)
{
    if (Net::getInstance()->isServer())
#ifdef WIN32
        closesocket(Net::getInstance()->getServerSocket());
#else
        close(Net::getInstance()->getServerSocket());
#endif
    else
#ifdef WIN32
        closesocket(Net::getInstance()->getClientSocket());
#else
        close(Net::getInstance()->getClientSocket());
#endif
    exit(0);
}

Game.h

#ifndef __GAME_H__
#define __GAME_H__

#include "Common.h"
#include "Stone.h"
#include "Plate.h"
#include "Step.h"

class Game:public CCLayer
{
    int _selectid;//记录选中棋子的id
    bool _isOver;//游戏是否结束
    bool regretFlag;//是否正确按下悔棋
    CCSprite* _selectFlag;//选中时的精灵图片
    CCMenu* menu;
    CCMenuItem* regretItem;
    CCMenuItem* regretTextItem;
    CCMenuItem* yesItem;
    CCMenuItem* noItem;
    CCMenuItem* giveMyItem;
    CCMenuItem* giveMyItemYes;
    CCMenuItem* giveMyItemNo;
public:
    static bool _redStart;//红棋开始
    static bool _redTurn;//该不该红走 (轮到谁走了)
    Plate* _plate;//棋盘
    Stone* _stone[32];//棋子
    CCArray* _steps;//记录走棋的信息


    CREATE_FUNC(Game);
    bool init();

    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
    //如果点到空地上,返回-1
    int getClickStone(CCTouch*);
    CCPoint getPosByRowCol(int, int);
    bool getRowColByPos(int &row, int &col, CCPoint pt);
    int getStoneIdByRowCol(int row, int col);
    bool canMove(int moveid, int row, int col, int killed);
    bool canMoveChe(int moveid, int row, int col, int killed);
    bool canMoveMa(int moveid, int row, int col, int killed);
    bool canMoveXiang(int moveid, int row, int col, int killed);
    bool canMoveShi(int moveid, int row, int col, int killed);
    bool canMoveShuai(int moveid, int row, int col, int killed);
    bool canMovePao(int moveid, int row, int col, int killed);
    bool canMoveBing(int moveid, int row, int col, int killed);

    int getStoneCountInLine(int row1, int col1, int row2, int col2);
    void onEnter();
    void onExit();
    void regret();
    void checkGameOver(int killid);
    void gameOverCallback(CCObject*);
    void closeGame(CCObject*);
    void preregret(CCObject*);
    void yesregret(CCObject*);
    void noregret(CCObject*);
    void waitYes(CCObject*);
    void waitNo(CCObject*);
    void initItem();


    void update(float);
    void doSelectStone(int id);
    void doMoveStone(int id, int row, int col);
    void selectStone(int id);
    void moveStone(int id, CCPoint pos);
    void sendSelectStoneToNet();
    void sendMoveStoneToNet(int row,int col);
    void initRegretButton();
    void moveBy(CCPoint pt, CCNode* node);
    void judgeRegret();
    void waitRegretYes();
    void waitRegretNo();
};

#endif

Net.cpp

#include "Net.h"

Net* Net::theOne = NULL;
Net::Net()
{
    _server = INVALID_SOCKET;//初始化为无效的SOCKET
    _client = INVALID_SOCKET;
    _isServer = false;
    _isListen = false;
    _isConnect = false;
}
//作为服务器接口
bool Net::startServer(unsigned short port)
{
    //创建socket
    _server = socket(AF_INET, SOCK_STREAM, 0);//1.用tcp/ip协议  2.用TCP流协议  3.默认为0
    if (_server == INVALID_SOCKET)
    {
        CCLog("Socket create error");
        return false;
    }
    setNonBlock(_server);//非阻塞

    //填信息
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
#ifdef WIN32
    addr.sin_addr.S_un.S_addr = INADDR_ANY;//任何一个IP
#else
    addr.sin_addr.s_addr = INADDR_ANY;
#endif
    //将端口号和程序绑定
    int ret = bind(_server, (struct sockaddr*)&addr, sizeof(addr));
    if (ret == SOCKET_ERROR)
    {
        CCLog("bind socket error");
        closesocket(_server);
        _server = INVALID_SOCKET;
        return false;
    }
    //设置监听
    listen(_server, 10);//允许10个在这里等待监听

    _isServer = true;//是服务端
    _isListen = true;//是处于监听状态
    _isConnect = false;//还未连接

    return true;
}
//服务端 专门用来接收客服端 的函数
bool Net::Accept()
{
    //判断服务端是否准备好
    if (!_isServer || !_isListen || _isConnect)
        return false;

    //struct sockaddr_in peeraddr;//定义一个对方的地址
    //int peerlen = sizeof(peeraddr);//定义对方的地址长度
    //if ((_client = accept(_server, (struct sockaddr*)&peeraddr, &peerlen)) < 0)//从完成连接队列返回第一个连接,如果已完成连接队列为空,则阻塞
    //  return false;

    //接收一个客服端
    _client = accept(_server, NULL, NULL);
    if (_client == INVALID_SOCKET)//看是否成功接收到客服端
        return false;

    setNonBlock(_server);//非阻塞。毕竟是游戏,不能老阻塞在这里,这也是创建这个函数的原因
    return true;
}
//作为客服端接口
bool Net::Connect(unsigned short port, const char* ipaddr)
{
    //创建客服端socket
    _client = socket(AF_INET, SOCK_STREAM, 0);

    //填信息
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
#ifdef WIN32
    addr.sin_addr.S_un.S_addr = inet_addr(ipaddr);//连接上一个IP
#else
    addr.sin_addr.s_addr = inet_addr(ipaddr);
#endif
    //int ret = connect(_client, (struct sockaddr*)&addr, sizeof(addr));//尝试连接
    //if (ret == SOCKET_ERROR)//看是否连接上了
    //{
    //  CCLog("%s", ipaddr);
    //  closesocket(_client);
    //  _client = INVALID_SOCKET;
    //  return false;
    //}
    if (connect(_client, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        CCLog("%s", ipaddr);
        closesocket(_client);
        return false;
    }
    setNonBlock(_client);//放在connect后面,因为connect是阻塞函数,放在上面会导致 connect 失效

    _isConnect = true;//连接上了之后就不能再次连接了,相当于一个服务端只接收一个客服端
    _isServer = false;//把服务器都设置为false
    _isListen = false;
    return true;
}
//客服端和服务器通用的端口
int Net::Recv(void* buf, int len)//需要传的东西,和长度
{
#if 0
    int alreadyRecvLen = 0;//已经接收到的长度
    /*select()机制中提供一fd_set的数据结构,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄,建立联系,建立联系的工作由程序员完成,
    当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一socket或文件发生了可读或可写事件。
    */
    while (1)
    {
        fd_set set;
        FD_ZERO(&set); /*将set清零使集合中不含任何fd*/
        FD_SET(_client, &set);/*将_client加入set集合*/
        struct timeval tv;
        tv.tv_sec = 0;//秒
        tv.tv_usec = 200;//微秒
        //非阻塞式I/O编程。。select只是检测是否可以发送数据,换句话说,如果你不要效率的话,不需要select函数都是可以的。
        //使用Select就可以完成非阻塞。返回值:准备就绪的描述符数,若超时则返回0,若出错则返回-1。
        int ret = select(-1,//本参数忽略,仅起到兼容作用。
            &set,//指向一组等待可读性检查的套接口。(我们只要可读Client即可)
            NULL,//指向一组等待可写性检查的套接口。
            NULL,//指向一组等待错误检查的套接口。
            &tv);//最多等待时间,对阻塞操作则为NULL。

        if (ret <= 0)
            return -1;

        ret = recv(_client, (char*)buf + alreadyRecvLen, len - alreadyRecvLen, 0);//1.指定接收端套接字描述符  4.一般置0。  
        if (ret > 0)//recv函数返回其实际copy的字节数   copy时出错,那么它返回SOCKET_ERROR    
        {
            alreadyRecvLen += ret;
            if (alreadyRecvLen == len)
                return len;
        }
        else if (ret == 0)//网络中断了,那么它返回0。
            return alreadyRecvLen;
        else
            break;
    }
    return -1;
#else
    setNonBlock(_client);
    return recv(_client, (char*)buf, len, 0);//这样是偷懒的行为
#endif
}
// 发送
int Net::Send(char* buf, int len)
{
#if 0
    int alreadySendLen = 0;//已经发送到的长度
    while (1)
    {
        //向一个已连接的套接口发送数据。不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。
        int ret = send(_client, buf + alreadySendLen, len - alreadySendLen, 0);//1.一个用于标识已连接套接口的描述字。
        if (ret > 0)//recv函数返回其实际copy的字节数   
        {
            alreadySendLen += ret;
            if (alreadySendLen == len)
                return len;
        }
        else//copy时出错,网络中断,返回SOCKET_ERROR   
            break;
    }
    return -1;
#else
    setNonBlock(_client);
    return send(_client, buf, len, 0);//这样是偷懒的行为
#endif
}

Net.h

#ifndef __NET_H__
#define __NET_H__

#ifdef WIN32
#include "WinSock2.h"
#pragma comment(lib,"ws2_32.lib")
#else
#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
#include 
#include 
#include //sockaddr_in
#include //close
#include 
#include 
#include 
#include if.h>
#endif

#include "cocos2d.h"
#include "SceneGame.h"

USING_NS_CC;

class Net:public CCLayer
{
protected:
    Net();
    bool _isServer;
    bool _isListen;
    bool _isConnect;    
    SOCKET _server;
    SOCKET _client;
    static Net* theOne;

    void setNonBlock(SOCKET sock)//设置socket为非阻塞
    {
#ifdef WIN32
        u_long arg = 1;
        ioctlsocket(sock, FIONBIO, &arg);//FIONBIO:允许或禁止套接口s的非阻塞模式。argp指向一个无符号长整型。如允许非阻塞模式则非零,如禁止非阻塞模式则为零。
#else
        int flag = fcntl(sock,F_GETFL,0);
        flag  |= O_NONBLOCK;
        fcntl(sock,F_SETFL,flag);
#endif
    }
public:
    // 成员函数后面加cost表示这个函数不能修改成员变量
    // 实质是用这个const修饰隐藏的this指针
    // 常对象只能调用常函数  const Net* p;
    // p->isServer();
    // p->StartServer(); // error:常量对象只能调用常量成员函数
    bool isServer(/* Net* this */) const
    {
        return _isServer;
    }
    SOCKET getServerSocket()
    {
        return _server;
    }
    SOCKET getClientSocket()
    {
        return _client;
    }
    static Net* getInstance()//单例
    {
        if (theOne == NULL)
            return theOne = new Net;
        return theOne;
    }
    bool startServer(unsigned short port);
    bool Accept();
    bool Connect(unsigned short port, const char* ipaddr);
    int Recv(void* buf, int len);
    int Send(char* buf, int len);
};

#endif



Plate.cpp

#include "Plate.h"


bool Plate::init()
{
    CCSprite::initWithFile("background.png");

    setPosition(ccp(0, 0));
    //设置锚点为(0,0)
    setAnchorPoint(ccp(0, 0));
    //缩放
    setScale(winSize.height / getContentSize().height);

    return true;
}



Plate.h

#ifndef __PLATE_H__
#define __PLATE_H__
#include "Common.h"

class Plate:public CCSprite
{
public:
    CREATE_FUNC(Plate);
    bool init();
};

#endif


SceneGame.cpp

#include "SceneGame.h"
#include "Net.h"
#include "Game.h"

int SceneGame::_randomSelf = -1;
int SceneGame::_randomOther = -1;

bool SceneGame::init()
{
    CCLayer::init();

    _menu = CCMenu::create();
    addChild(_menu);

    //开始服务器按钮
    initStartServerButton();

    //连接服务器按钮
    initConnectButton();

    //设置关闭按钮
    CCMenuItem* closeItem = CCMenuItemImage::create("CloseNormal.png", "CloseSelected.png", this, menu_selector(SceneGame::closeGame));
    closeItem->setPosition(ccp(370, -200));
    _menu->addChild(closeItem);

    //开启触摸  用 box 就不需要触摸了
    //setTouchEnabled(true);
    //setTouchMode(kCCTouchesOneByOne);

    //创建随机数
    _randomSelf = CCRANDOM_0_1() * 100;

    return true;
}
//创建服务器开始按钮
void SceneGame::initStartServerButton()
{
    serverItem = CCMenuItemImage::create("zhuji.png", "zhuji2.png");
    _menu->addChild(serverItem);
    serverItem->setTarget(this, menu_selector(SceneGame::startServer));//设置触发函数
    moveBy(ccp(200, 100), serverItem);//设置位置
}
//创建客服端连接按钮
void SceneGame::initConnectButton()
{
    clientItem = CCMenuItemImage::create("kefuji.png","kefuji2.png");
    _menu->addChild(clientItem);
    clientItem->setTarget(this, menu_selector(SceneGame::ConnectServer));//设置触发函数
    moveBy(ccp(200, -100), clientItem);//设置位置
}
//启动服务器
void SceneGame::startServer(CCObject*  sender)
{
    //ConnectServer按钮只能点一次
    serverItem->setEnabled(false);//点进来了,以后再也不能点了
    clientItem->setEnabled(false);

    getHostIP();

    if (Net::getInstance()->startServer(6543))
        scheduleUpdate();//定时器
}
//客服端 连接
void SceneGame::ConnectServer(CCObject* sender)
{
    serverItem->setEnabled(false);//点进来了,以后再也不能点了
    clientItem->setEnabled(false);

    //设置文本  我用 box 代替了这个text
    //_text = CCTextFieldTTF::textFieldWithPlaceHolder("Please input ip", "Arial", 30);
    //addChild(_text);
    //_text->setPosition(ccp(250, 225));

    //创建一个可以编辑的 box
    box = CCEditBox::create(CCSize(250, 50), CCScale9Sprite::create("green_edit.png"));
    addChild(box);
    box->setPosition(ccp(240, 225));
    //增加提示
    box->setPlaceHolder("please input:IP");
    //设置提示字体
    box->setFont("Arial", 30);
    //设置输入的字体颜色
    box->setFontColor(ccc3(0, 0, 255));
    //设置可以输入的长度
    box->setMaxLength(15);
    //弹出软键盘。最后一个参数是,回车键的样子
    box->setReturnType(kKeyboardReturnTypeDone);
    //设置键盘弹出为数字键盘或其他
    box->setInputMode(kEditBoxInputModeAny);

    schedule(schedule_selector(SceneGame::pingIP));
}
//bool SceneGame::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
//{
//  if (_text!=NULL && _text->boundingBox().containsPoint(pTouch->getLocation()))
//      _text->attachWithIME();//调出软键盘
//
//  return false;
//}
void SceneGame::pingIP(float)
{
    /*if (_text == NULL)
        return;
    const char* endIP= _text->getString();*/
    static char _IP[30];

    const char* IP = box->getText();
    if (strlen(IP) >15 || strlen(IP)<8)
        return;

    if (strcmp(_IP, IP) == 0)
        return;
    strcpy(_IP, IP);

    //if (Net::getInstance()->Connect(6543, "127.0.0.1"))//如果连接成功
    if (Net::getInstance()->Connect(6543, IP))//如果连接成功
    {
        if (_randomOther == -1)
        {
            Net::getInstance()->Send((char*)&_randomSelf, 4);//注意,先发,不然会挂死在这里

            //再启动一个定时器,其实没有必要,就当学习一下
            schedule(schedule_selector(SceneGame::RecvRadom));
        }
        unschedule(schedule_selector(SceneGame::pingIP));
        //setTouchEnabled(false);
        box->setVisible(false);
    }
}
//服务端
void SceneGame::update(float)
{
    if (Net::getInstance()->Accept())
    {
        if (_randomOther == -1)//还没有接收到客服端发过来的随机数
        {
            Net::getInstance()->Send((char*)&_randomSelf, 4);

            schedule(schedule_selector(SceneGame::RecvRadom));
        }
        unscheduleUpdate();
        CCLog("Connect OK");
    }
}
void SceneGame::RecvRadom(float)
{
    static int recvLen = 0;
    char* buf = (char*)&_randomOther;//随机数
    int ret = Net::getInstance()->Recv(buf + recvLen, 4 - recvLen);

    if (ret <= 0)
        return;

    recvLen += ret;
    if (recvLen != 4)
        return;

    if (_randomSelf > _randomOther || (_randomSelf == _randomOther && Net::getInstance()->isServer()))
    {
        Game::_redStart = true;
    }
    else
    {
        Game::_redStart = false;
    }
    _game = Game::create();
    addChild(_game);
    unschedule(schedule_selector(SceneGame::RecvRadom));
}

void SceneGame::moveBy(CCPoint pt, CCNode* node)
{
    node->setPosition(pt + node->getPosition());
}

void SceneGame::getHostIP()
{
#ifdef WIN32
    char szHost[256];//存放主机名的缓冲区  
    gethostname(szHost, 256);//取得本地主机名称  
    hostent *pHost = ::gethostbyname(szHost);//通过主机名得到地址信息  

    //一个主机可能有多个网卡、多个IP、下面的代码输出所有的IP地址  
    in_addr addr;
    for (int i = 0;; i++)
    {
        //获得地址(网络字节)  
        char *p = pHost->h_addr_list[i];
        if (NULL == p)
            break;//退出循环  

        //将地址拷贝到in_addr结构体中  
        memcpy(&addr.S_un.S_addr, p, pHost->h_length);

        //将in_addr转换为主机字节序  
        char *IP = inet_ntoa(addr);

        CCLabelTTF* label = CCLabelTTF::create(IP, "Arial", 30);
        addChild(label);
        moveBy(ccp(250, 280 - i * 30), label);//设置位置
    }
#else
    int sockfd;
    struct ifconf ifconf;
    struct ifreq *ifreq;
    char buf[512];//缓冲区
    //初始化ifconf
    ifconf.ifc_len = 512;
    ifconf.ifc_buf = buf;
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0))<0)
        return;
    ioctl(sockfd, SIOCGIFCONF, &ifconf); //获取所有接口信息

    //接下来一个一个的获取IP地址
    ifreq = (struct ifreq*)ifconf.ifc_buf;
    for (int i = (ifconf.ifc_len / sizeof(struct ifreq)); i>0; i--)
    {
        if (ifreq->ifr_flags == AF_INET){ //for ipv4
            char* IP = inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr);
            ifreq++;
            if(!strcmp(IP,"127.0.0.1"))
                continue;
            CCLabelTTF* label = CCLabelTTF::create(IP, "Arial", 30);
            addChild(label);
            moveBy(ccp(250, 280 - i * 30), label);//设置位置
        }
    }
#endif
}
void SceneGame::closeGame(CCObject*)
{
    if (Net::getInstance()->isServer())
#ifdef WIN32
        closesocket(Net::getInstance()->getServerSocket());
#else
        close(Net::getInstance()->getServerSocket());
#endif
    else
#ifdef WIN32
        closesocket(Net::getInstance()->getClientSocket());
#else
        close(Net::getInstance()->getClientSocket());
#endif
    exit(0);
}


SceneGame.h


#ifndef __SceneGame_H__
#define __SceneGame_H__

#include "Game.h"
#include "cocos-ext.h"
USING_NS_CC_EXT;

USING_NS_CC;

class SceneGame :public CCLayer
{
public:
    CREATE_FUNC(SceneGame);
    bool init();

    Game* _game;
    void regret(CCObject*);
    void moveBy(CCPoint pt, CCNode* node);

    void initStartServerButton();
    void initConnectButton();
    void startServer(CCObject*);
    void ConnectServer(CCObject*);
    void update(float);
    void RecvRadom(float);
    void initLabel();
    void closeGame(CCObject*);
    void pingIP(float);
    void getHostIP();
    //virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);

    static int _randomSelf;
    static int _randomOther;

    CCMenu* _menu;
    CCMenuItem* serverItem;
    CCMenuItem* clientItem;
    CCLabelTTF* _label;
    CCTextFieldTTF* _text;
    CCEditBox* box;
};

#endif



SceneStart.cpp

#include "SceneStart.h"
#include "SceneGame.h"

bool SceneStart::init()
{
    CCLayer::init();
    //背景图片
    CCSprite* s = CCSprite::create("desk.png");
    addChild(s);
    s->setPosition(ccp(winSize.width / 2, winSize.height / 2));

    //创建开始按钮
    CCSprite* sprite1 = CCSprite::create("bkg1.png");
    CCSprite* sprite2 = CCSprite::create("bkg2.png");
    addChild(sprite1);
    addChild(sprite2);
    sprite2->setPosition(ccp(winSize.width/4, winSize.height / 2));
    sprite1->setPosition(ccp(winSize.width - winSize.width/4, winSize.height / 2));

    _black = sprite1;
    _red = sprite2;

    //使能触摸,使用单点
    setTouchEnabled(true);
    setTouchMode(kCCTouchesOneByOne);

    //启动帧循环定时器(不要放在 ccTouchBegan 里面,不然有一个Bug就是:点击两次,不仅会加速,而且会启动两次定时器)
    scheduleUpdate();

    return true;
}

bool SceneStart::ccTouchBegan(CCTouch* touch, CCEvent*)
{
    //获取触摸位置
    CCPoint pt = touch->getLocation();
    //判断是否触摸到  黑白按钮
    if (_red->boundingBox().containsPoint(pt))
    {
        _bred = true;
    }
    else if (_black->boundingBox().containsPoint(pt))
    {
        _bred = false;
    }
    else return 0;

    //点中棋子后的效果
    CCMoveTo* move1 = CCMoveTo::create(0.5, ccp(winSize.width / 2 + 10, winSize.height / 2));
    CCMoveTo* move2 = CCMoveTo::create(0.5, ccp(winSize.width / 2, winSize.height / 2));
    CCRotateBy* rotate1 = CCRotateBy::create(2, 360);
    CCRotateBy* rotate2 = CCRotateBy::create(2, -360);
    _red->runAction(CCSpawn::createWithTwoActions(move1,rotate1));
    _black->runAction(CCSpawn::createWithTwoActions(move2, rotate2));

    return true;
}

void SceneStart::update(float dt)
{
    //要对两个棋子进行碰撞检测  _red->getContentSize().width  是图片的宽度
    //if (_red->boundingBox().intersectsRect(_black->boundingBox()))//判断矩形是否接触  intersectsRect
    if (_red->getPositionX() - _black->getPositionX() > 0 )
    {
        Game::_redStart = _bred;
        CCDirector::sharedDirector()->replaceScene(CreateScene(SceneGame::create()));
    }

}

SceneStart.h

#ifndef __SCENESTART_H__
#define __SCENESTART_H__

#include "Common.h"

class SceneStart :public CCLayer
{
private:
    CCSprite* _red;//红精灵
    CCSprite* _black;//黑精灵
    bool _bred;//哪一方走,红为true
public:
    CREATE_FUNC(SceneStart);
    bool init();
    bool ccTouchBegan(CCTouch*, CCEvent*);
    void update(float);//帧循环
};

#endif

Step.cpp

#include "Step.h"

Step* Step::create(int moveid, int rowFrom, int colFrom, int rowTo, int colTo, int killid)
{
    Step* step = new Step;
    step->_moveid = moveid;
    step->_rowFrom = rowFrom;
    step->_colFrom = colFrom;
    step->_rowTo = rowTo;
    step->_colTo = colTo;
    step->_killid = killid;

    step->autorelease();
    return step;
}



Step.h

#ifndef __STEP_H__
#define __STEP_H__

#include "Common.h"

class Step :public CCObject
{
public:
    int _moveid;
    int _rowFrom;
    int _colFrom;
    int _rowTo;
    int _colTo;
    int _killid;

    static Step* create(int moveid, int rowFrom, int colFrom, int rowTo, int colTo, int killid);
};
#endif


Stone.cpp

#include "Stone.h"
#include "Game.h"
CCPoint Stone::_ptOff = ccp(45, 25);//偏移值初始化
float Stone::_myWidth;// = winSize.height / 10;//棋子宽度初始化(千万注意。这里调用winSize会出问题。调用不了winSize,只能在函数里面调用了)

Stone* Stone::create(int id)
{
    Stone* stone = new Stone;
    stone->init(id);
    stone->autorelease();
    return stone;
}
bool Stone::init(int id)
{
    if (Game::_redStart)
    {
        _row = getRowByID(id);
        _col = getColByID(id);
    }
    else
    {
        _row = getRowByID(id);
        _col = getColByID(id);
        _row = 9 - _row;
        _col = 8 - _col;
    }
    _id = id;
    _type = getTypeByID(id);
    _red = id < 16;
    _dead = false;

    const char* bfile[] = { "bche.png", "bma.png", "bxiang.png", "bshi.png", "bjiang.png", "bpao.png", "bzu.png" };
    const char* rfile[] = { "rche.png", "rma.png", "rxiang.png", "rshi.png", "rshuai.png", "rpao.png", "rbing.png" };

    if (_red)
        CCSprite::initWithFile(rfile[_type]);
    else
        CCSprite::initWithFile(bfile[_type]);
    //棋子设置自己的位置
    setPosition(getPos());
    //发现棋子有点大了,改小一点
    setScale(.9f);

    return true;
}
//获取类型。类型只有6种{ CHE, MA, XIANG, SHI, SHUAI, PAO, BING };也就是说数字只有 0 -- 5
STONE_TYPE Stone::getTypeByID(int id)
{
    //每一个ID 对应一个位置,对应一个type
    STONE_TYPE type[32] = { CHE, MA, XIANG, SHI, SHUAI, SHI, XIANG, MA, CHE,
        PAO, PAO,
        BING, BING, BING, BING, BING,
        BING, BING, BING, BING, BING,
        PAO, PAO,
        CHE, MA, XIANG, SHI, SHUAI, SHI, XIANG, MA, CHE };
    return type[id];
}
//判断每个棋子处于哪一行
int Stone::getRowByID(int id)
{
    int row[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
        2, 2,
        3, 3, 3, 3, 3,
        6, 6, 6, 6, 6,
        7, 7,
        9, 9, 9, 9, 9, 9, 9, 9, 9 };
    return row[id];
}
//判断每个棋子处于哪一列
int Stone::getColByID(int id)
{
    int col[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,
        1, 7,
        0, 2, 4, 6, 8,
        0, 2, 4, 6, 8,
        1, 7,
        0, 1, 2, 3, 4, 5, 6, 7, 8 };
    return col[id];
}
//获取现在棋子的位置(世界坐标)
CCPoint Stone::getPos()
{
    float x = _col*_myWidth;
    float y = _row*_myWidth;
    return ccp(x, y) + _ptOff;//暂时不知道为什么不直接给一个特定的值,非得定义静态成员函数,然后让Game来给值???要是后面没用到就删除静态
}
void Stone::move(int row, int col)
{
    _row = row;
    _col = col;
    //this->setPosition(getPos());
    CCPoint pt = getPos();
    this->setPosition(pt);
}


Stone.h

#ifndef __STONE_H__
#define __STONE_H__

#include "Common.h"
enum STONE_TYPE{ CHE, MA, XIANG, SHI, SHUAI, PAO, BING };

class Stone:public CCSprite
{
public:
    int _id;//每个棋子都有一个id
    bool _red;//红色还是黑色
    STONE_TYPE _type;//类型
    int _row;//在棋盘中的行
    int _col;//在棋盘中的列
    bool _dead;//棋子死没死
    static CCPoint _ptOff;
    static float _myWidth;//棋子的宽度
    //创建棋子,和初始化
    static Stone* create(int id);
    bool init(int id);

    void move(int row, int col);
    void kill();
    STONE_TYPE getTypeByID(int id);
    int getRowByID(int);
    int getColByID(int);
    CCPoint getPos();
};

#endif

backMusic.cpp

#include "backMusic.h"
#include "SimpleAudioEngine.h"
bool backMusic::init()
{
    CCLayer::init();

    CCMenu* menu = CCMenu::create();
    addChild(menu);
    itemOn = CCMenuItemImage::create("OnMusic.png", "OffMusic.png");
    itemOff = CCMenuItemImage::create("OffMusic.png", "OnMusic.png");
    itemOn->setTarget(this, menu_selector(backMusic::musicOn));
    itemOff->setTarget(this, menu_selector(backMusic::musicOff));
    menu->addChild(itemOn);
    menu->addChild(itemOff);
    itemOn->setPosition(150, 180);
    itemOff->setPosition(150, 180);
    itemOff->setVisible(false);

    CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("backMusic.mp3", true);
    CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(1.0);
    return true;
}
void backMusic::musicOn(CCObject*)
{
    //CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();
    CocosDenshion::SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
    itemOff->setVisible(true);
    itemOn->setVisible(false);
}
void backMusic::musicOff(CCObject*)
{
    //CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("backMusic.mp3", true);
    CocosDenshion::SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
    itemOn->setVisible(true);
    itemOff->setVisible(false);
}



backMusic.h

#ifndef __backMusic_H__
#define __backMusic_H__

#include "cocos2d.h"
#include "cocos-ext.h"
USING_NS_CC;
USING_NS_CC_EXT;

class backMusic :public CCLayer
{
    CCMenuItem* itemOn;
    CCMenuItem* itemOff;
public:
    CREATE_FUNC(backMusic);
    bool init();
    void musicOff(CCObject*);
    void musicOn(CCObject*);
};

#endif

你可能感兴趣的:(游戏,cocos2d-x,网络,跨平台)