1 Star 0 Fork 0

Warspite / a-simple-gobang

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
AI.h 12.04 KB
一键复制 编辑 原始数据 按行查看 历史
Warspite 提交于 2023-08-03 17:50 . 添加项目文件。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
#pragma once
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cassert>
using namespace std;
int abss(int a) {
if (a < 0) return -a;
else return a;
}
long long getmin(int a, int b) {
if (a < b) return a;
else return b;
}
long long getmax(int a, int b) {
if (a > b) return a;
else return b;
}
//博弈树返回内容
struct node
{
//阿尔法
long long a;
//贝塔
long long b;
//节点值
long long point;
node() {
a = point = INT_MIN;
b = INT_MAX;
}
};
//棋盘大小
const int clen = 15;
class thinker {
private:
//电脑棋子颜色
const int AIcolor = 1;
//玩家棋子颜色
const int Player = 2;
//棋盘
int cboard[clen][clen];
//越界判断
bool yuejie(int x, int y)const;
//五元组情况
int state[3][clen][clen][4];
//五元组不同情况的分数
const long long cpoint[6] = { 0,0,2,1000,100000,INT_MAX };
//更新五元组
bool input(int x, int y, int who);
bool remove(int x, int y);
//不同情况的棋子排列
int AIstate[6];
int Manstate[6];
//判断该五元组是否已经无效
bool dead[clen][clen][4];
//记录无效个数
int deadnum = 0;
//获得局面分数
long long getpoint();
//电脑落子位置
int nx, ny;
//搜索深度
const int tdeep = 3;
//递归过程
node AIstep(int deep, const int rpoint, node root);
node Manstep(int deep, const int rpoint, node root);
//博弈树入口
void think();
public:
thinker() {
memset(cboard, 0, sizeof(cboard));
memset(state, 0, sizeof(state));
memset(AIstate, 0, sizeof(AIstate));
memset(Manstate, 0, sizeof(Manstate));
memset(dead, false, sizeof(dead));
}
void clear() {
memset(cboard, 0, sizeof(cboard));
memset(state, 0, sizeof(state));
memset(AIstate, 0, sizeof(AIstate));
memset(Manstate, 0, sizeof(Manstate));
memset(dead, false, sizeof(dead));
}
//用户输入
void playerinp(int x, int y) {
input(x,y, Player);
}
//获得电脑输入
void getAIinp(int& x, int& y) {
think();
x = nx;
y = ny;
input(x, y, AIcolor);
}
}AIplayer;
void thinker::think() {
node top;
top.a--;
const long long root = getpoint();
long long noww;
for (int i = 0; i < clen; i++) {
for (int j = 0; j < clen; j++) {
if (input(i, j, AIcolor)) {
noww = getpoint();
if (noww != root) {
node next = Manstep(tdeep, noww, top);
if (top.a < next.point) {
nx = i;
ny = j;
top.a = next.point;
top.point = next.point;
}
}
remove(i, j);
}
}
}
}
node thinker::Manstep(int deep, const int rpoint, node root) {
if (deep == 0) {
root.point = rpoint;
root.a = root.point;
root.b = root.point;
return root;
}
//游戏已经结束,一方获胜了
if (rpoint == INT_MAX || rpoint == INT_MIN) {
root.point = rpoint;
root.a = root.point;
root.b = root.point;
return root;
}
//当前局面分
long long tpoint;
//操作者
int op = Player;
for (int i = 0; i < clen; i++) {
for (int j = 0; j < clen; j++) {
if (input(i, j, op)) {
tpoint = getpoint();
if (tpoint != rpoint) {
node temp = AIstep(deep - 1, tpoint, root);
int tempmin = getmin(tpoint, getmin(temp.a, temp.b));
if (tempmin < root.b) {
root.b = tempmin;
root.point = tempmin;
}
}
remove(i, j);
}
if (getpoint() != rpoint) {
cout << "Manstep error:" << deep << " " << getpoint() << "\n";
exit(100);
}
if (root.a >= root.b) break;
}
if (root.a >= root.b) break;
}
return root;
}
node thinker::AIstep(int deep, const int rpoint, node root) {
if (deep == 0) {
root.point = rpoint;
root.a = root.point;
root.b = root.point;
return root;
}
//游戏已经结束,一方获胜了
if (rpoint == INT_MAX || rpoint == INT_MIN) {
root.point = rpoint;
root.a = root.point;
root.b = root.point;
return root;
}
//当前局面分
long long tpoint;
//操作者
int op = AIcolor;
for (int i = 0; i < clen; i++) {
for (int j = 0; j < clen; j++) {
if (input(i, j, op)) {
tpoint = getpoint();
if (tpoint != rpoint) {
node temp = Manstep(deep - 1, tpoint, root);
int tempmax = getmax(tpoint, getmax(temp.a, temp.b));
if (tempmax > root.a) {
root.a = tempmax;
root.point = tempmax;
}
}
remove(i, j);
}
if (getpoint() != rpoint) {
cout << "AIstep error:\n";
exit(120);
}
if (root.a >= root.b) break;
}
if (root.a >= root.b) break;
}
return root;
}
bool thinker::yuejie(int x, int y)const
{
if (x < 0 || x>=clen || y < 0 || y>=clen) return true;
return false;
}
bool thinker::input(int x, int y, int who) {
if (cboard[x][y] != 0) {
return false;
}
cboard[x][y] = who;
int other = who % 2 + 1;
for (int i = 0; i < 5; i++) {
if (!yuejie(x - i, y)) {
//如果该点在该方向上没有被标记为死点 并且 该点在该方向上有对方的棋子
if (!dead[x - i][y][0] && state[other][x - i][y][0] != 0) {
//标记为死点
dead[x - i][y][0] = true;
deadnum++;
//维护计分数组, 将对方的记录清除
if (other == AIcolor) {
AIstate[state[other][x - i][y][0]]--;
}
else {
Manstate[state[other][x - i][y][0]]--;
}
//更新五元组状态
state[who][x - i][y][0]++;
}
else if (!dead[x - i][y][0]) {
//不是死点,维护计分数组,将自己的记录清除
if (who == AIcolor) {
AIstate[state[who][x - i][y][0]]--;
}
else {
Manstate[state[who][x - i][y][0]]--;
}
//更新五元组状态
state[who][x - i][y][0]++;
//维护计分数组,添加记录
if (who == AIcolor) {
AIstate[state[who][x - i][y][0]]++;
}
else {
Manstate[state[who][x - i][y][0]]++;
}
}
else {
//更新五元组状态
state[who][x - i][y][0]++;
}
}
if (!yuejie(x, y - i)) {
//如果该点在该方向上没有被标记为死点 并且 该点在该方向上有对方的棋子
if (!dead[x][y - i][1] && state[other][x][y - i][1] != 0) {
//标记为死点
dead[x][y - i][1] = true;
deadnum++;
//维护计分数组, 将对方的记录清除
if (other == AIcolor) {
AIstate[state[other][x][y - i][1]]--;
}
else {
Manstate[state[other][x][y - i][1]]--;
}
//更新五元组状态
state[who][x][y - i][1]++;
}
else if (!dead[x][y - i][1]) {
//不是死点,维护计分数组,将自己的记录清除
if (who == AIcolor) {
AIstate[state[who][x][y - i][1]]--;
}
else {
Manstate[state[who][x][y - i][1]]--;
}
//更新五元组状态
state[who][x][y - i][1]++;
//维护计分数组,添加记录
if (who == AIcolor) {
AIstate[state[who][x][y - i][1]]++;
}
else {
Manstate[state[who][x][y - i][1]]++;
}
}
else {
//更新五元组状态
state[who][x][y - i][1]++;
}
}
if (!yuejie(x - i, y - i)) {
//如果该点在该方向上没有被标记为死点 并且 该点在该方向上有对方的棋子
if (!dead[x - i][y - i][2] && state[other][x - i][y - i][2] != 0) {
//标记为死点
dead[x - i][y - i][2] = true;
deadnum++;
//维护计分数组, 将对方的记录清除
if (other == AIcolor) {
AIstate[state[other][x - i][y - i][2]]--;
}
else {
Manstate[state[other][x - i][y - i][2]]--;
}
//更新五元组状态
state[who][x - i][y - i][2]++;
}
else if (!dead[x - i][y - i][2]) {
//不是死点,维护计分数组,将自己的记录清除
if (who == AIcolor) {
AIstate[state[who][x - i][y - i][2]]--;
}
else {
Manstate[state[who][x - i][y - i][2]]--;
}
//更新五元组状态
state[who][x - i][y - i][2]++;
//维护计分数组,添加记录
if (who == AIcolor) {
AIstate[state[who][x - i][y - i][2]]++;
}
else {
Manstate[state[who][x - i][y - i][2]]++;
}
}
else {
//更新五元组状态
state[who][x - i][y - i][2]++;
}
}
if (!yuejie(x - i, y + i)) {
//如果该点在该方向上没有被标记为死点 并且 该点在该方向上有对方的棋子
if (!dead[x - i][y + i][3] && state[other][x - i][y + i][3] != 0) {
//标记为死点
dead[x - i][y + i][3] = true;
deadnum++;
//维护计分数组, 将对方的记录清除
if (other == AIcolor) {
AIstate[state[other][x - i][y + i][3]]--;
}
else {
Manstate[state[other][x - i][y + i][3]]--;
}
//更新五元组状态
state[who][x - i][y + i][3]++;
}
else if (!dead[x - i][y + i][3]) {
//不是死点,维护计分数组,将自己的记录清除
if (who == AIcolor) {
AIstate[state[who][x - i][y + i][3]]--;
}
else {
Manstate[state[who][x - i][y + i][3]]--;
}
//更新五元组状态
state[who][x - i][y + i][3]++;
//维护计分数组,添加记录
if (who == AIcolor) {
AIstate[state[who][x - i][y + i][3]]++;
}
else {
Manstate[state[who][x - i][y + i][3]]++;
}
}
else {
//更新五元组状态
state[who][x - i][y + i][3]++;
}
}
}
return true;
}
bool thinker::remove(int x, int y){
if (cboard[x][y] == 0) {
exit(1);
return false;
}
int who = cboard[x][y];
int other = who % 2 + 1;
cboard[x][y] = 0;
for (int i = 0; i < 5; i++) {
if (!yuejie(x - i, y)) {
if (!dead[x - i][y][0]) {
//不是死点,维护计分数组,将自己的记录清除
if (who == AIcolor) {
AIstate[state[who][x - i][y][0]]--;
}
else {
Manstate[state[who][x - i][y][0]]--;
}
//更新五元组状态
state[who][x - i][y][0]--;
//维护计分数组,添加记录
if (who == AIcolor) {
AIstate[state[who][x - i][y][0]]++;
}
else {
Manstate[state[who][x - i][y][0]]++;
}
}
else {
//更新五元组状态
state[who][x - i][y][0]--;
//检查死点是否解除
if (state[who][x - i][y][0] == 0) {
//解除死点
dead[x - i][y][0] = 0;
deadnum--;
if (other == AIcolor) {
AIstate[state[other][x - i][y][0]]++;
}
else {
Manstate[state[other][x - i][y][0]]++;
}
}
}
}
if (!yuejie(x, y - i)) {
if (!dead[x][y - i][1]) {
//不是死点,维护计分数组,将自己的记录清除
if (who == AIcolor) {
AIstate[state[who][x][y - i][1]]--;
}
else {
Manstate[state[who][x][y - i][1]]--;
}
//更新五元组状态
state[who][x][y - i][1]--;
//维护计分数组,添加记录
if (who == AIcolor) {
AIstate[state[who][x][y - i][1]]++;
}
else {
Manstate[state[who][x][y - i][1]]++;
}
}
else {
//更新五元组状态
state[who][x][y - i][1]--;
//检查死点是否解除
if (state[who][x][y - i][1] == 0) {
//解除死点
dead[x][y - i][1] = 0;
deadnum--;
if (other == AIcolor) {
AIstate[state[other][x][y - i][1]]++;
}
else {
Manstate[state[other][x][y - i][1]]++;
}
}
}
}
if (!yuejie(x - i, y - i)) {
if (!dead[x - i][y - i][2]) {
//不是死点,维护计分数组,将自己的记录清除
if (who == AIcolor) {
AIstate[state[who][x - i][y - i][2]]--;
}
else {
Manstate[state[who][x - i][y - i][2]]--;
}
//更新五元组状态
state[who][x - i][y - i][2]--;
//维护计分数组,添加记录
if (who == AIcolor) {
AIstate[state[who][x - i][y - i][2]]++;
}
else {
Manstate[state[who][x - i][y - i][2]]++;
}
}
else {
state[who][x - i][y - i][2]--;
//检查死点是否解除
if (state[who][x - i][y - i][2] == 0) {
//解除死点
dead[x - i][y - i][2] = 0;
deadnum--;
if (other == AIcolor) {
AIstate[state[other][x - i][y - i][2]]++;
}
else {
Manstate[state[other][x - i][y - i][2]]++;
}
}
}
}
if (!yuejie(x - i, y + i)) {
if (!dead[x - i][y + i][3]) {
//不是死点,维护计分数组,将自己的记录清除
if (who == AIcolor) {
AIstate[state[who][x - i][y + i][3]]--;
}
else {
Manstate[state[who][x - i][y + i][3]]--;
}
//更新五元组状态
state[who][x - i][y + i][3]--;
//维护计分数组,添加记录
if (who == AIcolor) {
AIstate[state[who][x - i][y + i][3]]++;
}
else {
Manstate[state[who][x - i][y + i][3]]++;
}
}
else {
state[who][x - i][y + i][3]--;
//检查死点是否解除
if (state[who][x - i][y + i][3] == 0) {
//解除死点
dead[x - i][y + i][3] = 0;
deadnum--;
if (other == AIcolor) {
AIstate[state[other][x - i][y + i][3]]++;
}
else {
Manstate[state[other][x - i][y + i][3]]++;
}
}
}
}
}
return true;
}
long long thinker::getpoint() {
long long point = 0;
if (AIstate[5] != 0) {
return INT_MAX;
}
if (Manstate[5] != 0) {
return INT_MIN;
}
for (int i = 0; i < 6; i++) {
point += AIstate[i] * cpoint[i] * 0.95;
point -= Manstate[i] * cpoint[i];
}
point += deadnum;
return point;
}
1
https://gitee.com/jmk0314/a-simple-gobang.git
git@gitee.com:jmk0314/a-simple-gobang.git
jmk0314
a-simple-gobang
a-simple-gobang
master

搜索帮助