`

人工智能原来如此简单——你所见过的最好的五子棋

 
阅读更多

从开始着手做五子棋,到现在已经有一段时间了。这个项目也算告一段落。 从开始做的网络版,再到加入人机元素,  可谓是耗尽精力。   人机水平达到了比较牛逼的程度,可以战胜大多数人(略显夸张。。) 大言不惭的说最好,也是不符合程序猿严谨的风格,在新手中看来这个程序应该是写的可以了。但大牛看来就是乱七八糟(被大牛吐槽过)。。人机写到这个程度感觉再要进一步很难了。所以就先把这个版本发出来。


 

先看下效果图吧。 还是很漂亮的吧。这个界面也花了我很久的时间。

 

登陆界面

 

 



 

人机界面



 

可以更换背景

 

 

 

 

 


网络人人版

可下棋聊天

 

 

 



 
 

然后说下 一些做的不好的地方吧

1.我做了两个版本 一个是客户端一个是服务端, 必须先启动服务端 然后用客户端去连接客户端。(我想做成就一个版本, 任意打开的两个可以互联,但是一直没成功,求大神指导思路)。

 

2.棋子直接用画布画的圆圈没有用图片,不太好看。

3.最新下的棋子没有加入闪烁效果,棋子多了 可能分不清对方是在哪里下子

 

 

 

 总代码太长了 ,我就发下人机代码了 ,这是核心

电脑下棋思路: 15*15的五子棋盘一共有572种 成“5”组合。我们称这种组合为获胜组合。而保存这572种组合的表称为获胜表。每次下棋后,都要更新所以获胜组合情况(“5”中的棋子个数更改)。而电脑下棋前 扫描每个位置,看包含这个位置的所有组合,根据评估函数打分。分数有两个,一个是这个位置对电脑的得分,一个是对玩家的得分。。 电脑每次选取分数最高的地方下子。   五子棋人机思路及具体做法我做了个PPT ,大家可以下载看看,讲的很详细了。有什么不懂的地方欢迎留言。有什么可以改进的地方也欢迎留言指教!

 

 

package client;

import java.awt.Point;

public class ComputerNormal {
	static Integer[][][] pTable; // 人的获胜表
	static Integer[][][] cTable;// 机器的获胜表
	//win[0][k]:表示玩家在第k个获胜组合往其方向有win[0][k]个连续的黑棋。
	//win[0][k]取值为9则表示第k个获胜组合被封死了,没有成5的可能。
//	win[1][k]:表示计算机在第k个获胜组合往其方向有win[1][k]个连续的白棋。
	static Integer  win[][];
	static int row = 15;
	static int col = 15;
	
	public ComputerNormal() {
		InitBoard();
	}
	public static Point  cPutChess(Integer map[][])
	{
		
		//机器下子 判断机器分
		int maxi = 0,maxj = 0;
		int max=-999999;
		for(int i=0;i<row;i++)
		{
			for(int j=0;j<col;j++)
			{
				if(map[i][j]!=0)
					continue;
				int t=GiveScore(1, i, j);
				if(max<t)
				{
					max=t;
					maxi=i;
					maxj=j;
				}
			}
		}
		
		//机器下子 判断ren分
		int mini = 0,minj = 0;
		int min=0;
		for(int i=0;i<row;i++)
		{
			for(int j=0;j<col;j++)
			{
				if(map[i][j]!=0)
					continue;
				int t=GiveScore(2, i, j);
				if(min>t)
				{
					min=t;
					mini=i;
					minj=j;
				}
			}
		}
		int lastx=maxi,lasty=maxj;
		if(max<=Math.abs(min))
		{
			lastx=mini;
			lasty=minj;
		}
		
		Point p = new Point(lastx,lasty);
		return p;
	}
	//人下子后的状态变化
	public  static void pboardModify( int x, int y )
	{
		for( int k=0; k<572; k++ )	//修改玩家下子后棋盘状态的变化
		{
			//如果[x][y]位置是玩家第k个"5"中的位置,且第k个"5"没有被封死
			if( pTable[x][y][k]==1 && win[0][k]!=9 )
				win[0][k]++;
		//如果[x][y]位置是计算机第k个"5"中的位置,则玩家下子后第k个"5"被封死
			if( cTable[x][y][k]==1 )	//○●○○○
			{
				cTable[x][y][k] = 0;
				win[1][k] = 9;
			}
		}
	}//pboard
	
	//计算机下子后的状态变化
	public static void  cboardModify( int x, int y )
	{
		for( int k=0; k<572; k++ )	//修改计算机下子后,棋盘的变化状况
		{
			//如果[x][y]位置是计算机第k个"5"中的位置,且第k个"5"没有被封死
			if( cTable[x][y][k]==1 && win[1][k]!=9 )
				{
				win[1][k]++;
				}
		//如果[x][y]位置是玩家第k个"5"中的位置,则计算机下子后第k个"5"被封死
			if( pTable[x][y][k]==1 )	//●○●●●
			{
				pTable[x][y][k] =0;
				win[0][k] = 9;
			}
		}
	}//cboard
	
	/**
	 * 估值
	 */
	static int GiveScore( int type, int x, int y )
	{
		int k, score = 0;
		for( k=0; k<572; k++ )
		{
			if( type==1 )	//计算机下
			{
				if( cTable[x][y][k]==1 )	//[x][y]是第k个"5"上的一个位置
				{
					//第k个"5"中已经有win[1][k]个位置了
					switch( win[1][k] )
					{
					case 1:  score += 5;  break;
					case 2:  score += 50;  break;
					case 3:  score += 500;  break;
					case 4:  score += 5000;  break;
					default:  break;
					}
				}
			}
			else	//玩家下
			{
				if( pTable[x][y][k] ==1)	//[x][y]是第k个"5"上的一个位置
				{
					//第k个"5"中已经有win[0][k]个位置了
					switch( win[0][k] )
					{
					case 1:  score-=5;  break;
					case 2:  score-=50;  break;
					case 3:  score-=500;  break;
					case 4:  score-=5000;  break;
					default:  break;
					}
				}
			}
		}
		return score;
	}
	
	
	public static void InitBoard() {
		int i, j, k;
		pTable=new Integer[15][15][572];
		cTable=new Integer[15][15][572];
		for (i = 0; i < row; i++){
			pTable[i]=new Integer[15][572];
			cTable[i]=new Integer[15][572];
			for (j = 0; j < col; j++) {
				pTable[i][j]=new Integer[572];
				cTable[i][j]=new Integer[572];
				for (k = 0; k < 572; k++) {
					//pTable[i][j][k]=new Integer();
					pTable[i][j][k] = 0;
					cTable[i][j][k] = 0;
				}
			}
		}

		int count = 0;
		int x,y;
		// 横着的获胜组合
		for (x= 0; x < 15; x++) {
			for (y= 0; y < 11; y++) {
				for (k = 0; k < 5; k++) {
					pTable[x][y+ k][count] = 1;
					cTable[x][y+ k][count] = 1;
				}
				count++;
			}
		}
		
		
		//竖的获胜组合
		for (y = 0;y < 15; y++) {
			for (x = 0; x < 11; x++) {
				for (k = 0; k < 5; k++) {
					pTable[x+k][y][count] = 1;
					cTable[x+k][y][count] = 1;
				}
				count++;
			}
		}
		//主对角线
		for( x = 0; x < 11; x++ )	
		{
			for( y = 0; y < 11; y++ )
			{
				for( k = 0; k < 5; k++ )
				{
					pTable[x+k][y+k][count] = 1;
					cTable[x+k][y+k][count] = 1;
				}
				count++;
			}
		}
		
		//次对角线
		for( x = 4; x < 15; x++ )	
		{
			for( y = 0; y < 11; y++ )
			{
				for( k = 0; k < 5; k++ )
				{
					pTable[x-k][y+k][count] = 1;
					cTable[x-k][y+k][count] = 1;
				}
				count++;
			}
		}
		
		
		
		//初始化win
		win=new Integer[2][572];
		win[0]=new Integer[572];
		win[1]=new Integer[572];
		for( k = 0; k < 572; k++ )	//初始化win数组
			{
			win[0][k] = 0;
			win[1][k] = 0;
			}

		//初始化结束
		
	}//init 结束
	
	
	
}

 

 

自己也知道有很多做的不好的地方,很多需要改进的地方。

欢迎大牛指点!

 



 

  • 大小: 670.6 KB
  • 大小: 670.6 KB
  • 大小: 1 MB
  • 大小: 660.9 KB
  • 大小: 662.7 KB
  • 大小: 976.5 KB
  • 大小: 80.2 KB
分享到:
评论
3 楼 肆无忌惮_ 2014-07-22  
人生难得糊涂 写道
肆无忌惮_ 写道
注释好少啊,看不懂

写了个五子棋人机算法的PPT  你可以下来看看啊

看过了,还是不太明白那个572
2 楼 人生难得糊涂 2014-07-22  
肆无忌惮_ 写道
注释好少啊,看不懂

写了个五子棋人机算法的PPT  你可以下来看看啊
1 楼 肆无忌惮_ 2014-07-22  
注释好少啊,看不懂

相关推荐

Global site tag (gtag.js) - Google Analytics