第一次发博客,用C++写一个下五子棋的小AI
刚学C++一两年,试着写了一个下五子棋的小AI,核心的代码放在了gamemode.h和gamemode.cpp里面。毕竟本人是新手,所以做的比较粗糙,还望各位包涵(嘿嘿)。
1、其实调用这个AI的方式很简单,就是将棋盘状态保存在int Pad[15][15]这个数组里面(0表示该出没有棋子,1表示该处有白棋,-1表示该处有黑棋),然后如果调用void CulResult()这个函数,它就会根据棋盘上现在的状态计算出下一步的下棋位置(不管白棋还是黑棋都一样),并将这个位置储存在ivalue、jvalue这两个变量里(ivalue、jvalue分别表示行和列的坐标值,取值是1-15)。
2、在棋盘上下子的时候,可以调用bool CheckAndSet(CPoint point,bool type)这个函数,point表示下棋的位置,type表示下棋的种类。 这个函数会将type与turn做比较,检查是否轮到正确的下棋方下棋,如果下棋方正确则下棋并且返回true,下期方错误则会返回false。这个CPoint是引用的一个头文件里的,如果你没有的话请自己加一个这个类,只需要两个整型变量x、y就行了。然后调用完bool CheckAndSet(CPoint point,bool type)之后如果下棋成功了,建议调用一下bool ChangeTurn(),改变现在下一步的下棋方。另一种在棋盘上下棋的方式就是直接改int pad[15][15]数组的值,我觉得为了方便调试就把它设置为public了。
3、每下完一步棋都可以调用int checkwin()来检查现在是否有一方获胜了,如果白子赢了返回1,黑子赢了返回-1。
4、在声明一个gamemode类型的变量时,构造函数里的bool参数是指定玩家棋子的种类。在定义完gamemode变量以后要设置一下turn的值,也就是谁最先下棋。
最后说一下,我觉得我这个黑子、白子的次序和玩家、电脑的次序弄的有点乱,可能并不合理,但是改起来又有点麻烦,如果大家有建议欢迎提出。我会在之后上传一个我写好的工程,在我的资源里,可以直接用vs2012打开运行。但是在运行的时候先全屏,不然棋盘显示不全,
gamemode.h:
#include "math.h"
#include "stdafx.h"
struct TRNA //定义链表的结构体
{
int type;
int i;
int j;
TRNA *before;
TRNA *next;
};
struct check
{
int type;
int value;
};
class gamemode //定义五子棋的类
{
public:
int pad[15][15]; //储存棋盘当前的状态
bool turn; //true表示轮到白子,false表示轮到黑子。
bool player; //player表示玩家的子类型,true表示白子,false表示黑子。
int ivalue; //储存每一轮计算机计算的最终结果在数组中的行值
int jvalue; //储存每一轮计算机计算的最终结果在数组中的列值
float tend; //算法的下棋倾向,0-1表示偏向防守,1-2表示偏向攻击,1表示均衡
public:
gamemode(bool player); //参数player是初始化玩家的棋子类型,ture表示白子,false表示黑子
bool CheckAndSet(CPoint point,bool type); //检查棋子并下子
bool ChangeTurn(); //获取当前下棋方,并在获取后自动切换下棋方
void CulResult(); //调用4*2次SingleCul,获取所有扫描结果并相加
int checkwin(); //检查是否有一方获取了胜利,1表示玩家获胜,-1表示电脑获胜,0表示没有人获胜
private:
int location[15][15];
int longitude[15][15]; //存储纵向扫描白子优先度结果
int latitude[15][15]; //存储横向扫描白子优先度结果
int LtoR[15][15]; //存储左上到右下扫白子描优先度结果
int RtoL[15][15]; //存储右上到左下扫白子描优先度结果
int longitude2[15][15]; //存储纵向扫描黑子优先度结果
int latitude2[15][15]; //存储横向扫描黑子优先度结果
int LtoR2[15][15]; //存储左上到右下扫黑子描优先度结果
int RtoL2[15][15]; //存储右上到左下扫黑子描优先度结果
float result1[15][15]; //存储白子最终扫描结果
float result2[15][15]; //存储黑子最终扫描结果
void SingleCul(TRNA* linktable,int target[15][15]); //输入扫描结果的链表以及存储的数组,进行单次的扫描
void initialize(); //初始化存储扫描存储空间的函数
TRNA* getlon(); //获取纵向扫描结果
TRNA* getla(); //获取横向扫描结果
TRNA* getLtoR(); //获取左上到右下扫描结果
TRNA* getRtoL(); //获取右上到左下扫描结果
};
gamemode.cpp:
#include "stdafx.h"
#include "gamemode.h"
struct recorder
{
int i,j,type;
};
void release(TRNA* target) //释放链表
{
target = target->next;
for (; target->next != NULL; target = target->next)
{
delete target->before;
}
delete target;
}
/*
check _3a[3]={{0,10},{1,0},{0,10}};
check _5a[5]={{1,0},{0,30},{0,30},{1,0},{0,0}};
check _5b[5]={{1,0},{1,0},{0,60},{1,0},{1,0}};
check _5c[5]={{1,0},{1,0},{1,0},{0,60},{1,0}};
check _5d[5]={{0,0},{1,0},{0,30},{1,0},{0,0}};
check _6a[6]={{0,0},{0,15},{0,15},{1,0},{1,0},{-1,0}};
check _6b[6]={{0,30},{1,0},{0,30},{1,0},{0,0},{-1,0}};
check _6c[6]={{0,0},{0,30},{1,0},{1,0},{0,30},{0,0}};
check _6d[6]={{0,30},{0,30},{1,0},{1,0},{1,0},{-1,0}};
check _6e[6]={{0,30},{1,0},{1,0},{0,60},{1,0},{0,30}};
check _6f[6]={{0,30},{1,0},{1,0},{0,30},{1,0},{-1,0}};
check _6g[6]={{0,30},{1,0},{0,30},{1,0},{1,0},{-1,0}};
check _6h[6]={{0,60},{1,0},{1,0},{1,0},{1,0},{-1,0}};
check -6i[6]={{0,0},{0,30},{0,30},{1,0},{1,0},{0,0}};
check _7a[7]={{0,0},{0,30},{1,0},{1,0},{0,30},{0,30},{0,0}};
check _7b[7]={{0,0},{0,30},{1,0},{0,30},{1,0},{0,30},{0,0}};
check _7c[7]={{-1,0},{0,0},{1,0},{1,0},{0,30},{0,30},{0,0}};
check _7d[7]={{0,30},{0,60},{1,0},{1,0},{1,0},{0,60},{0,30}};
check _7e[7]={{0,30},{0,60},{1,0},{1,0},{1,0},{0,30},{-1,0}};
check _7f[7]={{-1,0},{0,30},{1,0},{1,0},{1,0},{0,30},{-1,0}};
*/
check _3group[3] = {{0,5},{1,0},{0,5}};
check _5group[5][5] = {{{1,0},{0,30},{0,30},{1,0},{0,0}} ,{{1,0},{1,0},{0,100},{1,0},{1,0}} ,{{1,0},{1,0},{1,0},{0,100},{1,0}} ,{{0,0},{1,0},{0,30},{1,0},{0,0}},{{0,100},{1,0},{1,0},{1,0},{1,0}}};
check _6group[10][6] = {{{0,0},{0,15},{0,15},{1,0},{1,0},{-1,0}} ,{{0,30},{1,0},{0,30},{1,0},{0,0},{-1,0}} ,{{0,0},{0,30},{1,0},{1,0},{0,30},{0,0}} ,{{0,37},{0,37},{1,0},{1,0},{1,0},{-1,0}},
{{0,37},{1,0},{1,0},{0,67},{1,0},{0,37}} ,{{0,37},{1,0},{1,0},{0,37},{1,0},{-1,0}} ,{{0,30},{1,0},{1,0},{0,30},{1,0},{-1,0}} ,{{0,100},{1,0},{1,0},{1,0},{1,0},{-1,0} },{{0,0},{0,30},{0,30},{1,0},{1,0},{0,0}},
{{0,37},{0,67},{1,0},{1,0},{1,0},{0,37}}};
check _7group[6][7] = {{{0,0},{0,30},{1,0},{1,0},{0,30},{0,30},{0,0}} ,{{0,0},{0,30},{1,0},{0,30},{1,0},{0,30},{0,0}} ,{{-1,0},{0,0},{1,0},{1,0},{0,30},{0,30},{0,0}} ,
{{0,37},{0,67},{1,0},{1,0},{1,0},{0,67},{0,37}} ,{{0,37},{0,67},{1,0},{1,0},{1,0},{0,37},{-1,0}} ,{{-1,0},{0,37},{1,0},{1,0},{1,0},{0,37},{-1,0}}};
check WinCon[5]={{1,0},{1,0},{1,0},{1,0},{1,0}};
gamemode::gamemode(bool play) :player(play)
{
int i, j;
tend=1;
int a=0,b=0,max=0;
for (i = 0; i<15; i++)
for (j = 0; j<15; j++)
{
pad[i][j] = 0;
longitude[i][j] = 0;
latitude[i][j] = 0;
LtoR[i][j] = 0;
RtoL[i][j] = 0;
result1[i][j] = 0;
result1[i][j] = 0;
}
for(i=0;i<14;i++)
for(j=0;j<14;j++)
{
a=i-7;
b=j-7;
a=a<0?-a:a;
b=b<0?-b:b;
max=a>b?a:b;
location[i][j]=7-max;
}
}
bool gamemode::CheckAndSet(CPoint point, bool type)
{
int x, y;
x=point.x;
y=point.y;
if (gamemode::pad[y - 1][x - 1] == 0)
{
if(type==player)
{
pad[y - 1][x - 1] = 1;
return true;
}
else if(type!=player)
{
pad[y - 1][x - 1] = -1;
return true;
}
}
else
{
return false;
}
}
bool gamemode::ChangeTurn()
{
turn = !turn;
return !turn;
}
void gamemode::initialize()
{
int i, j;
for (i = 0; i<15; i++)
for (j = 0; j<15; j++)
{
longitude[i][j] = 0;
latitude[i][j] = 0;
LtoR[i][j] = 0;
RtoL[i][j] = 0;
longitude2[i][j] = 0;
latitude2[i][j] = 0;
LtoR2[i][j] = 0;
RtoL2[i][j] = 0;
result1[i][j] = 0;
result2[i][j] = 0;
}
}
TRNA* gamemode::getlon()
{
int i, j;
TRNA* start = new(TRNA);
start->before = NULL;
TRNA* p = start;
for (j = 0; j<15; j++)
{
for (i = 0; i<15; i++)
{
p->type = pad[i][j];
p->i = i;
p->j = j;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
p->type = -2;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
return start;
}
TRNA* gamemode::getla()
{
int i, j;
TRNA* start = new(TRNA);
start->before = NULL;
TRNA* p = start;
for (i = 0; i<15; i++)
{
for (j = 0; j<15; j++)
{
p->type = pad[i][j];
p->i = i;
p->j = j;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
p->type = -2;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
return start;
}
TRNA* gamemode::getLtoR()
{
int i, j;
TRNA* start = new(TRNA);
start->before = NULL;
TRNA* p = start;
for (j = 0; j<11; j++)
{
int k = j;
for (i = 0; k<15; i++, k++)
{
p->type = pad[i][k];
p->i = i;
p->j = k;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
p->type = -2;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
for (i = 1; i<11; i++)
{
int k = i;
for (j = 0; k<15; j++, k++)
{
p->type = pad[k][j];
p->i = k;
p->j = j;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
p->type = -2;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
return start;
}
TRNA* gamemode::getRtoL()
{
int i, j;
TRNA* start = new(TRNA);
start->before = NULL;
TRNA* p = start;
for (j = 14; j >= 4; j--)
{
int k = j;
for (i = 0; k >= 0; i++, k--)
{
p->type = pad[i][k];
p->i = i;
p->j = k;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
p->type = -2;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
for (i = 1; i<11; i++)
{
int k = i;
for (j = 14; k<15; j--, k++)
{
p->type = pad[k][j];
p->i = k;
p->j = j;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
p->type = -2;
p->next = new(TRNA);
p->next->before = p;
p = p->next;
p->next = NULL;
}
return start;
}
void gamemode::SingleCul(TRNA* linktable, int target[15][15])
{
TRNA *start, *end, *allend;
int i, j;
for (start = linktable, end = start->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (i = 0, temp = start; i<3; i++, temp = temp->next)
{
flag = false;
if (temp->type == _3group[i].type)
flag = true;
else
break;
}
if (flag)
{
for (temp = start, i = 0; temp != end; temp = temp->next, i++)
{
if (_3group[i].value>target[temp->i][temp->j])
{
target[temp->i][temp->j] = _3group[i].value;
}
}
}
}
for (i = 0; i<5; i++)
{
for (start = linktable, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (j = 0, temp = start; j<5; j++, temp = temp->next)
{
flag = false;
if (temp->type == _5group[i][j].type)
flag = true;
else
break;
}
if (flag)
{
for (temp = start, j = 0; temp != end; temp = temp->next, j++)
{
if (_5group[i][j].value>target[temp->i][temp->j])
{
target[temp->i][temp->j] = _5group[i][j].value;
}
}
}
}
}
allend = end->before->before;
for (i = 0; i<5; i++)
{
for (start = allend, end = start->before->before->before->before->before; end->before != NULL; start = start->before, end = end->before)
{
TRNA* temp;
bool flag;
for (j = 0, temp = start; j<5; j++, temp = temp->before)
{
flag = false;
if (temp->type == _5group[i][j].type)
flag = true;
else
break;
}
if (flag)
{
for (temp = start, j = 0; temp != end; temp = temp->before, j++)
{
if (_5group[i][j].value>target[temp->i][temp->j])
{
target[temp->i][temp->j] = _5group[i][j].value;
}
}
}
}
}
for (i = 0; i<10; i++)
{
for (start = linktable, end = start->next->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (j = 0, temp = start; j<6; j++, temp = temp->next)
{
flag = false;
if (temp->type == _6group[i][j].type)
flag = true;
else
break;
}
if (flag)
{
for (temp = start, j = 0; temp != end; temp = temp->next, j++)
{
if (_6group[i][j].value>target[temp->i][temp->j])
{
target[temp->i][temp->j] = _6group[i][j].value;
}
}
}
}
}
for (i = 0; i<10; i++)
{
for (start = allend, end = start->before->before->before->before->before; end->before != NULL; start = start->before, end = end->before)
{
TRNA* temp;
bool flag;
for (j = 0, temp = start; j<6; j++, temp = temp->before)
{
flag = false;
if (temp->type == _6group[i][j].type)
flag = true;
else
break;
}
if (flag)
{
for (temp = start, j = 0; temp != end; temp = temp->before, j++)
{
if (_6group[i][j].value>target[temp->i][temp->j])
{
target[temp->i][temp->j] = _6group[i][j].value;
}
}
}
}
}
for (i = 0; i<6; i++)
{
for (start = linktable, end = start->next->next->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (j = 0, temp = start; j<7; j++, temp = temp->next)
{
flag = false;
if (temp->type == _7group[i][j].type)
flag = true;
else
break;
}
if (flag)
{
for (temp = start, j = 0; temp != end; temp = temp->next, j++)
{
if (_7group[i][j].value>target[temp->i][temp->j])
{
target[temp->i][temp->j] = _7group[i][j].value;
}
}
}
}
}
for (i = 0; i<6; i++)
{
for (start = allend, end = start->before->before->before->before->before; end->before != NULL; start = start->before, end = end->before)
{
TRNA* temp;
bool flag;
for (j = 0, temp = start; j<7; j++, temp = temp->before)
{
flag = false;
if (temp->type == _7group[i][j].type)
flag = true;
else
break;
}
if (flag)
{
for (temp = start, j = 0; temp != end; temp = temp->before, j++)
{
if (_7group[i][j].value>target[temp->i][temp->j])
{
target[temp->i][temp->j] = _7group[i][j].value;
}
}
}
}
}
}
void gamemode::CulResult()
{
gamemode::initialize();
TRNA* LO = gamemode::getlon();
TRNA* LA = gamemode::getla();
TRNA* LT = gamemode::getLtoR();
TRNA* RT = gamemode::getRtoL();
gamemode::SingleCul(LO, gamemode::longitude);
gamemode::SingleCul(LA, gamemode::latitude);
gamemode::SingleCul(LT, gamemode::LtoR);
gamemode::SingleCul(RT, gamemode::RtoL);
TRNA* temp;
for (temp = LO; temp->next != NULL; temp = temp->next)
{
temp->type = temp->type * -1;
}
for (temp = LA; temp->next != NULL; temp = temp->next)
{
temp->type = temp->type * -1;
}
for (temp = LT; temp->next != NULL; temp = temp->next)
{
temp->type = temp->type * -1;
}
for (temp = RT; temp->next != NULL; temp = temp->next)
{
temp->type = temp->type * -1;
}
gamemode::SingleCul(LO, gamemode::longitude2);
gamemode::SingleCul(LA, gamemode::latitude2);
gamemode::SingleCul(LT, gamemode::LtoR2);
gamemode::SingleCul(RT, gamemode::RtoL2);
int i, j;
recorder Max={0,0,0};
for (i = 0; i<15; i++)
{
for (j = 0; j<15; j++)
{
result1[i][j] = longitude[i][j] + latitude[i][j] + LtoR[i][j] + RtoL[i][j];
}
}
for (i = 0; i<15; i++)
{
for (j = 0; j<15; j++)
{
result2[i][j] = longitude2[i][j] + latitude2[i][j] + LtoR2[i][j] + RtoL2[i][j];
}
}
for (i = 0; i<15; i++)
{
for (j = 0; j<15; j++)
{
if (Max.type < (result1[i][j] + tend * result2[i][j] + location[i][j]))
{
Max.type = result1[i][j] + tend * result2[i][j] + location[i][j];
Max.i = i;
Max.j = j;
}
}
}
gamemode::ivalue = Max.i;
gamemode::jvalue = Max.j;
release(LA);
release(LO);
release(LT);
release(RT);
}
int gamemode::checkwin()
{
int i, j;
gamemode::initialize();
TRNA* LO = gamemode::getlon();
TRNA* LA = gamemode::getla();
TRNA* LT = gamemode::getLtoR();
TRNA* RT = gamemode::getRtoL();
TRNA *start, *end, *allend;
for (start = LO, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (i = 0, temp = start; i<5; i++, temp = temp->next)
{
flag = false;
if (temp->type == WinCon[i].type)
flag = true;
else
break;
}
if (flag)
return 1;
}
for (start = LA, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (i = 0, temp = start; i<5; i++, temp = temp->next)
{
flag = false;
if (temp->type == WinCon[i].type)
flag = true;
else
break;
}
if (flag)
return 1;
}
for (start = LT, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (i = 0, temp = start; i<5; i++, temp = temp->next)
{
flag = false;
if (temp->type == WinCon[i].type)
flag = true;
else
break;
}
if (flag)
return 1;
}
for (start = RT, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (i = 0, temp = start; i<5; i++, temp = temp->next)
{
flag = false;
if (temp->type == WinCon[i].type)
flag = true;
else
break;
}
if (flag)
return 1;
}
TRNA *temp;
for (temp = LO; temp->next != NULL; temp = temp->next)
{
temp->type = temp->type * -1;
}
for (temp = LA; temp->next != NULL; temp = temp->next)
{
temp->type = temp->type * -1;
}
for (temp = LT; temp->next != NULL; temp = temp->next)
{
temp->type = temp->type * -1;
}
for (temp = RT; temp->next != NULL; temp = temp->next)
{
temp->type = temp->type * -1;
}
for (start = LO, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (i = 0, temp = start; i<5; i++, temp = temp->next)
{
flag = false;
if (temp->type == WinCon[i].type)
flag = true;
else
break;
}
if (flag)
return -1;
}
for (start = LA, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (i = 0, temp = start; i<5; i++, temp = temp->next)
{
flag = false;
if (temp->type == WinCon[i].type)
flag = true;
else
break;
}
if (flag)
return -1;
}
for (start = LT, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (i = 0, temp = start; i<5; i++, temp = temp->next)
{
flag = false;
if (temp->type == WinCon[i].type)
flag = true;
else
break;
}
if (flag)
return -1;
}
for (start = RT, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
{
TRNA* temp;
bool flag;
for (i = 0, temp = start; i<5; i++, temp = temp->next)
{
flag = false;
if (temp->type == WinCon[i].type)
flag = true;
else
break;
}
if (flag)
return -1;
}
return 0;
}