// 黑白棋(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;
}
黑白棋样例程序及注释解析(无决策算法)
最新推荐文章于 2019-05-22 14:32:50 发布