AI勉强能动,还是得改

This commit is contained in:
liuweilhy 2018-12-04 00:22:00 +08:00
parent 41917c1d74
commit 24d897eb69
6 changed files with 92 additions and 53 deletions

View File

@ -34,15 +34,14 @@ void AiThread::run()
mutex.unlock();
ai_ab.setChess(*chess);
ai_ab.alphaBetaPruning(1);
ai_ab.alphaBetaPruning(5);
const char * str = ai_ab.bestMove();
qDebug() << str;
emit command(str);
if (strcmp(str, "error!"))
emit command(str);
// 测试用
qDebug() << "thread running " << iTemp << "ms";
msleep(250);
iTemp += 250;
qDebug() << "thread running " << iTemp++ << "times";
}
}
@ -67,10 +66,10 @@ void AiThread::stop()
return;
mutex.lock();
requestInterruption();
if (waiting_) {
waiting_ = false;
pauseCondition.wakeAll();
}
requestInterruption();
mutex.unlock();
}

View File

@ -92,6 +92,14 @@ void GameController::gameReset()
chess.reset();
chessTemp = chess;
// 停掉线程
ai1.stop();
ai1.quit();
ai1.wait();
ai2.stop();
ai2.quit();
ai2.wait();
// 清除棋子
qDeleteAll(pieceList);
pieceList.clear();
@ -210,7 +218,10 @@ void GameController::setEngine1(bool arg)
if (arg) {
qDebug() << "Player1 is computer.";
ai1.setAi(chess);
ai1.start();
if (ai1.isRunning())
ai1.resume();
else
ai1.start();
}
else {
qDebug() << "Player1 is not computer.";
@ -221,8 +232,18 @@ void GameController::setEngine1(bool arg)
void GameController::setEngine2(bool arg)
{
isEngine2 = arg;
qDebug() << "size of NineChess::ChessData" << sizeof(NineChess::ChessData);
qDebug() << "size of NineChess: " << sizeof(chess);
if (arg) {
qDebug() << "Player2 is computer.";
ai2.setAi(chess);
if (ai2.isRunning())
ai2.resume();
else
ai2.start();
}
else {
qDebug() << "Player2 is not computer.";
ai2.stop();
}
}
void GameController::setAnimation(bool arg)
@ -708,18 +729,20 @@ bool GameController::updateScence(NineChess &chess)
// 如果还未决出胜负
if (chess.whoWin() == NineChess::NOBODY) {
if (chess.whosTurn() == NineChess::PLAYER1) {
ai1.resume();
if(isEngine1)
ai1.resume();
ai2.pause();
}
else {
if(isEngine2)
ai2.resume();
ai1.pause();
ai2.resume();
}
}
// 如果已经决出胜负
else {
ai1.pause();
ai1.pause();
ai1.stop();
ai2.stop();
}
}

View File

@ -633,7 +633,7 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
return false;
}
// 移子
move_ = currentPos << 8 + pos;
move_ = (currentPos << 8) + pos;
player_ms = update(time_p);
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u) %02u:%02u.%03u", currentPos / SEAT, currentPos % SEAT + 1,
c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000);
@ -910,7 +910,7 @@ bool NineChess::place(int pos)
return false;
}
// 移子
move_ = currentPos << 8 + pos;
move_ = (currentPos << 8) + pos;
board[pos] = board[currentPos];
board[currentPos] = '\x00';
currentPos = pos;

View File

