添加slug,改版文章目录命名结构,添加了一个实用的新建文章Shell脚本。
This commit is contained in:
@@ -0,0 +1,387 @@
|
||||
// 亚马逊棋(Amazons)蒙特卡洛AI程序 - 优化版
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
#include <cstring> // 添加memset
|
||||
|
||||
#define GRIDSIZE 8
|
||||
#define OBSTACLE 2
|
||||
#define judge_black 0
|
||||
#define judge_white 1
|
||||
#define grid_black 1
|
||||
#define grid_white -1
|
||||
|
||||
using namespace std;
|
||||
|
||||
// 均衡型参数配置
|
||||
const double CONTROL_FACTOR = 1.0;
|
||||
const double SAFETY_FACTOR = 1.0;
|
||||
const double SURROUND_FACTOR = 10.0;
|
||||
const double CENTER_FACTOR = 1.0;
|
||||
|
||||
// 蒙特卡洛参数 - 减少模拟次数提高速度
|
||||
const int SIMULATIONS_PER_MOVE = 15; // 减少模拟次数
|
||||
const int MAX_SIMULATION_STEPS = 5; // 减少模拟步数
|
||||
const int MCTS_ITERATIONS = 50; // 减少迭代次数
|
||||
|
||||
// 预计算方向向量
|
||||
const int dx[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
|
||||
const int dy[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };
|
||||
|
||||
int currBotColor;
|
||||
int gridInfo[GRIDSIZE][GRIDSIZE] = { 0 };
|
||||
|
||||
// 随机数生成器
|
||||
static mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
|
||||
|
||||
// 走法结构体 - 紧凑表示
|
||||
struct Move {
|
||||
unsigned char x0, y0, x1, y1, x2, y2;
|
||||
|
||||
Move(int x0=0, int y0=0, int x1=0, int y1=0, int x2=0, int y2=0)
|
||||
: x0(x0), y0(y0), x1(x1), y1(y1), x2(x2), y2(y2) {}
|
||||
|
||||
bool isValid() const { return x0 != 255; }
|
||||
};
|
||||
|
||||
// 移动缓存结构
|
||||
struct MoveCache {
|
||||
int pieceX, pieceY;
|
||||
int moveCount;
|
||||
int moves[56]; // 最大可能移动数:8个方向 * 7步 = 56
|
||||
|
||||
MoveCache() : pieceX(-1), pieceY(-1), moveCount(0) {
|
||||
memset(moves, 0, sizeof(moves));
|
||||
}
|
||||
};
|
||||
|
||||
// 预计算中心距离
|
||||
const double centerDistance[GRIDSIZE][GRIDSIZE] = {
|
||||
{9.90, 8.96, 8.06, 7.28, 7.28, 8.06, 8.96, 9.90},
|
||||
{8.96, 7.07, 6.10, 5.39, 5.39, 6.10, 7.07, 8.96},
|
||||
{8.06, 6.10, 4.95, 4.03, 4.03, 4.95, 6.10, 8.06},
|
||||
{7.28, 5.39, 4.03, 2.12, 2.12, 4.03, 5.39, 7.28},
|
||||
{7.28, 5.39, 4.03, 2.12, 2.12, 4.03, 5.39, 7.28},
|
||||
{8.06, 6.10, 4.95, 4.03, 4.03, 4.95, 6.10, 8.06},
|
||||
{8.96, 7.07, 6.10, 5.39, 5.39, 6.10, 7.07, 8.96},
|
||||
{9.90, 8.96, 8.06, 7.28, 7.28, 8.06, 8.96, 9.90}
|
||||
};
|
||||
|
||||
// 全局移动列表缓存
|
||||
vector<Move> allPossibleMoves;
|
||||
vector<MoveCache> moveCache[2]; // 0:黑方, 1:白方
|
||||
|
||||
inline bool inMap(int x, int y) {
|
||||
return (unsigned)x < GRIDSIZE && (unsigned)y < GRIDSIZE;
|
||||
}
|
||||
|
||||
// 快速棋盘复制(使用memcpy)
|
||||
inline void copyBoard(const int src[GRIDSIZE][GRIDSIZE], int dst[GRIDSIZE][GRIDSIZE]) {
|
||||
memcpy(dst, src, sizeof(int) * GRIDSIZE * GRIDSIZE);
|
||||
}
|
||||
|
||||
bool ProcStep(int x0, int y0, int x1, int y1, int x2, int y2, int color, bool check_only) {
|
||||
if (!inMap(x0, y0) || !inMap(x1, y1) || !inMap(x2, y2))
|
||||
return false;
|
||||
if (gridInfo[x0][y0] != color || gridInfo[x1][y1] != 0)
|
||||
return false;
|
||||
if (gridInfo[x2][y2] != 0 && !(x2 == x0 && y2 == y0))
|
||||
return false;
|
||||
|
||||
if (!check_only) {
|
||||
gridInfo[x0][y0] = 0;
|
||||
gridInfo[x1][y1] = color;
|
||||
gridInfo[x2][y2] = OBSTACLE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 计算棋子的所有移动位置(优化版)
|
||||
void calculateMovesFast(const int grid[GRIDSIZE][GRIDSIZE], int x, int y,
|
||||
int moves[], int &count) {
|
||||
count = 0;
|
||||
int color = grid[x][y];
|
||||
if (color == 0) return;
|
||||
|
||||
for (int d = 0; d < 8; ++d) {
|
||||
for (int step = 1; step < GRIDSIZE; ++step) {
|
||||
int xx = x + dx[d] * step;
|
||||
int yy = y + dy[d] * step;
|
||||
|
||||
if (!inMap(xx, yy) || grid[xx][yy] != 0)
|
||||
break;
|
||||
|
||||
moves[count++] = (xx << 3) | yy; // 使用位运算压缩坐标
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 预先计算所有棋子的移动
|
||||
void precalculateMoves(const int grid[GRIDSIZE][GRIDSIZE], int color) {
|
||||
int idx = (color == grid_black) ? 0 : 1;
|
||||
moveCache[idx].clear();
|
||||
|
||||
for (int i = 0; i < GRIDSIZE; ++i) {
|
||||
for (int j = 0; j < GRIDSIZE; ++j) {
|
||||
if (grid[i][j] == color) {
|
||||
MoveCache mc;
|
||||
mc.pieceX = i;
|
||||
mc.pieceY = j;
|
||||
calculateMovesFast(grid, i, j, mc.moves, mc.moveCount);
|
||||
if (mc.moveCount > 0) {
|
||||
moveCache[idx].push_back(mc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取所有可能的走法(使用缓存)
|
||||
vector<Move> getAllPossibleMovesFast(const int grid[GRIDSIZE][GRIDSIZE], int color) {
|
||||
vector<Move> moves;
|
||||
int idx = (color == grid_black) ? 0 : 1;
|
||||
|
||||
// 如果缓存未计算,先计算
|
||||
if (moveCache[idx].empty()) {
|
||||
precalculateMoves(grid, color);
|
||||
}
|
||||
|
||||
// 临时棋盘用于计算箭的位置
|
||||
int tempGrid[GRIDSIZE][GRIDSIZE];
|
||||
|
||||
for (const auto& piece : moveCache[idx]) {
|
||||
for (int m = 0; m < piece.moveCount; ++m) {
|
||||
int movePos = piece.moves[m];
|
||||
int moveX = movePos >> 3;
|
||||
int moveY = movePos & 7;
|
||||
|
||||
// 创建临时棋盘
|
||||
copyBoard(grid, tempGrid);
|
||||
tempGrid[moveX][moveY] = color;
|
||||
tempGrid[piece.pieceX][piece.pieceY] = 0;
|
||||
|
||||
// 计算箭的位置
|
||||
int arrowMoves[56];
|
||||
int arrowCount = 0;
|
||||
calculateMovesFast(tempGrid, moveX, moveY, arrowMoves, arrowCount);
|
||||
|
||||
for (int a = 0; a < arrowCount; ++a) {
|
||||
int arrowPos = arrowMoves[a];
|
||||
int arrowX = arrowPos >> 3;
|
||||
int arrowY = arrowPos & 7;
|
||||
moves.push_back(Move(piece.pieceX, piece.pieceY, moveX, moveY, arrowX, arrowY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
|
||||
// 快速局面评估(简化版)
|
||||
double evaluateBoardFast(const int grid[GRIDSIZE][GRIDSIZE], int originalColor) {
|
||||
double score = 0.0;
|
||||
|
||||
// 快速评估:只计算移动能力和中心控制
|
||||
for (int i = 0; i < GRIDSIZE; ++i) {
|
||||
for (int j = 0; j < GRIDSIZE; ++j) {
|
||||
int piece = grid[i][j];
|
||||
if (piece != 0 && piece != OBSTACLE) {
|
||||
// 中心控制
|
||||
double centerValue = (10.0 - centerDistance[i][j]) * CENTER_FACTOR;
|
||||
|
||||
// 移动能力(简化计算)
|
||||
int moves[56];
|
||||
int moveCount = 0;
|
||||
calculateMovesFast(grid, i, j, moves, moveCount);
|
||||
double mobility = moveCount * CONTROL_FACTOR;
|
||||
|
||||
if (piece == originalColor) {
|
||||
score += centerValue + mobility;
|
||||
} else {
|
||||
score -= centerValue + mobility;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 归一化
|
||||
return tanh(score / 50.0);
|
||||
}
|
||||
|
||||
// 优化的随机游戏模拟
|
||||
double simulateRandomGameFast(Move move, const int originalGrid[GRIDSIZE][GRIDSIZE], int color) {
|
||||
// 使用栈上数组,避免动态分配
|
||||
int simGrid[GRIDSIZE][GRIDSIZE];
|
||||
copyBoard(originalGrid, simGrid);
|
||||
|
||||
// 执行第一步
|
||||
simGrid[move.x1][move.y1] = color;
|
||||
simGrid[move.x0][move.y0] = 0;
|
||||
simGrid[move.x2][move.y2] = OBSTACLE;
|
||||
|
||||
int currentColor = -color;
|
||||
int steps = 0;
|
||||
|
||||
// 快速随机模拟
|
||||
while (steps < MAX_SIMULATION_STEPS) {
|
||||
// 获取当前玩家的移动
|
||||
int moves[56];
|
||||
int moveCount = 0;
|
||||
bool hasMove = false;
|
||||
|
||||
// 找到一个可以移动的棋子
|
||||
for (int i = 0; i < GRIDSIZE && !hasMove; ++i) {
|
||||
for (int j = 0; j < GRIDSIZE && !hasMove; ++j) {
|
||||
if (simGrid[i][j] == currentColor) {
|
||||
calculateMovesFast(simGrid, i, j, moves, moveCount);
|
||||
if (moveCount > 0) {
|
||||
// 随机选择一个移动
|
||||
int moveIdx = rng() % moveCount;
|
||||
int movePos = moves[moveIdx];
|
||||
int moveX = movePos >> 3;
|
||||
int moveY = movePos & 7;
|
||||
|
||||
// 计算箭的位置
|
||||
int arrowMoves[56];
|
||||
int arrowCount = 0;
|
||||
|
||||
// 临时棋盘计算箭
|
||||
int tempGrid[GRIDSIZE][GRIDSIZE];
|
||||
copyBoard(simGrid, tempGrid);
|
||||
tempGrid[moveX][moveY] = currentColor;
|
||||
tempGrid[i][j] = 0;
|
||||
calculateMovesFast(tempGrid, moveX, moveY, arrowMoves, arrowCount);
|
||||
|
||||
if (arrowCount > 0) {
|
||||
int arrowIdx = rng() % arrowCount;
|
||||
int arrowPos = arrowMoves[arrowIdx];
|
||||
int arrowX = arrowPos >> 3;
|
||||
int arrowY = arrowPos & 7;
|
||||
|
||||
// 执行移动
|
||||
simGrid[moveX][moveY] = currentColor;
|
||||
simGrid[i][j] = 0;
|
||||
simGrid[arrowX][arrowY] = OBSTACLE;
|
||||
hasMove = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasMove) break;
|
||||
|
||||
currentColor = -currentColor;
|
||||
steps++;
|
||||
}
|
||||
|
||||
return evaluateBoardFast(simGrid, color);
|
||||
}
|
||||
|
||||
// 主决策函数
|
||||
Move findBestMoveWithMonteCarlo() {
|
||||
// 清空缓存
|
||||
moveCache[0].clear();
|
||||
moveCache[1].clear();
|
||||
|
||||
// 获取所有可能走法
|
||||
vector<Move> moves = getAllPossibleMovesFast(gridInfo, currBotColor);
|
||||
|
||||
if (moves.empty()) {
|
||||
return Move(255, 255, 255, 255, 255, 255);
|
||||
}
|
||||
|
||||
// 如果走法很少,直接返回第一个
|
||||
if (moves.size() == 1) {
|
||||
return moves[0];
|
||||
}
|
||||
|
||||
Move bestMove = moves[0];
|
||||
double bestScore = -1e9;
|
||||
|
||||
// 限制检查的走法数量
|
||||
int checkCount = min((int)moves.size(), 30);
|
||||
|
||||
// 均匀采样,而不是检查所有走法
|
||||
vector<int> indices(moves.size());
|
||||
for (int i = 0; i < moves.size(); ++i) indices[i] = i;
|
||||
shuffle(indices.begin(), indices.end(), rng);
|
||||
|
||||
for (int i = 0; i < checkCount; ++i) {
|
||||
int idx = indices[i];
|
||||
double totalScore = 0.0;
|
||||
|
||||
// 减少模拟次数
|
||||
int sims = (i < 10) ? SIMULATIONS_PER_MOVE : (SIMULATIONS_PER_MOVE / 2);
|
||||
|
||||
for (int sim = 0; sim < sims; ++sim) {
|
||||
totalScore += simulateRandomGameFast(moves[idx], gridInfo, currBotColor);
|
||||
}
|
||||
|
||||
double avgScore = totalScore / sims;
|
||||
|
||||
if (avgScore > bestScore) {
|
||||
bestScore = avgScore;
|
||||
bestMove = moves[idx];
|
||||
}
|
||||
}
|
||||
|
||||
return bestMove;
|
||||
}
|
||||
|
||||
int main() {
|
||||
ios::sync_with_stdio(false);
|
||||
cin.tie(0);
|
||||
|
||||
// 快速初始化棋盘
|
||||
memset(gridInfo, 0, sizeof(gridInfo));
|
||||
gridInfo[0][2] = gridInfo[2][0] = gridInfo[5][0] = gridInfo[7][2] = grid_black;
|
||||
gridInfo[0][5] = gridInfo[2][7] = gridInfo[5][7] = gridInfo[7][5] = grid_white;
|
||||
|
||||
int turnID;
|
||||
cin >> turnID;
|
||||
|
||||
currBotColor = grid_white;
|
||||
for (int i = 0; i < turnID; i++) {
|
||||
int x0, y0, x1, y1, x2, y2;
|
||||
cin >> x0 >> y0 >> x1 >> y1 >> x2 >> y2;
|
||||
|
||||
if (x0 == -1) {
|
||||
currBotColor = grid_black;
|
||||
} else if (x0 >= 0) {
|
||||
ProcStep(x0, y0, x1, y1, x2, y2, -currBotColor, false);
|
||||
}
|
||||
|
||||
if (i < turnID - 1) {
|
||||
cin >> x0 >> y0 >> x1 >> y1 >> x2 >> y2;
|
||||
if (x0 >= 0) {
|
||||
ProcStep(x0, y0, x1, y1, x2, y2, currBotColor, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 决策
|
||||
Move bestMove = findBestMoveWithMonteCarlo();
|
||||
|
||||
// 如果无效,使用简单策略
|
||||
if (!bestMove.isValid()) {
|
||||
// 简单策略:找到第一个合法走法
|
||||
vector<Move> moves = getAllPossibleMovesFast(gridInfo, currBotColor);
|
||||
if (!moves.empty()) {
|
||||
bestMove = moves[0];
|
||||
}
|
||||
}
|
||||
|
||||
cout << (int)bestMove.x0 << ' ' << (int)bestMove.y0 << ' '
|
||||
<< (int)bestMove.x1 << ' ' << (int)bestMove.y1 << ' '
|
||||
<< (int)bestMove.x2 << ' ' << (int)bestMove.y2 << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user