cocos2d-x3.14中國象棋AI(七)悔棋

悔棋需要用到備忘錄模式。大致思路是:我們先創(chuàng)建一個(gè)Step結(jié)構(gòu)體悬秉,這個(gè)結(jié)構(gòu)體記錄著兩個(gè)棋子的id(一個(gè)是移動(dòng)棋子,一個(gè)是被殺棋子)冰蘑、移動(dòng)前行列和泌,移動(dòng)后行列。然后創(chuàng)建一個(gè)Step鏈表存放所有Step祠肥,在調(diào)用移動(dòng)棋子函數(shù)moveStone時(shí)把當(dāng)前棋子狀態(tài)放進(jìn)_steps中武氓,當(dāng)玩家點(diǎn)擊菜單按鈕的悔棋按鈕時(shí)調(diào)用悔棋按鈕的回調(diào)函數(shù)執(zhí)行悔棋操作。在完成這一篇內(nèi)容后搪柑,下一篇我們就開始寫人工智能聋丝,寫完AI類,簡(jiǎn)單的cocos2dx-3.14的中國象棋也就基本算完成了工碾。

這里把LayerGameMain需要添加的成員變量和成員函數(shù)都列出來

//定義一個(gè)結(jié)構(gòu)體記錄每一步信息
struct Step
{
    int moveid;//移動(dòng)棋子的id
    int killid;//被殺棋子的id
    int rowFrom;//移動(dòng)前的行
    int colFrom;//移動(dòng)前的列
    int rowTo;//移動(dòng)后的行
    int colTo;//移動(dòng)后的列
};

    //悔棋相關(guān)
    list<Step *> _steps;//存放整局棋譜
    void recordStep(int moveid, int killid, int rowFrom, int colFrom, int rowTo, int colTo);//記錄悔棋相關(guān)參數(shù)
    void addCtrlMenu();//添加悔棋等菜單
    void regretItemCallback(Ref *obj);//悔棋菜單回調(diào)函數(shù)
    void regret1Step();//悔棋1步執(zhí)行函數(shù)

這里就不大篇幅地解釋了弱睦,要看懂也很容易,先從moveStone找到addCtrlMenu函數(shù)然后查看一下addCtrlMenu函數(shù)基本就能看懂渊额。這里直接上所有代碼况木。
LayerGameMain.h

#ifndef __LAYERGAMEMAIN_H__
#define __LAYERGAMEMAIN_H__

#include "cocos2d.h"
#include "Plate.h"
#include "Stone.h"
#include <list>
#include <vector>

using namespace std;

/*
cocos2d-x3.14.1版本將大部分類的前綴CC去掉了,不過有部分還是兼容旬迹,如果用舊的命名創(chuàng)建對(duì)應(yīng)的類會(huì)有警告提示/錯(cuò)誤提示
*/

USING_NS_CC;

//定義一個(gè)結(jié)構(gòu)體記錄每一步信息
struct Step
{
    int moveid;//移動(dòng)棋子的id
    int killid;//被殺棋子的id
    int rowFrom;//移動(dòng)前的行
    int colFrom;//移動(dòng)前的列
    int rowTo;//移動(dòng)后的行
    int colTo;//移動(dòng)后的列
};

class LayerGameMain : public Layer
{
public:
    static Scene* createScene();
    virtual bool init();
    CREATE_FUNC(LayerGameMain);

    //添加棋盤和棋子
    void addPlate();//用于在LayerGameMain上添加棋盤層/精靈
    void addStones();//用于在LayerGameMain上添加棋子層/精靈

    //觸摸事件回調(diào)函數(shù)
    bool touchBeganCallBack(Touch *pTouch, Event *pEvent);
    void touchEndedCallBack(Touch *pTouch, Event *pEvent);

    //選中棋子相關(guān)
    Sprite *selectBox;//選中款精靈
    static int _selectedId;//標(biāo)記當(dāng)前選中的棋子id火惊,沒有點(diǎn)中為-1
    bool Screen2Plate(Point &point, int &row, int &col);//循環(huán)棋盤上所有點(diǎn),通過Plate2Screen獲取到棋子中心點(diǎn)奔垦,用引用輸出中心點(diǎn)
    Point Plate2Screen(int row, int col);//獲取棋子中心點(diǎn)返回到世界坐標(biāo)給Screen2Plate
    void selectStone(Touch *pTouch);//選中棋子屹耐,將選中框精靈移動(dòng)到選中的棋子上