@ -111,15 +111,15 @@ public:
enum NineChess::Actions action;
// 玩家1剩余未放置子数
int8_t player1_InHand;
char player1_InHand;
// 玩家2剩余未放置子数
int8_t player2_InHand;
char player2_InHand;
// 玩家1盘面剩余子数
int8_t player1_Remain;
char player1_Remain;
// 玩家1盘面剩余子数
int8_t player2_Remain;
char player2_Remain;
// 尚待去除的子数
int8_t num_NeedRemove;
char num_NeedRemove;
/* 本打算用如下的结构体来表示“三连”
struct Mill {

View File

@ -22,11 +22,17 @@ depth(3) // 默认3层深度
NineChessAi_ab::~NineChessAi_ab()
{
deleteTree(rootNode);
rootNode = nullptr;
}
void NineChessAi_ab::buildChildren(Node *node)
{
char opponent;
// 如果有子节点,则返回,避免重复建立
if (node->children.size())
return;
// 临时变量
char opponent = chessTemp.data.turn == NineChess::PLAYER1 ? 0x20 : 0x10;
// 列出所有合法的下一招
switch (chessTemp.data.action)
{
@ -49,28 +55,29 @@ void NineChessAi_ab::buildChildren(Node *node)
char newPos;
for (int i = NineChess::SEAT; i < (NineChess::RING + 1)*NineChess::SEAT; i++) {
if (!chessTemp.choose(i))
break;
continue;
if ((chessTemp.data.turn == NineChess::PLAYER1 && (chessTemp.data.player1_Remain > chessTemp.rule.numAtLest || !chessTemp.rule.canFly)) ||
(chessTemp.data.turn == NineChess::PLAYER2 && (chessTemp.data.player2_Remain > chessTemp.rule.numAtLest || !chessTemp.rule.canFly))) {
for (int j = 0; j < 4; j++) {
if (newPos == chessTemp.moveTable[i][j]) {
newPos = chessTemp.moveTable[i][j];
if (newPos && !chessTemp.board[newPos]) {
Node * newNode = new Node;
newNode->parent = node;
newNode->value = 0;
newNode->move = i << 8 + newPos;
newNode->move = (i << 8) + newPos;
node->children.push_back(newNode);
}
}
}
else {
for (int j = NineChess::SEAT; j < (NineChess::RING + 1)*NineChess::SEAT; j++) {
if (newPos & chessTemp.board[j])
break;
Node * newNode = new Node;
newNode->parent = node;
newNode->value = 0;
newNode->move = i << 8 + j;
node->children.push_back(newNode);
if (!chessTemp.board[j]) {
Node * newNode = new Node;
newNode->parent = node;
newNode->value = 0;
newNode->move = (i << 8) + j;
node->children.push_back(newNode);
}
}
}
}
@ -78,7 +85,6 @@ void NineChessAi_ab::buildChildren(Node *node)
break;
case NineChess::ACTION_CAPTURE:
opponent = chessTemp.data.turn == NineChess::PLAYER1 ? 0x20 : 0x10;
// 全成三的情况
if (chessTemp.isAllInMills(opponent)) {
for (int i = NineChess::SEAT; i < (NineChess::RING + 1)*NineChess::SEAT; i++) {
@ -94,13 +100,13 @@ void NineChessAi_ab::buildChildren(Node *node)
else {
for (int i = NineChess::SEAT; i < (NineChess::RING + 1)*NineChess::SEAT; i++) {
if (chessTemp.board[i] & opponent) {
if (chessTemp.isInMills(i))
break;
Node * newNode = new Node;
newNode->parent = node;
newNode->value = 0;
newNode->move = -i;
node->children.push_back(newNode);
if (!chessTemp.isInMills(i)) {
Node * newNode = new Node;
newNode->parent = node;
newNode->value = 0;
newNode->move = -i;
node->children.push_back(newNode);
}
}
}
}
@ -139,6 +145,12 @@ void NineChessAi_ab::setChess(const NineChess &chess)
this->chess = chess;
chessTemp = chess;
chessData = &(chessTemp.data);
deleteTree(rootNode);
rootNode = new Node;
rootNode->value = 0;
rootNode->move = 0;
rootNode->parent = nullptr;
requiredQuit = false;
// 生成棋子价值表
for (int j = 0; j < NineChess::SEAT; j++)
@ -191,9 +203,9 @@ int NineChessAi_ab::evaluate(Node *node)
case NineChess::ACTION_CHOOSE:
case NineChess::ACTION_PLACE:
break;
// 如果形成去子状态,每有一个可去的子,算100分
// 如果形成去子状态,每有一个可去的子,算500分
case NineChess::ACTION_CAPTURE:
value += (chessData->turn == NineChess::PLAYER1) ? chessData->num_NeedRemove * 100 : -chessData->num_NeedRemove * 100;
value += (chessData->turn == NineChess::PLAYER1) ? chessData->num_NeedRemove * 500 : -chessData->num_NeedRemove * 500;
break;
default:
break;
@ -240,11 +252,11 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
// 对先手搜索Max
if (chessTemp.whosTurn() == NineChess::PLAYER1) {
for (auto child : node->children) {
hashTable.push_back({chessTemp.data, 0, depth});
dataStack.push(chessTemp.data);
chessTemp.command(child->move);
value = alphaBetaPruning(depth - 1, alpha, beta, child);
chessTemp.data = hashTable.back().data;
hashTable.pop_back();
chessTemp.data = dataStack.top();
dataStack.pop();
// 取最大值
if (value > alpha)
alpha = value;
@ -259,11 +271,11 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
// 对后手搜索Min
else {
for (auto child : node->children) {
hashTable.push_back({ chessTemp.data, 0, depth });
dataStack.push(chessTemp.data);
chessTemp.command(child->move);
value = alphaBetaPruning(depth - 1, alpha, beta, child);
chessTemp.data = hashTable.back().data;
hashTable.pop_back();
chessTemp.data = dataStack.top();
dataStack.pop();
// 取最小值
if (value < beta)
beta = value;
@ -293,7 +305,7 @@ const char *NineChessAi_ab::bestMove()
break;
}
srand((unsigned)time(0));
int i = rand() % 12;
int i = rand() % n;
return move2string(moves[i]);
}
@ -304,16 +316,16 @@ const char *NineChessAi_ab::move2string(int16_t move)
chessTemp.pos2cp(-move, c, p);
sprintf(cmdline, "-(%1u,%1u)", c, p);
}
else if (move & 0x00ff) {
chessTemp.pos2cp(move & 0x00ff, c, p);
sprintf(cmdline, "(%1u,%1u)", c, p);
}
else {
else if (move & 0x7f00) {
int c1, p1;
chessTemp.pos2cp(move >> 8, c1, p1);
chessTemp.pos2cp(move & 0x00ff, c, p);
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u)", c1, p1, c, p);
}
else {
chessTemp.pos2cp(move & 0x007f, c, p);
sprintf(cmdline, "(%1u,%1u)", c, p);
}
return cmdline;
}

View File

@ -9,6 +9,9 @@
#include "ninechess.h"
#include <list>
#include <stack>
using namespace std;
// 注意NineChess类不是线程安全的
// 所以不能在ai类中修改NineChess类的静态成员变量切记
@ -79,6 +82,8 @@ private:
// 根节点
Node * rootNode;
// 局面数据栈
stack<NineChess::ChessData> dataStack;
// 局面数据哈希表
list<struct Hash> hashTable;
// 哈希表最大大小