Renju
来自Botzone Wiki
Renju 又称连珠,是一种五子棋的变种。
游戏规则
- 与五子棋基本规则相同,棋盘大小为15*15。
- 在黑棋第三手后(棋盘上有两黑一白三个棋子),白棋可以选择是否换手。如果换手,则黑棋变白白棋变黑,换手后下一手由黑棋下。
游戏交互方式
本游戏与Botzone上其他游戏一样,使用相同的交互方式:Bot#交互
具体交互内容
每回合Bot收到的request不是字符串,而是一个JSON对象,表示对方落子位置。格式如下:
{
"x": Number, // 横坐标
"y": Number // 纵坐标
}
Bot所需要输出的response也是格式相同的JSON对象,表示自己要落子的位置。
如果是黑方的第一回合,则 request 为 {"x": -1, "y": -1}
。
如果是白方的第三回合,则 response 可以为 {"x": -1, "y": -1}
,代表换手。其他情况下 response 的 x, y 必须在棋盘中。
游戏样例程序
Javascript
这是 Javascript 版本,随机选择棋盘上的一个空白点落子。如果能换手的话,总是换手。
var SIZE = 15; // 棋盘大小 15*15
var Grid = new Array(SIZE);
for (var i = Grid.length - 1; i >= 0; i--) {
Grid[i] = new Array(SIZE);
}
var inGrid = function(x, y) {
return x >= 0 && x < SIZE && y >= 0 && y < SIZE;
};
var reverseGrid = function() { // 因为我们没记录 Grid 上棋子的颜色,所以其实是没用的。
for (var i = 0; i < SIZE; i++) {
for (var j = 0; j < SIZE; j++) {
if (Grid[i][j] !== undefined) {
Grid[i][j] = +!Grid[i][j];
}
}
}
};
var placeAt = function(i, x, y) {
if (inGrid(x, y) && Grid[x][y] === undefined) {
Grid[x][y] = 1;
return true;
}
if (i > 0) { // 简单认为非第一手的错误输入都是换手标志
reverseGrid();
return true;
}
return false;
};
var randomAvailablePosition = function() {
var result = [];
for (var i = 0; i < SIZE; i++) {
for (var j = 0; j < SIZE; j++) {
if (Grid[i][j] === undefined) {
result.push({ x: i, y: j });
}
}
}
return result[Math.floor(Math.random()*result.length)];
};
process.stdin.resume();
process.stdin.setEncoding('utf8');
var fullInput = "";
process.stdin.on('data', function(chunk) {
fullInput += chunk;
});
process.stdin.on('end', function() {
// 解析读入的JSON
var input = JSON.parse(fullInput);
var output;
var isWhite = inGrid(input.requests[0].x, input.requests[0].y); // 白棋后手
for (i = input.requests.length - 1; i >= 0; i--) {
placeAt(i, input.requests[i].x, input.requests[i].y);
}
for (i = input.responses.length - 1; i >= 0; i--) {
placeAt(i, input.responses[i].x, input.responses[i].y);
}
if (isWhite && input.requests.length === 2) { // 可以换手
output = {
response: { x: -1, y: -1 } // 总是换手
}
} else {
output = {
response: randomAvailablePosition()
};
}
console.log(JSON.stringify(output));
});
Java
import java.util.*;
import org.json.simple.JSONValue;
class Main {
static class Grid {
public static final int SIZE = 15;
private int[][] grid = new int[SIZE][SIZE];
public void placeAt(int x, int y) {
if (x >= 0 && y >= 0) {
grid[x][y] = 1;
}
}
public void reverse() {
// 因为我们没记录 Grid 上棋子的颜色,所以其实是没用的。
}
public Map randomAvailablePosition() {
List xList = new LinkedList();
List yList = new LinkedList();
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (grid[i][j] == 0) {
xList.add(i);
yList.add(j);
}
}
}
int rand = (int) (Math.random()*xList.size());
return generateResponse((int) xList.get(rand), (int) yList.get(rand));
}
public Map generateResponse(int x, int y) {
Map map = new HashMap();
map.put("x", x);
map.put("y", y);
return map;
}
}
public static void main(String[] args) {
String inputFull = new Scanner(System.in).nextLine();
Map<String, List> input = (Map) JSONValue.parse(inputFull);
Grid grid = new Grid();
List<Map> requests = input.get("requests");
List<Map> responses = input.get("responses");
for (Map<String, Long> rec : requests) {
grid.placeAt(rec.get("x").intValue(), rec.get("y").intValue());
}
for (Map<String, Long> rec : responses) {
grid.placeAt(rec.get("x").intValue(), rec.get("y").intValue());
}
Map output = new HashMap();
if (((Long) requests.get(0).get("x")).intValue() > 0 && requests.size() == 2) {
output.put("response", grid.generateResponse(-1, -1));
} else {
output.put("response", grid.randomAvailablePosition());
}
System.out.print(JSONValue.toJSONString(output));
}
}
C++
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include "jsoncpp/json.h" // C++编译时默认包含此库
using namespace std;
const int SIZE = 15;
bool Grid[SIZE][SIZE];
void placeAt(int x, int y)
{
if (x >= 0 && y >= 0) {
Grid[x][y] = true;
}
}
Json::Value randomAvailablePosition()
{
vector<int> xs, ys;
for (int i = 0; i < SIZE; ++i) {
for (int j = 0; j < SIZE; ++j) {
if (Grid[i][j] == false) {
xs.push_back(i);
ys.push_back(j);
}
}
}
srand(time(0));
int rand_pos = rand() % xs.size();
Json::Value action;
action["x"] = xs[rand_pos];
action["y"] = ys[rand_pos];
return action;
}
int main()
{
// 读入JSON
string str;
getline(cin, str);
Json::Reader reader;
Json::Value input;
reader.parse(str, input);
// 分析自己收到的输入和自己过往的输出,并恢复状态
int turnID = input["responses"].size();
for (int i = 0; i < turnID; i++) {
placeAt(input["requests"][i]["x"].asInt(), input["requests"][i]["y"].asInt());
placeAt(input["responses"][i]["x"].asInt(), input["responses"][i]["y"].asInt());
}
placeAt(input["requests"][turnID]["x"].asInt(), input["requests"][turnID]["y"].asInt());
// 输出决策JSON
Json::Value ret;
int i = 0;
if (input["requests"][i]["x"].asInt() > 0 && turnID == 1) {
Json::Value action;
action["x"] = -1;
action["y"] = -1;
ret["response"] = action;
} else {
ret["response"] = randomAvailablePosition();
}
Json::FastWriter writer;
cout << writer.write(ret) << endl;
return 0;
}