    //獲取棋子相關(guān)
    __Array *arrStone;//用于存放棋子
    Stone* getStoneFromArrById(int id);//通過棋子id從arrStone獲取對(duì)應(yīng)棋子
    int getStoneIdFromRowCol(int row, int col);//通過行列獲取棋子id

    //棋子移動(dòng)相關(guān)
    static bool _redTurn;
    void moveStone(Touch *pTouch);
    int getStoneCount(int row1, int col1, int row2, int col2);
    bool canMove(int moveid, int row, int col, int killid);//篩選移動(dòng)規(guī)則
        //moveid為當(dāng)前想要移動(dòng)棋子的id,killid移動(dòng)的目的點(diǎn)(-1為沒有棋子)椿猎,row和col為目的點(diǎn)的行列
        //炮惶岭、兵、將犯眠、車移動(dòng)規(guī)則都有點(diǎn)相似
    bool canMoveChe(int moveid, int row, int col);//車移動(dòng)規(guī)則
    bool canMovePao(int moveid, int row, int col, int killid);//炮移動(dòng)規(guī)則
    bool canMoveBing(int moveid, int row, int col);//兵移動(dòng)規(guī)則
    bool canMoveJiang(int moveid, int row, int col, int killid);//將移動(dòng)規(guī)則
    bool canMoveMa(int moveid, int row, int col);//馬移動(dòng)規(guī)則
    bool canMoveXiang(int moveid, int row, int col);//象移動(dòng)規(guī)則
    bool canMoveShi(int moveid, int row, int col);//士移動(dòng)規(guī)則
    bool isSameColor(int clickedId);//判斷選中棋子顏色是否相同

    //悔棋相關(guān)
    list<Step *> _steps;//存放整局棋譜
    void recordStep(int moveid, int killid, int rowFrom, int colFrom, int rowTo, int colTo);//記錄悔棋相關(guān)參數(shù)
    void addCtrlMenu();//添加悔棋等菜單
    void regretItemCallback(Ref *obj);//悔棋菜單回調(diào)函數(shù)
    void regret1Step();//悔棋1步執(zhí)行函數(shù)
};

#endif // !__LAYERGAMEMAIN_H__

LayerGameMain.cpp

#include "LayerGameMain.h"

using namespace std;

int LayerGameMain::_selectedId = -1;
bool LayerGameMain::_redTurn = true;

Scene* LayerGameMain::createScene()
{
    auto ret = Scene::create();
    auto layer = LayerGameMain::create();
    ret->addChild(layer);

    return ret;
}

bool LayerGameMain::init()
{
    if (!Layer::init())
    {
        return false;
    }
    arrStone = __Array::create();
    arrStone->retain();//計(jì)數(shù)器+1按灶,否則會(huì)被回收
    _steps.clear();//初始化steps鏈表
    selectBox = Sprite::create("selected.png");
    selectBox->setVisible(false);
    selectBox->setLocalZOrder(1000);//設(shè)置顯示優(yōu)先級(jí)
    this->addChild(selectBox);

    this->addPlate();
    this->addStones();

    addCtrlMenu();

    //cocos2d-x3.14.1觸摸事件,創(chuàng)建監(jiān)聽
    EventDispatcher* eventDispatcher = Director::getInstance()->getEventDispatcher();
    auto listener = EventListenerTouchOneByOne::create();
    listener->setEnabled(true);
    listener->setSwallowTouches(true);
    listener->onTouchBegan = CC_CALLBACK_2(LayerGameMain::touchBeganCallBack, this);
    listener->onTouchEnded = CC_CALLBACK_2(LayerGameMain::touchEndedCallBack, this);
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

    return true;
}

void LayerGameMain::addPlate()
{
    Plate *plate = Plate::create();
    
    this->addChild(plate);
}

void LayerGameMain::addStones()
{
    int i = 0;
    Stone *stone;
    for (i = 0; i < 32; i++)
    {
        stone = Stone::create(i);
        arrStone->addObject(stone);//將棋子添加進(jìn)數(shù)組
        this->addChild(stone);
    }
}

Stone* LayerGameMain::getStoneFromArrById(int stoneId)
{
    Stone *ret;
    ret = nullptr;
    if (stoneId > 0)
    {
        ret = (Stone *)arrStone->getObjectAtIndex(stoneId);
    }
    
    return ret;
}

