我这个程序在QQ五子棋上实验了一下,结果是黑棋先手全胜,白棋后手的胜率却惨不忍睹,原因有下:
1、五子棋的先手是有优势的,所以职业比赛里都会有禁手来实现公平
2、水平有限,对局面的评估只有一小部分

主要思路就是博弈树,程序向前看一步,对对手可能的走法进行评估,评估的策略主要有两条:
1、扫描整个棋盘,判断出现了多少个三子成线并且两端未堵的情况,对方每出现一种该情况,评估大幅下降,因为这几乎是必堵的,反之评估大幅上升,程序追求的就是这种情况;
2、判断出现了多少个两子成线的情况,这种情况的评估值比上一种要少
此外还有一个几乎是没用的判断,是我从九宫格的评估方案上“拿”过来的,用两种颜色的棋子分别填满棋盘,判断出现了多少个五子成龙的情况,不过很鸡肋

#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <cstdio>
#include <set>
#include <math.h>
#include <algorithm>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
int changex=8,changey=8;
struct Node
{int A[16][16];int f;
};
void mcopy(int des[16][16],int src[16][16])
{for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)des[i][j]=src[i][j];
}
bool check(int flag,int tmp[16][16])
{int fflag;if(flag==0)fflag=1;elsefflag=0;//棋谱1:四子连线,端点都在for(int i=1; i<=15; ++i) //水平方向for(int j=1; j<=10; ++j){if(tmp[i][j]!=fflag&&tmp[i][j+1]==flag&&tmp[i][j+2]==flag&&tmp[i][j+3]==flag&&tmp[i][j+4]==flag&&tmp[i][j+5]!=fflag)return true;}for(int i=1; i<=10; ++i) //垂直方向for(int j=1; j<=15; ++j){if(tmp[i][j]!=fflag&&tmp[i+1][j]==flag&&tmp[i+2][j]==flag&&tmp[i+3][j]==flag&&tmp[i+4][j]==flag&&tmp[i+5][j]!=fflag)return true;}for(int i=1; i<=10; ++i) //正斜方向for(int j=1; j<=10; ++j){if(tmp[i][j]!=fflag&&tmp[i+1][j+1]==flag&&tmp[i+2][j+2]==flag&&tmp[i+3][j+3]==flag&&tmp[i+4][j+4]==flag&&tmp[i+5][j+5]!=fflag)return true;}for(int i=1; i<=10; ++i) //反斜方向for(int j=15; j>=6; --j){if(tmp[i][j]!=fflag&&tmp[i+1][j-1]==flag&&tmp[i+2][j-2]==flag&&tmp[i+3][j-3]==flag&&tmp[i+4][j-4]==flag&&tmp[i+5][j-5]!=fflag)return true;}//棋谱2:最简单的五子成型for(int i=1; i<=15; ++i) //水平方向for(int j=1; j<=11; ++j){if(tmp[i][j]==flag&&tmp[i][j+1]==flag&&tmp[i][j+2]==flag&&tmp[i][j+3]==flag&&tmp[i][j+4]==flag)return true;}for(int i=1; i<=11; ++i) //垂直方向for(int j=1; j<=15; ++j){if(tmp[i][j]==flag&&tmp[i+1][j]==flag&&tmp[i+2][j]==flag&&tmp[i+3][j]==flag&&tmp[i+4][j]==flag)return true;}for(int i=1; i<=11; ++i) //正斜方向for(int j=1; j<=11; ++j){if(tmp[i][j]==flag&&tmp[i+1][j+1]==flag&&tmp[i+2][j+2]==flag&&tmp[i+3][j+3]==flag&&tmp[i+4][j+4]==flag)return true;}for(int i=1; i<=11; ++i) //反斜方向for(int j=15; j>=5; --j){if(tmp[i][j]==flag&&tmp[i+1][j-1]==flag&&tmp[i+2][j-2]==flag&&tmp[i+3][j-3]==flag&&tmp[i+4][j-4]==flag)return true;}return false;
}
int h(int flag,int A[16][16])
{int tmp[16][16];mcopy(tmp,A);int fflag;if(flag==1)fflag=0;elsefflag=1;int val=0;//出现没有堵住的三子,对己方不利的评价要很高for(int i=1; i<=15; ++i) //水平方向for(int j=1; j<=11; ++j){if(tmp[i][j]!=flag&&tmp[i][j+1]==fflag&&tmp[i][j+2]==fflag&&tmp[i][j+3]==fflag&&tmp[i][j+4]!=flag)val+= -1000;if(tmp[i][j]!=fflag&&tmp[i][j+1]==flag&&tmp[i][j+2]==flag&&tmp[i][j+3]==flag&&tmp[i][j+4]!=fflag)val+= 1000;/*if(tmp[i][j]!=flag&&tmp[i][j+1]==fflag&&tmp[i][j+2]!=flag&&tmp[i][j+3]==fflag&&tmp[i][j+4]!=flag)val+= -100;if(tmp[i][j]!=fflag&&tmp[i][j+1]==flag&&tmp[i][j+2]!=fflag&&tmp[i][j+3]==flag&&tmp[i][j+4]!=fflag)val+= 100;*/}for(int i=1; i<=11; ++i) //垂直方向for(int j=1; j<=15; ++j){if(tmp[i][j]!=flag&&tmp[i+1][j]==fflag&&tmp[i+2][j]==fflag&&tmp[i+3][j]==fflag&&tmp[i+4][j]!=flag)val+= -1000;if(tmp[i][j]!=fflag&&tmp[i+1][j]==flag&&tmp[i+2][j]==flag&&tmp[i+3][j]==flag&&tmp[i+4][j]!=fflag)val+= 1000;/*if(tmp[i][j]!=flag&&tmp[i+1][j]==fflag&&tmp[i+2][j]!=flag&&tmp[i+3][j]==fflag&&tmp[i+4][j]!=flag)val+= -100;if(tmp[i][j]!=fflag&&tmp[i+1][j]==flag&&tmp[i+2][j]!=fflag&&tmp[i+3][j]==flag&&tmp[i+4][j]!=fflag)val+= 100;*/}for(int i=1; i<=11; ++i) //正斜方向for(int j=1; j<=11; ++j){if(tmp[i][j]!=flag&&tmp[i+1][j+1]==fflag&&tmp[i+2][j+2]==fflag&&tmp[i+3][j+3]==fflag&&tmp[i+4][j+4]!=flag)val+= -1000;if(tmp[i][j]!=fflag&&tmp[i+1][j+1]==flag&&tmp[i+2][j+2]==flag&&tmp[i+3][j+3]==flag&&tmp[i+4][j+4]!=fflag)val+= 1000;/*if(tmp[i][j]!=flag&&tmp[i+1][j+1]==fflag&&tmp[i+2][j+2]!=flag&&tmp[i+3][j+3]==fflag&&tmp[i+4][j+4]!=flag)val+= -100;if(tmp[i][j]!=fflag&&tmp[i+1][j+1]==flag&&tmp[i+2][j+2]!=fflag&&tmp[i+3][j+3]==flag&&tmp[i+4][j+4]!=fflag)val+= 100;*/}for(int i=1; i<=11; ++i) //反斜方向for(int j=15; j>=5; --j){if(tmp[i][j]!=flag&&tmp[i+1][j-1]==fflag&&tmp[i+2][j-2]==fflag&&tmp[i+3][j-3]==fflag&&tmp[i+4][j-4]!=flag)val+= -1000;if(tmp[i][j]!=fflag&&tmp[i+1][j-1]==flag&&tmp[i+2][j-2]==flag&&tmp[i+3][j-3]==flag&&tmp[i+4][j-4]!=fflag)val+= 1000;/*if(tmp[i][j]!=flag&&tmp[i+1][j-1]==fflag&&tmp[i+2][j-2]!=flag&&tmp[i+3][j-3]==fflag&&tmp[i+4][j-4]!=flag)val+= -100;if(tmp[i][j]!=fflag&&tmp[i+1][j-1]==flag&&tmp[i+2][j-2]!=fflag&&tmp[i+3][j-3]==flag&&tmp[i+4][j-4]!=fflag)val+= 100;*/}//出现未堵住的两子,评价次之for(int i=1; i<=15; ++i) //水平方向for(int j=1; j<=12; ++j){if(tmp[i][j]!=flag&&tmp[i][j+1]==fflag&&tmp[i][j+2]==fflag&&tmp[i][j+3]!=flag)val+= -100;if(tmp[i][j]!=fflag&&tmp[i][j+1]==flag&&tmp[i][j+2]==flag&&tmp[i][j+3]!=fflag)val+= 100;}for(int i=1; i<=12; ++i) //垂直方向for(int j=1; j<=15; ++j){if(tmp[i][j]!=flag&&tmp[i+1][j]==fflag&&tmp[i+2][j]==fflag&&tmp[i+3][j]!=flag)val+= -100;if(tmp[i][j]!=fflag&&tmp[i+1][j]==flag&&tmp[i+2][j]==flag&&tmp[i+3][j]!=fflag)val+= 100;}for(int i=1; i<=12; ++i) //正斜方向for(int j=1; j<=12; ++j){if(tmp[i][j]!=flag&&tmp[i+1][j+1]==fflag&&tmp[i+2][j+2]==fflag&&tmp[i+3][j+3]!=flag)val+= -100;if(tmp[i][j]!=fflag&&tmp[i+1][j+1]==flag&&tmp[i+2][j+2]==flag&&tmp[i+3][j+3]!=fflag)val+= 100;}for(int i=1; i<=12; ++i) //反斜方向for(int j=15; j>=4; --j){if(tmp[i][j]!=flag&&tmp[i+1][j-1]==fflag&&tmp[i+2][j-2]==fflag&&tmp[i+3][j-3]!=flag)val+= -100;if(tmp[i][j]!=fflag&&tmp[i+1][j-1]==flag&&tmp[i+2][j-2]==flag&&tmp[i+3][j-3]!=fflag)val+= 100;}/*if(val!=0){return val;}*/for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)if(tmp[i][j]==8)tmp[i][j]=flag;int sum1=0;for(int i=1; i<=15; ++i) //水平方向for(int j=1; j<=11; ++j)if(tmp[i][j]==flag&&tmp[i][j+1]==flag&&tmp[i][j+2]==flag&&tmp[i][j+3]==flag&&tmp[i][j+4]==flag)sum1++;for(int i=1; i<=11; ++i) //垂直方向for(int j=1; j<=15; ++j)if(tmp[i][j]==flag&&tmp[i+1][j]==flag&&tmp[i+2][j]==flag&&tmp[i+3][j]==flag&&tmp[i+4][j]==flag)sum1++;for(int i=1; i<=11; ++i) //正斜方向for(int j=1; j<=11; ++j)if(tmp[i][j]==flag&&tmp[i+1][j+1]==flag&&tmp[i+2][j+2]==flag&&tmp[i+3][j+3]==flag&&tmp[i+4][j+4]==flag)sum1++;for(int i=1; i<=11; ++i) //反斜方向for(int j=15; j>=5; --j)if(tmp[i][j]==flag&&tmp[i+1][j-1]==flag&&tmp[i+2][j-2]==flag&&tmp[i+3][j-3]==flag&&tmp[i+4][j-4]==flag)sum1++;mcopy(tmp,A);for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)if(tmp[i][j]==8)tmp[i][j]=fflag;int sum0=0;for(int i=1; i<=15; ++i) //水平方向for(int j=1; j<=11; ++j)if(tmp[i][j]==fflag&&tmp[i][j+1]==fflag&&tmp[i][j+2]==fflag&&tmp[i][j+3]==fflag&&tmp[i][j+4]==fflag)sum0++;for(int i=1; i<=11; ++i) //垂直方向for(int j=1; j<=15; ++j)if(tmp[i][j]==fflag&&tmp[i+1][j]==fflag&&tmp[i+2][j]==fflag&&tmp[i+3][j]==fflag&&tmp[i+4][j]==fflag)sum0++;for(int i=1; i<=11; ++i) //正斜方向for(int j=1; j<=11; ++j)if(tmp[i][j]==fflag&&tmp[i+1][j+1]==fflag&&tmp[i+2][j+2]==fflag&&tmp[i+3][j+3]==fflag&&tmp[i+4][j+4]==fflag)sum0++;for(int i=1; i<=11; ++i) //反斜方向for(int j=15; j>=5; --j)if(tmp[i][j]==fflag&&tmp[i+1][j-1]==fflag&&tmp[i+2][j-2]==fflag&&tmp[i+3][j-3]==fflag&&tmp[i+4][j-4]==fflag)sum0++;return val+sum1-sum0;
}
int move1(int A[16][16])
{int tmp[16][16],num,ans=INF;for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)if(A[i][j]==8){mcopy(tmp,A);tmp[i][j]=0; //对手下if(check(0,tmp))num=-INF;elsenum=h(1,tmp);//cout<<num<<endl;ans=min(ans,num);}return ans;
}
int move0(int A[16][16])
{int tmp[16][16],num,ans=INF;for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)if(A[i][j]==8){mcopy(tmp,A);tmp[i][j]=1; //对手下if(check(1,tmp))num=-INF;elsenum=h(0,tmp);//cout<<num<<endl;ans=min(ans,num);}return ans;
}
void solve1(Node &node)
{int tmp[16][16],f,ans=-INF,anst[16][16]= {};for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)if(node.A[i][j]==8){mcopy(tmp,node.A);tmp[i][j]=1; //自己下if(check(1,tmp)){f=move1(tmp);if(f!=-INF)f=INF;}elsef=move1(tmp);//cout<<f<<endl;if(f>ans){//cout<<f<<endl;ans=f;mcopy(anst,tmp);}}for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)if(node.A[i][j]!=anst[i][j]){changex=i;changey=j;break;}mcopy(node.A,anst);node.f=ans;cout<<ans<<endl;
}
void solve0(Node &node)
{int tmp[16][16],f,ans=-INF,anst[16][16]= {};for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)if(node.A[i][j]==8){mcopy(tmp,node.A);tmp[i][j]=0; //自己下if(check(0,tmp)){f=move0(tmp);if(f!=-INF)f=INF;}elsef=move0(tmp);if(f>ans){//cout<<f<<endl;ans=f;mcopy(anst,tmp);}}for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)if(node.A[i][j]!=anst[i][j]){changex=i;changey=j;break;}mcopy(node.A,anst);node.f=ans;cout<<ans<<endl;
}
void show(int A[16][16])
{int sum=0;for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)sum+=A[i][j];if(sum==0)cout<<"无法继续!"<<endl;else{for(int i=0; i<=15; ++i){for(int j=0; j<=15; ++j){if(i==0){cout<<j<<" ";if(j==0)cout<<" ";}else if(j==0){cout<<i<<" ";if(i<10)cout<<" ";}else if((i==4&&j==4)||(i==4&&j==12)||(i==12&&j==4)||(i==12&&j==12)||(i==changex&&j==changey)){if(A[i][j]==8)cout<<".<";elsecout<<A[i][j]<<"<";}else{if(A[i][j]==8)cout<<". ";elsecout<<A[i][j]<<" ";}if(j>9&&i!=0)cout<<" ";}cout<<endl;}cout<<endl;}
}
int main()
{int flag=1,myturn,first=1;int i,j;Node node;for(int i=1; i<=15; ++i)for(int j=1; j<=15; ++j)node.A[i][j]=8;cout<<"程序执黑棋(1)or白棋(0)?";cin>>myturn;while(1){if(flag){if(flag==myturn){if(first)//人工智能第一次不会走中间,因为中间范围的评价相同,所以第一步要强制下在中间{node.A[8][8]=1;first=0;}elsesolve1(node);}else{cout<<"对方的选择是?";cin>>i>>j;node.A[i][j]=1;}show(node.A);flag=0;}else{if(flag==myturn){if(first){node.A[i-1][j-1]=0;first=0;}elsesolve0(node);}else{cout<<"对方的选择是?";cin>>i>>j;node.A[i][j]=0;}show(node.A);flag=1;}}return 0;
}

人工智能实现简单的五子棋程序相关推荐

  1. C++实现简单的五子棋程序

    //全部代码12 .26.2017 #include<iostream> #include<stdlib.h> #include<iomanip>     //格式 ...

  2. 简单的五子棋程序(可悔棋版和普通版)

    //普通版 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <wind ...

  3. vc6.0c语言五子棋程序,哪位大虾可以给我个VC6.0下用C语言编的五子棋,要有流程图...

    五子棋 代码 VC6.0 qq_29018467112015-06-14 五子棋 (用C语言编写五子棋游戏) rannianzhixia170392017-04-20 基于easyx图形的五子棋游戏 ...

  4. java人际对战五子棋_系统框图如下 java实现五子棋程序 可以实现人人对战 人机对战 简单功能 悔棋 认输...

    展开全部 一.实验题目 五子棋游戏e69da5e6ba9062616964757a686964616f31333365633835. 二.问题分析 五子棋是双人博弈棋类益智游戏,由围棋演变而来,属纯策 ...

  5. 用c语言做一个五子棋程序,C语言制作简单五子棋游戏

    原标题:C语言制作简单五子棋游戏 C语言制作简单的五子棋游戏 学习C语言的人很多,但是用C语言很少,而用来为自己所用,来做游戏的人就更少了,很多人都是跟着学校学习,学校讲到哪就坐到哪,但是以后却还是不 ...

  6. Java版五子棋程序

    一.实验题目 五子棋游戏. 二.问题分析 五子棋是双人博弈棋类益智游戏,由围棋演变而来,属纯策略型.棋盘通常15*15,即15行,15列,共225个交叉点,即棋子落点:棋子由黑白两色组成,黑棋123颗 ...

  7. 【C语言】实现简单的五子棋

    用c语言实现简单的五子棋 (2019年10月文档) ps:那时候刚刚学会用走迷宫就自己从零开始实现了下五子棋,这里下棋的思路现在想起来也特别新奇,并不是简单的输入坐标下棋,我一开始就琢磨出了wasd去 ...

  8. 网络版五子棋程序的开发

    前言 这是小的一个五子棋联网对战的小程序,可以实行网络对战. 我们的开发过程是了解五子棋的运行原理,然后开发网络部分进行实现. 开发工具 开发语言:Java 开发工具:Eclipse Neon 开发平 ...

  9. 如何编写一个简单的 Python 程序

    本教程将教你如何编写一个简单的 Python 程序.我们将从解释 Python 程序是什么开始,然后继续讨论语法的各个方面,即语言的结构. 什么是 Python? Python是一种越来越受欢迎的编程 ...

最新文章

  1. 【海洋女神原创】installshield 32位打包和64位打包的注意事项
  2. 你的中文大模型真的行吗?来用智源指数测测看
  3. Java程序员必看!2021Java大厂面试知识分享
  4. 编程软件python下载-Thonny(Python编程工具) v3.2.7 官方版
  5. 使用Gson对复杂json对象的成员进行删选
  6. java中的解码和编码_关于java中编码和解码(一)
  7. Nginx服务系列——代理
  8. 【性能优化】之 表分析及动态采样
  9. Deep Boltzmann Machines
  10. ubuntu优化服务器网络连接数,ubuntu下解决高并发socket最大连接数限制,tcp默认1024个连接...
  11. @RequestParam用法与@PathVariable用法的区别
  12. SSE instruction set not enabled
  13. java判断读到末尾_Java Web入门之java--第一节 java 简介及开发环境安装
  14. GPU 加速数据科学乘风破浪
  15. c语言80c51控制系统设计,89C51单片机的步进电动机控制系统设计
  16. 由系统函数求零极点图、频率响应(幅频特性、相频特性)的 Matlab 和 Python 方法
  17. Dubbo源码解析-Dubbo协议解析
  18. c语言输入身高输出标准体重,项目2:就拿胖子说事---(4)计算出标准体重,输出体重状态(正常/超重/超轻)...
  19. 人、机、料、法、环 全面理解
  20. Android 使用adb查看和修改电池信息

热门文章

  1. vert.x mysql_vert.x真的不需要ORM吗?
  2. table同时实现跨行跨列
  3. python使用pyqt5制作exe电脑小工具
  4. 面试知识点(C++)
  5. android quick settings中去掉不需要的图标
  6. RMAN-03002、RMAN-20230、RMAN-06015错误处理方法
  7. linux 进程亲缘性,Linux线程亲缘性
  8. (十五)配置代理跨域
  9. 3D建模的相关知识,想学习之前也必须了解以下几点!
  10. 最好用的三款服装批发进销存软件出炉