C# · 12月 20, 2021

C++简单五子棋的AI设计实现

本文实例为大家分享了C++五子棋的AI设计实现代码,供大家参考,具体内容如下

设计思路:通过接口获取信息来确定颜色,通过set_chess函数来确定落点。

对每个点位给出两种颜色棋子的打分,分别存在两个15*15的数组里,数组下标代表点的位置。

确定最大值所在数组之后,遍历该数组找出所有最大值对应的位置,然后对这些位置统计另一种颜色的棋子的分数,再选取一次最大值,从而确定要落点的位置。

打分函数的设计:在四个方向分别统计然后相加。对于某一个方向的分数统计,则分为正反两个方向进行,统计的时候如果有连成5个则直接返回一个最大值(最高分)。其他情况则按不同情况设置不同的权重,触发结束某一个方向上的统计的事件如下:遇到异色棋子;空白格子超过两个;遇到棋盘边界。其中遇到异色棋子和棋盘边界均视为一边被堵死,相比空白来说适当减分,而1个空白相比于完全连续则应再适当减分,最后取10的次幂,以保证不同情况的优先级,即不至于出现因为下到位置A可以形成4个活2而放弃下可以形成1个活4的位置B。

具体代码如下:

#pragma once

#ifndef AI_H

#define AI_H

#include “renju.h”

#include

#include

class Ai

{

public:

Ai(chessboard &bd,state hm)

{

ms.set_color(hm);

this->p_bd = &bd;

}

chess set_chess();

private:

int evaluate(position pos,state color,position (*pf)(position,bool ));//给出落子位置和方向移动函数,返回该落子位置在该方向上的评分

int point(position pos,state color);//给出一个落子位置,返回该落子的得分

void whole_points(int points[][15],state color );//给定颜色 ,记录该颜色棋子下在每一处的得分

int best_posits(const int points[][15],position p_s[],int& count); //给出分数数组,找出最大值对应的位置(可能不止一个),返回分数最大值

chess ms;

const chessboard *p_bd;

};

//确定落子

chess Ai:: set_chess()

{

int points_b[15][15]; //记录黑棋各落点分数

int points_w[15][15]; //记录白棋各落点分数

position best_b[20]; //记录黑棋最大分数对应的落点位置

position best_w[20]; //记录白棋最大分数对应的落点位置

int s_black = 0,s_white = 0; //记录黑白棋分别的最大分数值

int count_b = 0,count_w = 0; //记录黑白棋最大分数对应的落点位置个数

whole_points(points_b,black);

whole_points(points_w,white);

s_white = best_posits(points_w,best_w,count_w);

s_black = best_posits(points_b,best_b,count_b);

if( s_black > s_white ) //黑棋最高分高过白棋,在黑棋最高分对应的位置中选出白棋分数最大的位置落子

{

sb: int a[20];

for(int i = 0;i < count_b;i++)

{

a[i] = point(best_b[i],white);

}

int max_w = MAX(a,count_b);

for(int i = 0;i < count_b;i++)

{

if(a[i] == max_w)

{

ms.set_point(best_b[i]);

return ms;

}

}

}

if( s_black < s_white ) //白棋最高分高过黑棋,在白棋最高分对应的位置中选出黑棋分数最大的位置落子

{

sw: int a[20];

for(int i = 0;i < count_w;i++)

{

a[i] = point(best_w[i],black);

}

int max_b = MAX(a,count_b);

for(int i = 0;i < count_w;i++)

{

if(a[i] == max_b)

{

ms.set_point(best_w[i]);

return ms;

}

}

}

if( s_black == s_white )

{

if(ms.get_color() == white)

goto sw;

if(ms.get_color() == black)

goto sb;

}

}

//给出分数数组,找出最大值对应的位置(可能不止一个),返回分数最大值

int Ai::best_posits(const int points[][15],int& count)

{

int max_row[15];

int max_all;

for(int i = 0;i < 15;i++)

max_row[i] = MAX(points[i],15);

max_all = MAX(max_row,15);

cout<<"maxall"<<max_all;

count = 0;

for(int i = 0;i < 15;i++)

{

for(int j =0;j < 15;j++)

{

if(points[i][j] == max_all)

{

position x(i,j);

p_s[count] = x;

count++;

}

}

}

return max_all;

}

