我写了一个五子棋棋盘背景图的人机对战算法,但是只能通过对每个点的分值估计,判断当前棋盘分值最高的位置,我想让

五子棋估值算法 - 推酷
五子棋估值算法
首先说明整个五子棋程序的整体布局。(用Java实现)
class Chess{
Player player1 ;
Player player2;
//其余界面显示相关函数;
class Player{
abstract Point play(); //落子操作
int getLine(Point p, int i, int j) ;
class Person extends Player{
Point play(int x,int y );
class Robot extends Player{
int evaluate(Point, int, int);
int Evaluate(Point);
Point play();
class ChessBox{
int chess_flag[15][15] //0:空
估值函数。即给定棋盘上一个点,求出该点在当前棋局下的权值。若在该点
落子后更容易接近胜利,则该点权值就高,越接近5子相连,权值越高。函数的形式为
int Evaluate(Point p);
首先考虑每个点有8个方向可以连子,每个方向上又有多种连子棋型,如活四、活三、死三等,而所连的子又可能属于己方或者对方。活四与活三的权值自然不同。而同样是活三,己方的活三与对方的活三权值也不同,这样才能实现攻守的策略。假如现在棋局上同时有己方的活三和对方的活三,此时轮到我方落子,则正常情况下应当在己方活三上落子,使之成为活四,从而获胜。则计算机在判断棋局时,遇到己方活三,权值应当较高,遇到对方活三,权值应当较低。
以上即是对于估值函数所应达到的要求的分析。
由于着眼处在于对棋型的判断,而不是方向,所以对于各个方向应当能够进行比较统一的处理,所以在判断棋子的相对位置时,应当与方向无关,而只与相互之间的顺序有关。若取某一行(列、斜列),假设当前点的坐标为0,取右(下、右下、右上)为正方向,则在该行(列、斜列)上各点都能得到相应的坐标。如下图。
由此,只要三个元素即可确定棋盘上任意一点,即当前点、方向、相对坐标值。进而可以获得任意一点的落子情况。函数即为
int getLine(Point p,int i,int j);
其中p即为当前点,i为方向,取值为从1到8的整数,j为相对于p点的坐标值。在函数体内要依据方向对x、y的值进行处理。返回值为该点的落子情况,0表示无子,1或2分别表示两个player,-1表示超出棋盘界。
代码如下:
int getLine(Point p, int i, int j) { // p:当前点
j:坐标相对值
int x = p.x, y = p.y;
switch (i) {
if (x & 0 || y & 0 || x & 14 || y & 14) { // 越界处理
return -1;
return box.getFlag(x,y);
对于方向的处理完成后,就是棋型的判断。
结合已有的算法结构,参考下图
将棋型分为以下几种:
*: 当前空位置;
0: 其他空位置;
1: plyer(当前所计算的player的代号);
2: 3-plyer(对方的代号);
1.活四 :01111*
2.死四A :21111*
3.死四B :111*1
4.死四C :11*11
5.活三(近三位置) :111*0
6.活三(远三位置) :1110*
此外由于两个或多个方向上都有活二的棋型较为常见且胜率较高(见下图)。所以增加对此种棋型的判断。
即在每一个方向的棋型判断中扫描 011*0 或 111*0 并计数,若最终计数值大于等于 2 ,则权值增加一个较大的数值,否则不增加。
由此只要循环 8 次,每次循环中扫描各个棋型,并更新 value值即可。
代码如下:
1 int evaluate(Point p, int me,int plyer) { /* me:我的代号;plyer:当前计算的player的代号;*/
int value = 0;
int numoftwo=0;
4 for (int i = 1; i &= 8; i++) { // 8个方向
*代表当前空位置
0代表其他空位置
if (getLine(p, i, -1) == plyer && getLine(p, i, -2) == plyer
&& getLine(p, i, -3) == plyer && getLine(p, i, -4) == plyer
&& getLine(p, i, -5) == 0) {
value += 300000;
if(me!=plyer){value-=500;}
System.out.print(&+ 300000&);
//计算011*0或111*0的个数
if (getLine(p, i, -1) == plyer && getLine(p, i, -2) == plyer
&& getLine(p, i, -3) != 3-plyer&&getLine(p,i,1)!=3-plyer) {
numoftwo++;
22 if(numoftwo&=2){
23 value+=3000;
24 if(me!=plyer){
25 value-=100;
int Evaluate(Point p)
函数则只要调用&
int evaluate(Point p, int me, int plyer)
函数就可以获得p 点的权值。
代码如下:
1 int Evaluate(Point p){
2 return evaluate(p, 1,1)+ evaluate(p, 1,2);
最终程序核心算法只运用该估值算法,没有进行深度搜索。界面如下:
可见估值算法即便非常完美(当然这个算法离完美还差得远 ̄□ ̄||),依然无法做到立于不败之地,因为往往会出现对方有多个接近连五,以至于堵都堵不住。所以博弈还是必须要深度搜索的。
最后贴出自己写的估值算法完整的代码(仅供参考,正确性未经严格验证):
1 int Evaluate(Point p){
return evaluate(p, 1,1)
+ evaluate(p, 1,2);
6 int evaluate(Point p, int me,int plyer) { // me:我的代号
plyer:当前计算的player的代号
int value = 0;
int numoftwo=0;
for (int i = 1; i &= 8; i++) { // 8个方向
// 活四 01111* *代表当前空位置
0代表其他空位置
if (getLine(p, i, -1) == plyer && getLine(p, i, -2) == plyer
&& getLine(p, i, -3) == plyer && getLine(p, i, -4) == plyer
&& getLine(p, i, -5) == 0) {
value += 300000;
if(me!=plyer){value-=500;}
// 死四A 21111*
if (getLine(p, i, -1) == plyer && getLine(p, i, -2) == plyer
&& getLine(p, i, -3) == plyer && getLine(p, i, -4) == plyer
&& (getLine(p, i, -5) == 3 - plyer||getLine(p, i, -5) == -1)) {
value += 250000;
if(me!=plyer){value-=500;}
// 死四B 111*1
if (getLine(p, i, -1) == plyer && getLine(p, i, -2) == plyer
&& getLine(p, i, -3) == plyer && getLine(p, i, 1) == plyer) {
value += 240000;
if(me!=plyer){value-=500;}
// 死四C 11*11
if (getLine(p, i, -1) == plyer && getLine(p, i, -2) == plyer
&& getLine(p, i, 1) == plyer && getLine(p, i, 2) == plyer) {
value += 230000;
if(me!=plyer){value-=500;}
// 活三 近3位置 111*0
if (getLine(p, i, -1) == plyer && getLine(p, i, -2) == plyer
&& getLine(p, i, -3) == plyer) {
if (getLine(p, i, 1) == 0) {
value += 750;
if (getLine(p, i, -4) == 0) {
value += 3150;
if(me!=plyer){value-=300;}
if ((getLine(p, i, 1) == 3 - plyer||getLine(p, i, 1) == -1) && getLine(p, i, -4) == 0) {
value += 500;
// 活三 远3位置 1110*
if (getLine(p, i, -1) == 0 && getLine(p, i, -2) == plyer
&& getLine(p, i, -3) == plyer && getLine(p, i, -4) == plyer) {
value += 350;
// 死三 11*1
if (getLine(p, i, -1) == plyer && getLine(p, i, -2) == plyer
&& getLine(p, i, 1) == plyer) {
value += 600;
if (getLine(p, i, -3) == 0 && getLine(p, i, 2) == 0) {
value += 3150;
if ((getLine(p, i, -3) == 3 - plyer||getLine(p, i, -3) == -1) && (getLine(p, i, 2) == 3 - plyer||getLine(p, i, 2) == -1)) {
value += 700;
//活二的个数
if (getLine(p, i, -1) == plyer && getLine(p, i, -2) == plyer
&& getLine(p, i, -3) != 3-plyer&&getLine(p,i,1)!=3-plyer) {
numoftwo++;
//其余散棋
int numOfplyer = 0; // 因为方向会算两次?
for (int k = -4; k &= 0; k++) { // ++++* +++*+ ++*++ +*+++ *++++
int temp = 0;
for (int l = 0; l &= 4; l++) {
if (getLine(p, i, k + l) == plyer) {
if (getLine(p, i, k + l) == 3 - plyer
|| getLine(p, i, k + l) == -1) {
numOfplyer +=
value += numOfplyer * 15;
if (numOfplyer != 0) {
if(numoftwo&=2){
value+=3000;
if(me!=plyer){
value-=100;
110 int getLine(Point p, int i, int j) { // i:方向 j:相对p的顺序值(以p为0) p:当前点
int x = p.x, y = p.y;
switch (i) {
if (x & 0 || y & 0 || x & 14 || y & 14) { // 越界处理
return -1;
return box.getFlag(x,y);
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致五子棋算法详解_图文_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
五子棋算法详解
上传于||暂无简介
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
下载文档到电脑,查找使用更方便
还剩10页未读,继续阅读
你可能喜欢五子棋的小游戏,怎样判断胜负(大虾请帮忙)
[问题点数:100分,结帖人ebombsuhocom]
五子棋的小游戏,怎样判断胜负(大虾请帮忙)
[问题点数:100分,结帖人ebombsuhocom]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2002年3月 软件工程/管理大版内专家分月排行榜第二
2000年11月 总版技术专家分月排行榜第一2000年10月 总版技术专家分月排行榜第一
2001年2月 Web 开发大版内专家分月排行榜第一2000年11月 Web 开发大版内专家分月排行榜第一2000年10月 Web 开发大版内专家分月排行榜第一2000年11月 VC/MFC大版内专家分月排行榜第一2000年10月 VC/MFC大版内专家分月排行榜第一2000年11月 VB大版内专家分月排行榜第一2000年10月 VB大版内专家分月排行榜第一
2000年9月 VB大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。求JAVA大神帮帮忙,我用Java做人机对战的五子棋,做了一点,算法还没有写,但是有很多问题。。_百度知道
求JAVA大神帮帮忙,我用Java做人机对战的五子棋,做了一点,算法还没有写,但是有很多问题。。
baidu://a.baidu问题1.com/zhidao/pic/item/9e3df8dcd100baa17db912c8fc2e4b.jpg" esrc="http.hiphotos.hiphotos:当我运行后,还没有点击棋盘就有棋子出现2://a.com/zhidao/wh%3D450%2C600/sign=bbc034af682/9e3df8dcd100baa17db912c8fc2e4b,我点击一下出现一个黑棋://a
提问者采纳
1 可能你数组初始化有问题或你图形画法有问题,你自己看看2 算法问题或者图形画法有问题3 设置标志量,鼠标事件监听器发现标志量没有开始,不响应具体函数
提问者评价
其他类似问题
为您推荐:
其他2条回答
自动画棋子是不可能的
肯定是你启动的时候调了画棋子的方法或者有画棋子的代码没有删除
你好好检查你的代码
多动手调试
你的这些问题只能通过调试才能找到问题的原因并纠正它
debugger下 或者贴出代码
五子棋的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁求JAVA大神帮帮忙,我用Java做人机对战的五子棋,做了一点,算法还没有写,但是有很多问题。。, 求JAVA大神帮帮忙,我用Java做
求JAVA大神帮帮忙,我用Java做人机对战的五子棋,做了一点,算法还没有写,但是有很多问题。。 题1:当我运行后,还没有点击棋盘就有棋子出现2.开始下棋后,但是会出现两个白棋3,我点击一下出现一个黑棋
enjoy任伟 求JAVA大神帮帮忙,我用Java做人机对战的五子棋,做了一点,算法还没有写,但是有很多问题。。
1 可能你数组初始化有问题或你图形画法有问题,你自己看看2 算法问题或者图形画法有问题3 设置标志量,鼠标事件监听器发现标志量没有开始,不响应具体函数
自动画棋子是不可能的
肯定是你启动的时候调了画棋子的方法或者有画棋子的代码没有删除
你好好检查你的代码
多动手调试
你的这些问题只能通过调试才能找到问题的原因并纠正它
debugger下 或者贴出代码

我要回帖

更多关于 五子棋棋盘大小 的文章

 

随机推荐