bool LayerGameMain::touchBeganCallBack(Touch *pTouch, Event *pEvent)
{

    return true;
}
void LayerGameMain::touchEndedCallBack(Touch *pTouch, Event *pEvent)
{
    if (_selectedId == -1)
    {
        selectStone(pTouch);
    }
    else
    {
        moveStone(pTouch);
    }
}

bool LayerGameMain::Screen2Plate(Point &point, int &row, int &col)
{
    int distance = Stone::_d/2 * Stone::_d/2;//以半徑作為距離
    for (row = 0; row <= 9; row++)
    {
        for (col = 0; col <= 8; col++)
        {
            Point ptCenter = Plate2Screen(row, col);
            if (distance > ptCenter.getDistanceSq(point))//獲取點(diǎn)距的平方并比較筐咧,如果小于半徑平方則為能選中中心點(diǎn)上的棋子
            {
                return true;
            }
        }
    }

    return false;
}
Point LayerGameMain::Plate2Screen(int row, int col)//該函數(shù)與Stone的getPositionFromPlate類似
{
    Point ret = Point(Stone::_offx + col*Stone::_d, Stone::_offy + row*Stone::_d);
    
    return ret;
}
int LayerGameMain::getStoneIdFromRowCol(int row, int col)
{
    int ret = -1;
    Ref *obj;
    CCARRAY_FOREACH(arrStone,obj)
    {
        Stone *stone = (Stone *)obj;
        if (stone->_row == row && stone->_col == col && !stone->_isdead)//已死去的棋子不能選中
        {
            ret = stone->_id;
            return ret;
        }
    }
    return ret;
}

void LayerGameMain::selectStone(Touch *pTouch)
{
    Point point = pTouch->getLocation();
    int row, col;
    if (!Screen2Plate(point, row, col))//點(diǎn)中范圍不在棋盤上直接返回
    {
        selectBox->setVisible(false);
        return;
    }
    int clickedId = getStoneIdFromRowCol(row, col);
    if (clickedId < 0)//沒選中棋子直接返回
    {
        selectBox->setVisible(false);
        return;
    }
    Stone *clickedStone = getStoneFromArrById(clickedId);
    if (clickedStone->_red != _redTurn)//如果沒有輪到鸯旁,不能選中噪矛、移動(dòng)
    {
        return;
    }
    selectBox->setPosition(Plate2Screen(row, col));
    selectBox->setVisible(true);

    _selectedId = clickedId;//記錄下棋子id
}

void LayerGameMain::moveStone(Touch *pTouch)
{
    Point ptClicked = pTouch->getLocation();
    int row, col;
    if (!Screen2Plate(ptClicked, row, col))//獲取觸點(diǎn)的行列,如果觸點(diǎn)不在棋盤上直接返回
    {
        return;
    }
    int clickedId = getStoneIdFromRowCol(row, col);//獲取觸點(diǎn)上的棋子id铺罢,沒有棋子為-1
    //如果點(diǎn)中相同顏色的棋子艇挨,選中框轉(zhuǎn)移到最后選中的棋子上
    if (clickedId != -1 && isSameColor(clickedId))
    {
        Stone *clickedStone = getStoneFromArrById(clickedId);
        selectBox->setPosition(Plate2Screen(clickedStone->_row, clickedStone->_col));
        _selectedId = clickedId;
        return;
    }

    if (!canMove(_selectedId, row, col, clickedId))
    {
        return;
    }

    Stone *selectedStone = getStoneFromArrById(_selectedId);

    //悔棋相關(guān),移動(dòng)前記錄各項(xiàng)信息
    recordStep(_selectedId, clickedId, selectedStone->_row, selectedStone->_col, row, col);
    
    //移動(dòng)相關(guān)
    Point pt = Plate2Screen(row, col);
    MoveTo *to = MoveTo::create(0.3, pt);
    selectedStone->runAction(to);
    selectedStone->_row = row;
    selectedStone->_col = col;

    if (clickedId != -1)
    {
        Stone *clickedStone = getStoneFromArrById(clickedId);
        clickedStone->setVisible(false);
        clickedStone->_isdead = true;
    }

    //移動(dòng)完畢初始化選中框和選中id
    selectBox->setVisible(false);
    _selectedId = -1;//移動(dòng)完成后初始化為-1
    _redTurn = !_redTurn;
    
}