//给定颜色 ,记录该颜色棋子下在每一处的得分

void Ai::whole_points(int points[][15],state color )

{

for( int i =0;i < 15;i++)

{

for(int j = 0;j < 15;j++)

{

position temp(i,j);

points[i][j] = point(temp,color);

}

}

}

//位置函数,用于上下移动棋子并判断是否越界

position up(position pos,bool dir)

{

position r;

if(dir)

{

while(pos.y > 0)

{

r.x = pos.x;

r.y = pos.y – 1;

return r;

}

throw 0;

}

else

{

while(pos.y < 14)

{

r.x = pos.x;

r.y = pos.y + 1;

return r;

}

throw 0;

}

}

//位置函数,用于左右移动棋子并判断是否越界

position left(position pos,bool dir)

{

position r;

if(dir)

{

while(pos.x > 0)

{

r.x = pos.x – 1;

r.y = pos.y;

return r;

}

throw 0;

}

else

{

while(pos.x < 14)

{

r.x = pos.x + 1;

r.y = pos.y;

return r;

}

throw 0;

}

}

//位置函数,用于左上右下移动棋子并判断是否越界

position left_up(position pos,bool dir)

{

position r;

if(dir)

{

while(pos.x > 0 && pos.y > 0)

{

r.x = pos.x – 1;

r.y = pos.y – 1;

return r;

}

throw 0;

}

else

{

while(pos.x < 14 && pos.y < 14)

{

r.x = pos.x + 1;

r.y = pos.y + 1;

return r;

}

throw 0;

}

}

//位置函数,用于右上左下移动棋子并判断是否越界

position right_up(position pos,bool dir)

{

position r;

if(dir)

{

while(pos.x 0)

{

r.x = pos.x + 1;

r.y = pos.y – 1;

return r;

}

throw 0;

}

else

{

while(pos.x > 0 && pos.y < 14)

{

r.x = pos.x – 1;

r.y = pos.y + 1;

return r;

}

throw 0;

}

}

int Ai::evaluate(position pos,bool ))

{

int sum = 0;

position p_i = pos;

int count = 0,mc = 1;

bool flag = true;

int c_blank = 0;

state judge_t;

try

{

do

{

p_i = pf(p_i,flag);

judge_t = p_bd -> viewboard(p_i);

if(judge_t == color)

{

if(c_blank == 1)

{

count += 1;

}

else

{

mc++;

if(mc == 5)

return 100000000000;

count += 2;

}

}

else

{

if(judge_t == blank)

{

if(c_blank >= 1)

flag = false;

else

{

c_blank++;

}

}

else

{

count-=2;

flag = false;

}

}

}while(flag);

}

catch(int key)

{

flag = false;

if(c_blank == 0)count-=2;

}

p_i = pos;

int b_blank = 0;//记录另一半的空白格子

try

{

do

{

p_i = pf(p_i,flag);

judge_t = p_bd -> viewboard(p_i);

if(judge_t == color)

{

if(b_blank == 1)

{

count += 1;

}

else

{

if(c_blank == 0 && b_blank == 0)

mc++;

if(mc == 5)

return 100000000000;

count += 2;

}

}

else

{

if(judge_t == blank)

{

if(b_blank >= 1)

flag = true;

else

{

b_blank++;

}

}

else

{

count-=2;

flag = true;

}

}

}while(!flag);

}

catch(int key)

{

if(b_blank == 0)count-=2;

return pow(10,count);

}

return pow(10,count);

}

//给出一个落子位置,返回该落子的得分

int Ai::point(position pos,state color)

{

if(p_bd -> viewboard(pos) != blank)

{

return 0;

}

position (*p_f)(position,bool) = NULL;

int sum = 0;

p_f = up;

sum += evaluate(pos,color,p_f);

p_f = left;

sum += evaluate(pos,p_f);

p_f = left_up;

sum += evaluate(pos,p_f);

p_f = right_up;

sum += evaluate(pos,p_f);

return sum;

}

#endif

其中所需要的头文件在上一篇文章中有提到:C++语言设计实现五子棋

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。