C++简单五子棋的AI设计实现
本文实例为大家分享了C++五子棋的AI设计实现代码,供大家参考,具体内容如下
设计思路:通过接口获取信息来确定颜色,通过set_chess函数来确定落点。
- 对每个点位给出两种颜色棋子的打分,分别存在两个15*15的数组里,数组下标代表点的位置。
- 确定最大值所在数组之后,遍历该数组找出所有最大值对应的位置,然后对这些位置统计另一种颜色的棋子的分数,再选取一次最大值,从而确定要落点的位置。
- 打分函数的设计:在四个方向分别统计然后相加。对于某一个方向的分数统计,则分为正反两个方向进行,统计的时候如果有连成5个则直接返回一个最大值(最高分)。其他情况则按不同情况设置不同的权重,触发结束某一个方向上的统计的事件如下:遇到异色棋子;空白格子超过两个;遇到棋盘边界。其中遇到异色棋子和棋盘边界均视为一边被堵死,相比空白来说适当减分,而1个空白相比于完全连续则应再适当减分,最后取10的次幂,以保证不同情况的优先级,即不至于出现因为下到位置A可以形成4个活2而放弃下可以形成1个活4的位置B。
具体代码如下:
#pragmaonce #ifndefAI_H #defineAI_H #include"renju.h" #include#include classAi { public: Ai(chessboard&bd,statehm) { ms.set_color(hm); this->p_bd=&bd; } chessset_chess(); private: intevaluate(positionpos,statecolor,position(*pf)(position,bool));//给出落子位置和方向移动函数,返回该落子位置在该方向上的评分 intpoint(positionpos,statecolor);//给出一个落子位置,返回该落子的得分 voidwhole_points(intpoints[][15],statecolor);//给定颜色,记录该颜色棋子下在每一处的得分 intbest_posits(constintpoints[][15],positionp_s[],int&count);//给出分数数组,找出最大值对应的位置(可能不止一个),返回分数最大值 chessms; constchessboard*p_bd; }; //确定落子 chessAi::set_chess() { intpoints_b[15][15];//记录黑棋各落点分数 intpoints_w[15][15];//记录白棋各落点分数 positionbest_b[20];//记录黑棋最大分数对应的落点位置 positionbest_w[20];//记录白棋最大分数对应的落点位置 ints_black=0,s_white=0;//记录黑白棋分别的最大分数值 intcount_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:inta[20]; for(inti=0;i 0) { r.x=pos.x; r.y=pos.y-1; returnr; } throw0; } else { while(pos.y<14) { r.x=pos.x; r.y=pos.y+1; returnr; } throw0; } } //位置函数,用于左右移动棋子并判断是否越界 positionleft(positionpos,booldir) { positionr; if(dir) { while(pos.x>0) { r.x=pos.x-1; r.y=pos.y; returnr; } throw0; } else { while(pos.x<14) { r.x=pos.x+1; r.y=pos.y; returnr; } throw0; } } //位置函数,用于左上右下移动棋子并判断是否越界 positionleft_up(positionpos,booldir) { positionr; if(dir) { while(pos.x>0&&pos.y>0) { r.x=pos.x-1; r.y=pos.y-1; returnr; } throw0; } else { while(pos.x<14&&pos.y<14) { r.x=pos.x+1; r.y=pos.y+1; returnr; } throw0; } } //位置函数,用于右上左下移动棋子并判断是否越界 positionright_up(positionpos,booldir) { positionr; if(dir) { while(pos.x<14&&pos.y>0) { r.x=pos.x+1; r.y=pos.y-1; returnr; } throw0; } else { while(pos.x>0&&pos.y<14) { r.x=pos.x-1; r.y=pos.y+1; returnr; } throw0; } } intAi::evaluate(positionpos,statecolor,position(*pf)(position,bool)) { intsum=0; positionp_i=pos; intcount=0,mc=1; boolflag=true; intc_blank=0; statejudge_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) return100000000000; count+=2; } } else { if(judge_t==blank) { if(c_blank>=1) flag=false; else { c_blank++; } } else { count-=2; flag=false; } } }while(flag); } catch(intkey) { flag=false; if(c_blank==0)count-=2; } p_i=pos; intb_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) return100000000000; count+=2; } } else { if(judge_t==blank) { if(b_blank>=1) flag=true; else { b_blank++; } } else { count-=2; flag=true; } } }while(!flag); } catch(intkey) { if(b_blank==0)count-=2; returnpow(10,count); } returnpow(10,count); } //给出一个落子位置,返回该落子的得分 intAi::point(positionpos,statecolor) { if(p_bd->viewboard(pos)!=blank) { return0; } position(*p_f)(position,bool)=NULL; intsum=0; p_f=up; sum+=evaluate(pos,color,p_f); p_f=left; sum+=evaluate(pos,color,p_f); p_f=left_up; sum+=evaluate(pos,color,p_f); p_f=right_up; sum+=evaluate(pos,color,p_f); returnsum; } #endif
其中所需要的头文件在上一篇文章中有提到:C++语言设计实现五子棋
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。