int LayerGameMain::getStoneCount(int row1, int col1, int row2, int col2)
{
    int ret = 0;//記錄棋子的個(gè)數(shù)
    if (row1 != row2 && col1 != col2) return -1;//行列都不同畏铆,沒有直線
    if (row1 == row2 && col1 == col2) return -1;//行列都相同雷袋,兩點(diǎn)相同,不需要移動(dòng)

    if (row1 == row2)//列相同
    {
        int mincol = col1 < col2 ? col1 : col2;//獲取兩點(diǎn)間較小的行
        int maxcol = col1 > col2 ? col1 : col2;//獲取兩點(diǎn)間較大的行
        for (int col = mincol+1; col < maxcol; col++)//遍歷兩點(diǎn)間所有點(diǎn)
        {
            if (getStoneIdFromRowCol(row1, col) > 0)//如果存在棋子辞居,ret棋子計(jì)數(shù)器+1
            {
                ++ret;
            }
        }
    }
    else if(col1 == col2)
    {
        int minrow = row1 < row2 ? row1 : row2;//獲取兩點(diǎn)間較小的列
        int maxrow = row1 > row2 ? row1 : row2;//獲取兩點(diǎn)間較大的列
        for (int row = minrow + 1; row < maxrow; row++)//遍歷兩點(diǎn)間所有點(diǎn)
        {
            if (getStoneIdFromRowCol(row, col1) > 0)//如果存在棋子,ret棋子計(jì)數(shù)器+1
            {
                ++ret;
            }
        }
    }

    return ret;
}

