黑白棋样例程序及注释解析(无决策算法)

来源:互联网 发布:安庆网络问政平台新版 编辑:程序博客网 时间:2024/05/19 03:46
// 黑白棋(Reversi)样例程序 // 随机策略 // 作者:zhouhy // 游戏信息:http://www.botzone.org/games#Reversi #include <iostream> #include <string> #include <cstdlib> #include <ctime> #include "jsoncpp/json.h" // C++编译时默认包含此库 using namespace std; int currBotColor; // 我所执子颜色(1为黑,-1为白,棋盘状态亦同) int gridInfo[8][8] = { 0 }; // 先x后y,记录棋盘状态 int blackPieceCount = 2, whitePieceCount = 2; // 向Direction方向改动坐标,并返回是否越界 这个是八个方向上的   inline bool MoveStep(int &x, int &y, int Direction) //注意:这里调用一次move,x,y也相应移动了一步 {    if (Direction == 0 || Direction == 6 || Direction == 7)        x++;    if (Direction == 0 || Direction == 1 || Direction == 2)        y++;    if (Direction == 2 || Direction == 3 || Direction == 4)        x--;    if (Direction == 4 || Direction == 5 || Direction == 6)        y--;    if (x < 0 || x > 7 || y < 0 || y > 7)        return false;    return true; } // 在坐标处落子,检查是否合法(八个方向有一个方向是可以夹住对方子的)或模拟落子 bool ProcStep(int xPos, int yPos, int color, bool checkOnly = false) {    int effectivePoints[8][2];    int dir, x, y, currCount;    bool isValidMove = false;   //是否是合法的移动    if (gridInfo[xPos][yPos] != 0)   //如果棋盘上这个位置有子,下面都是这个地方没字的情况        return false;                 //返回不合法    for (dir = 0; dir < 8; dir++)   // 这里遍历八个方向,每次搞一个方向 搞一圈下来把所有方向上面的夹住的对方的棋子保存在effectivePoints上    {        x = xPos;        y = yPos;        currCount = 0;        while (1)        {            if (!MoveStep(x, y, dir))//朝着一个方向上移动判断是否超界,边界就break, 每while一次都会往dir方向前进一步            {                currCount = 0;                break;            }            if (gridInfo[x][y] == -color)  //移动一下还是对方棋子那就对方棋子个数加1,把对方的个数和位置记下来保存到effectivePoints数组上            {                currCount++; //数字就加一                effectivePoints[currCount][0] = x;                effectivePoints[currCount][1] = y;            }            else if (gridInfo[x][y] == 0) //没有棋子            {                currCount = 0;                break;            }            else     //这种情况指的是这个棋子是我方,那么计数器就不置0了,直接跳出,这时已经是我方棋子夹住了currCount多的敌方棋子            {                break;            }        }        if (currCount != 0)        {            isValidMove = true;  //如果八个方向只要有一个方向使对方子可以反转的,这步棋就是可以的            if (checkOnly)    //如果只是检查这步是否合法就返回合法,下面的不进行反转操作                return true;            if (color == 1) //如果是黑棋                         {                blackPieceCount += currCount;                whitePieceCount -= currCount;   //改变黑白棋子个数            }            else  //白棋            {                whitePieceCount += currCount;                blackPieceCount -= currCount;            }            while (currCount > 0)  //这里把加在中间的对方棋子翻转过去            {                x = effectivePoints[currCount][0];                y = effectivePoints[currCount][1];                gridInfo[x][y] *= -1;                 currCount--;            }        }    }    if (isValidMove) //如果这个地方是合法的坐标,那么下面就对这盘棋的黑白进行改变+1    {        gridInfo[xPos][yPos] = color;        if (color == 1)            blackPieceCount++;        else            whitePieceCount++;        return true;    }    else        return false; } // 检查color方有无合法棋步 bool CheckIfHasValidMove(int color) {    int x, y;    for (y = 0; y < 8; y++)    for (x = 0; x < 8; x++)    if (ProcStep(x, y, color, true))  // 坐标处的落子,检查是否合法        return true;              //都合法才返回合法真    return false;                 //有一个不合法就返回不合法假 } int main() {    int x, y;    // 初始化棋盘    gridInfo[3][4] = gridInfo[4][3] = 1;  //|白|黑|    gridInfo[3][3] = gridInfo[4][4] = -1; //|黑|白|    // 读入JSON    string str;    getline(cin, str);    Json::Reader reader;    Json::Value input; //三维,保存n个回合双方的棋子坐标    reader.parse(str, input);    // 分析自己收到的输入和自己过往的输出,并恢复状态    int turnID = input["responses"].size();//大概就是第几回合的意思    currBotColor = input["requests"][(Json::Value::UInt) 0]["x"].asInt() < 0 ? 1 : -1; // 第一回合收到坐标是-1, -1,说明我是黑方    for (int i = 0; i < turnID; i++)  //以往回合的落子信息已经保存到全局变量gridInfo里面了    {        // 根据这些输入输出逐渐恢复状态到当前回合        x = input["requests"][i]["x"].asInt();        y = input["requests"][i]["y"].asInt();        if (x >= 0)            ProcStep(x, y, -currBotColor); // 模拟对方落子        x = input["responses"][i]["x"].asInt();        y = input["responses"][i]["y"].asInt();        if (x >= 0)            ProcStep(x, y, currBotColor); // 模拟己方落子    }    // 看看自己本回合输入    x = input["requests"][turnID]["x"].asInt();    y = input["requests"][turnID]["y"].asInt();    if (x >= 0)        ProcStep(x, y, -currBotColor); // 模拟对方落子    // 找出合法落子点    int possiblePos[64][2], posCount = 0, choice;    for (y = 0; y < 8; y++)      for (x = 0; x < 8; x++)  //遍历棋盘找出可以落子的点,        if (ProcStep(x, y, currBotColor, true))        {            possiblePos[posCount][0] = x;            possiblePos[posCount++][1] = y;        }    // 做出决策(你只需修改以下部分)    int resultX, resultY;    if (posCount > 0)    {        srand(time(0));        choice = rand() % posCount;        resultX = possiblePos[choice][0];        resultY = possiblePos[choice][1];    }    else    {        resultX = -1;        resultY = -1;    }    // 决策结束,输出结果(你只需修改以上部分)    Json::Value ret;    ret["response"]["x"] = resultX;    ret["response"]["y"] = resultY;    Json::FastWriter writer;    cout << writer.write(ret) << endl; //这是电脑上的决定    return 0; }
原创粉丝点击