bool LayerGameMain::canMove(int moveid, int row, int col, int killid)
{
    Stone *stone = getStoneFromArrById(moveid);
    switch (stone->_type)
    {
        case Stone::CHE:
            return canMoveChe(moveid, row, col);
            break;
        case Stone::JIANG:
            return canMoveJiang(moveid, row, col, killid);
            break;
        case Stone::BING:
            return canMoveBing(moveid, row, col);
            break;
        case Stone::PAO:
            return canMovePao(moveid, row, col, killid);
            break;
        case Stone::MA:
            return canMoveMa(moveid, row, col);
            break;
        case Stone::XIANG:
            return canMoveXiang(moveid, row, col);
            break;
        case Stone::SHI:
            return canMoveShi(moveid, row, col);
            break;
        default:
            break;
    }
    return false;
}
bool LayerGameMain::canMoveChe(int moveid, int row, int col)
{
    //車只有在兩點(diǎn)間不存在棋子時(shí)才能走
    Stone *che = getStoneFromArrById(moveid);
    return getStoneCount(che->_row, che->_col, row, col) == 0;
}
bool LayerGameMain::canMovePao(int moveid, int row, int col, int killid)
{
    //炮可以行走只有兩種情況:1.兩點(diǎn)間沒有棋子蛋勺。2.兩點(diǎn)間存在一個(gè)棋子瓦灶,并且目的點(diǎn)也存在棋子。
    Stone *pao = getStoneFromArrById(moveid);
    if (killid == -1)
    {
        return getStoneCount(pao->_row, pao->_col, row, col) == 0;
    }

    return getStoneCount(pao->_row, pao->_col, row, col) == 1;
}
bool LayerGameMain::canMoveBing(int moveid, int row, int col)
{
    //兵行走規(guī)則:1.只能走一格抱完。2.不能回退贼陶。3.過河前只能直走
    Stone *bing = getStoneFromArrById(moveid);
    int dRow = abs(bing->_row - row);
    int dCol = abs(bing->_col - col);
    int d = dRow * 10 + dCol;//此處類似標(biāo)記效果,10等價(jià)于(1巧娱,0)碉怔,1代表可移動(dòng),第一位說明可以左右移動(dòng)一格禁添,第二位說明可以上下移動(dòng)一格
    if (d != 1 && d != 10)
    {
        return false;
    }

    if (bing->_red)
    {
        //兵不能回退
        if (row < bing->_row)
        {
            return false;
        }
        //兵過河前不能左右移動(dòng)
        if (bing->_row <= 4 && bing->_row == row)
        {
            return false;
        }
    }
    else
    {
        if (row > bing->_row)
        {
            return false;
        }
        if (bing->_row >= 5 && bing->_row == row)
        {
            return false;
        }
    }

    return true;
}
bool LayerGameMain::canMoveJiang(int moveid, int row, int col, int killid)
{
    //將規(guī)則:1.一次只能移動(dòng)一格撮胧。2.不能出九宮格。3.將帥照面時(shí)可以直接對(duì)殺老翘。
    Stone *jiang = getStoneFromArrById(moveid);
    //將照面殺
    if (killid != -1)
    {
        Stone *kill = getStoneFromArrById(killid);
        if (kill->_type == Stone::JIANG)
        {
            return canMoveChe(moveid, row, col);//復(fù)用車的移動(dòng)方法芹啥,減少代碼量
        }
    }
    int dRow = abs(jiang->_row - row);
    int dCol = abs(jiang->_col - col);
    int d = dRow * 10 + dCol;//此處類似標(biāo)記效果,10等價(jià)于(1铺峭,0)墓怀,1代表可移動(dòng),第一位說明可以左右移動(dòng)一格卫键,第二位說明可以上下移動(dòng)一格
    if (d != 1 && d != 10)
    {
        return false;
    }
    //將不能左右出九宮
    if (col < 3 || col > 5)
    {
        return false;
    }
    //將不能上下出九宮
    if (jiang->_red)
    {
        if (row > 2 || row <0)
        {
            return false;
        }
    }
    else
    {
        if (row < 7 || row >9)
        {
            return false;
        }
    }
    return true;
}
bool LayerGameMain::canMoveMa(int moveid, int row, int col)
{
    //馬規(guī)則:1.馬走日傀履。2.卡住馬腳不能移動(dòng)。
    Stone *ma = getStoneFromArrById(moveid);
    int dRow = abs(ma->_row - row);
    int dCol = abs(ma->_col - col);
    int d = dRow * 10 + dCol;
    //12為橫日莉炉,21為豎日,類似于(1钓账,2)(2,1)做法
    if (d == 12 || d == 21)
    {
        int cRow, cCol;
        if (d == 12)
        {
            //蹩腳點(diǎn)
            cCol = (col + ma->_col) / 2;
            cRow = ma->_row;
        }
        else
        {
            cCol = ma->_col;
            cRow = (ma->_row + row) / 2;
        }
        //獲取蹩腳點(diǎn)后判斷蹩腳點(diǎn)是否有棋子
        if (getStoneIdFromRowCol(cRow, cCol) == -1)
        {
            return true;
        }
    }
    return false;
}
bool LayerGameMain::canMoveXiang(int moveid, int row, int col)
{
    //象規(guī)則:1.象走田呢袱。2.被卡象眼不能移動(dòng)官扣。3.象不能過河
    Stone *xiang = getStoneFromArrById(moveid);
    int dRow = abs(xiang->_row - row);
    int dCol = abs(xiang->_col - col);
    int d = dRow * 10 + dCol;
    if (d != 22)
    {
        return false;
    }

    int cRow, cCol;
    cRow = (row + xiang->_row) / 2;
    cCol = (col + xiang->_col) / 2;
    if (getStoneIdFromRowCol(cRow, cCol) != -1)//卡主香煙不能移動(dòng)
    {
        return false;
    }

    if (xiang->_red)
    {
        if (row > 4) return false;
    }
    else
    {
        if (row < 5) return false;
    }

    return true;
}
bool LayerGameMain::canMoveShi(int moveid, int row, int col)
{
    //士規(guī)則:1.一次斜著走一格。2.不能出九宮格
    Stone *shi = getStoneFromArrById(moveid);
    int dRow = abs(shi->_row - row);
    int dCol = abs(shi->_col - col);
    int d = dRow * 10 + dCol;
    //只能斜線走
    if (d != 11)
    {
        return false;
    }
    //不能兩側(cè)走出九宮
    if (col<3 || col>5)
    {
        return false;
    }
    //不能上下走出九宮
    if (shi->_red)
    {
        if (row>2 || row<0)
        {
            return false;
        }
    }
    else
    {
        if (row<7 || row>9)
        {
            return false;
        }
    }

    return true;
}

bool LayerGameMain::isSameColor(int clickedId)
{
    Stone *clickedStone = getStoneFromArrById(clickedId);
    Stone *selectedStone = getStoneFromArrById(_selectedId);

    return selectedStone->_red == clickedStone->_red;
}

void LayerGameMain::recordStep(int moveid, int killid, int rowFrom, int colFrom, int rowTo, int colTo)
{
    Step *step = new Step();
    step->moveid = moveid;
    step->killid = killid;
    step->rowFrom = rowFrom;
    step->colFrom = colFrom;
    step->rowTo = rowTo;
    step->colTo = colTo;
    
    _steps.push_back(step);
}

void LayerGameMain::addCtrlMenu()
{
    MenuItemImage *regretItem = MenuItemImage::create("regret.png",
                                                      "regretselected.png",
                                                      this,
                                                      menu_selector(LayerGameMain::regretItemCallback));
    Menu *menu = Menu::create();
    menu->addChild(regretItem);
    this->addChild(menu);
    menu->setPosition(Point(400, 160));
}

void LayerGameMain::regretItemCallback(Ref *obj)
{
    if (_steps.size() <= 1)//只走了一步不能悔棋
    {
        return;
    }
    for (int i = 0; i < 2; i++)//悔棋兩步
    {
        regret1Step();
    }

    return;
}

void LayerGameMain::regret1Step()
{
    Step *step = *_steps.rbegin();
    Stone *stone = getStoneFromArrById(step->moveid);
    stone->_row = step->rowFrom;
    stone->_col = step->colFrom;
    stone->setPosition(Plate2Screen(stone->_row, stone->_col));
    if (step->killid != -1)//如果目標(biāo)點(diǎn)有棋子羞福,將棋子回歸為原來狀態(tài)
    {
        stone = getStoneFromArrById(step->killid);
        stone->_isdead = false;
        stone->setVisible(true);
    }
    _redTurn = !_redTurn;//執(zhí)棋權(quán)歸還給對(duì)方
    delete step;
    _steps.pop_back();

    //防止選中棋子情況下悔棋
    selectBox->setVisible(false);
    _selectedId = -1;

    return;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惕蹄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌卖陵,老刑警劉巖遭顶,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異泪蔫,居然都是意外死亡棒旗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門撩荣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铣揉,“玉大人,你說我怎么就攤上這事餐曹」涔埃” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵台猴,是天一觀的道長(zhǎng)朽合。 經(jīng)常有香客問我,道長(zhǎng)饱狂,這世上最難降的妖魔是什么率触? 我笑而不...
    開封第一講書人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任皆刺,我火速辦了婚禮督禽,結(jié)果婚禮上赵哲,老公的妹妹穿的比我還像新娘。我一直安慰自己衍腥,他們只是感情好磺樱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著婆咸,像睡著了一般竹捉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尚骄,一...
    開封第一講書人閱讀 51,231評(píng)論 1 299
  • 那天块差,我揣著相機(jī)與錄音,去河邊找鬼倔丈。 笑死憨闰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的需五。 我是一名探鬼主播鹉动,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼宏邮!你這毒婦竟也來了泽示?” 一聲冷哼從身側(cè)響起缸血,我...
    開封第一講書人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎械筛,沒想到半個(gè)月后捎泻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡埋哟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年笆豁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赤赊。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闯狱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砍鸠,到底是詐尸還是另有隱情扩氢,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布爷辱,位于F島的核電站,受9級(jí)特大地震影響朦肘,放射性物質(zhì)發(fā)生泄漏饭弓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一媒抠、第九天 我趴在偏房一處隱蔽的房頂上張望弟断。 院中可真熱鬧,春花似錦趴生、人聲如沸阀趴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刘急。三九已至,卻和暖如春浸踩,著一層夾襖步出監(jiān)牢的瞬間叔汁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來泰國打工检碗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留据块,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓折剃,卻偏偏與公主長(zhǎng)得像另假,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子怕犁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 在這里我們需要給Stone類添加多幾個(gè)成員變量以方便后面解決棋子擺放問題边篮。 bool _red 顏色標(biāo)記己莺,判斷當(dāng)前...
    lable閱讀 1,017評(píng)論 1 0
  • 要獲取和選中棋子我們需要要在原來LayerGameMain基礎(chǔ)上添加多三個(gè)成員變量和六個(gè)成員函數(shù)。幾個(gè)函數(shù)和變量間...
    lable閱讀 717評(píng)論 0 0
  • 擺棋看起來可能會(huì)有點(diǎn)煩苟耻,但是棋子亂擺的話后面會(huì)很難管理篇恒,所以還是要沉下心把棋子按一定規(guī)則擺好。 為了擺棋更方便凶杖,我...
    lable閱讀 575評(píng)論 0 0
  • 有做完上一篇的同學(xué)會(huì)發(fā)現(xiàn)胁艰,移動(dòng)棋子存在很多bug,這也是正常智蝠,我們只是寫了移動(dòng)的規(guī)則腾么,具體的細(xì)節(jié)并沒有完善,在這一...
    lable閱讀 512評(píng)論 0 0
  • 我們要通過AI類計(jì)算下一步棋該如何走的話就必需讓AI獲得當(dāng)前棋盤上棋子的局勢(shì)杈湾、輪到誰執(zhí)棋等各種棋盤上的信息解虱,而這種...
    lable閱讀 1,499評(píng)論 1 3