⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gobang.java

📁 java五子棋人机对战代码
💻 JAVA
字号:
import java.util.Date;
import java.util.Random;
import java.util.concurrent.*;
import javax.swing.JOptionPane;

public final class Gobang {
	
	public static final int  NONE = 0,//无子
								BLACK = 1, //黑子
								WHITE = -1,//白子
								SIZE = 15,
								HUM_VS_AI = 0,
								AI_VS_HUM = 1,
								EAZY = 2,
								HAND = 4,
								WANG = 0,//横方向
								SHAFT = 1,//竖
								R_RAMP = 2,//右斜
								L_RAMP = 3;//左斜
	public static final int  FIVE = 10000,//五连的分数
								L_FOUR = 2000,//活四
								D_FOUR = 1200,//冲四
								L_THREE = 800,//活三
								D_THREE = 180,//冲三
								L_TWO = 80,//活二
								D_TWO = 20;//冲二
	private int model;
	private int aiSide,humSide;
	private int[][] tempB;//棋盘数组
	private int[] rows;//记录行
	private int[] cols;//记录列
	private int level;//级别
	private int stepNum;//步数
	private int winner;//赢家
	private int minRow,maxRow,minCol,maxCol;//控制搜索范围
	private boolean oneRoundisEnd;//一轮是否结束
	private Game frame;
	
	
	public Gobang(Game f, int[][] b ,int m, int l)
	{
		frame = f;
		b = new int[SIZE][SIZE];
		model = m;
		level = l;
		winner = NONE;
		stepNum = 0;
		rows = new int[SIZE*SIZE];
		cols = new int[SIZE*SIZE];
		tempB = new int[SIZE][SIZE];
		for(int r = 0; r<SIZE; r++)
			for(int c = 0; c<SIZE; c++)
				tempB[r][c] = b[r][c];
		if(model == HUM_VS_AI)
		{
			humSide = BLACK;
			aiSide = WHITE;
			frame.rep(SIZE,SIZE,tempB);
		}
		else if(model == AI_VS_HUM)//若电脑下,第一步天元
		{
			humSide = WHITE;
			aiSide = BLACK;
			step(7,7,aiSide);
		}
		oneRoundisEnd = true;
	}
	
	public void setLevel(int l)
	{
		level = l;
	}
	
	private boolean step(int r,int c,int side)//生成一步棋
	{
		if(tempB[r][c] == NONE)
		{
			tempB[r][c] = side;
			rows[stepNum] = r;
			cols[stepNum] = c;
			frame.rep(r,c,tempB);
			stepNum++;
			win(r,c,side);
			if(stepNum == 1)//计算范围
			{
				minRow = r-level-1;
				maxRow = r+level+1;
				minCol = c-level-1;
				maxCol = c+level+1;
			}
			else
			{
				if(r-level-1<minRow) minRow = Math.max(r-level-1,0);
				if(r+level+1>maxRow) maxRow = Math.min(r+level+1,SIZE-1); 
				if(c-level-1<minCol) minCol = Math.max(c-level-1,0); 
				if(c+level+1>maxCol) maxCol = Math.min(c+level+1,SIZE-1);
			}
			return true;
		}
		else
			return false;
	}
	
	public void back()//悔棋
	{
		if(stepNum >1)
		{
			oneRoundisEnd = true;
			winner = NONE;
			stepNum--;
			tempB[rows[stepNum]][cols[stepNum]] = NONE;
			stepNum--;
			tempB[rows[stepNum]][cols[stepNum]] = NONE;
			frame.rep(rows[stepNum-1],cols[stepNum-1],tempB);
		}
	}
	
	private boolean win(int r,int c,int side)//判断是否胜利
	{
		if(	score(side,r,c,WANG)==FIVE||
			score(side,r,c,SHAFT)==FIVE||
			score(side,r,c,L_RAMP)==FIVE||
			score(side,r,c,R_RAMP)==FIVE){
			winner = side;
			String s;
			if(side == BLACK)
				s = "黑方胜";
			else
				s = "白方胜";
			JOptionPane.showMessageDialog(frame, 
										s, "结束",
										JOptionPane.INFORMATION_MESSAGE);
			return true;
		}
		return false;
	}
	

	private void aiPlay(int d)//电脑下,用线程是因为防止与panel的重绘冲突
	{
		ExecutorService exec = Executors.newCachedThreadPool();
		exec.execute(new AI());
	}
	
	
	private boolean humPlay(int row,int col)//人下
	{
		if(step(row,col,humSide)){
			oneRoundisEnd = false;
			return true;
		}
		else
			return false;
	}
	
	public void oneRound(int r,int c)//人机下一轮
	{
		if(oneRoundisEnd && winner==NONE)
			if(humPlay(r,c) && winner==NONE)
				aiPlay(level);
	}
	
	private int score(int side,int r,int c,int direction)//返回一个方向的棋形
	{
		int num = 1,//棋形
			m = 1,n = 1;
		final int ltag = 10,rtag = 100,//两个tag为两端死活标志,为方便switch使用(提高效率)为整型
					a,b;
		switch(direction)
		{
			case WANG   : a = 0; b = 1; break;
			case SHAFT  : a = 1; b = 0; break;
			case R_RAMP : a = 1; b = 1; break;
			case L_RAMP : a = 1; b = -1; break;
			default	: a = 0;  b = 0;
		}
		for(m = 1; m < 5; m++)
		{
			int row = r-a*m, col = c-b*m;
			if(row<0||col>=SIZE||col<0){
				num = num+ltag;//若为死num加上标志,下类同
				break;
			}
			int temp = tempB[row][col];
			if(temp == side)
				num++;
			else if(temp == NONE)
				break;
			else{
				num = num+ltag;
				break;
			}
		}
		for(n = 1; n < 5; n++)
		{
			int row = r+a*n, col = c+b*n;
			if(row>=SIZE||col>=SIZE||col<0){
				num = num+rtag;
				break;
			}
			int temp = tempB[row][col];
			if(temp == side)
				num++;
			else if(temp == NONE)
				break;
			else{
				num = num+rtag;
				break;
			}
		
		}
		int row,col;
		switch(num)
		{
			case 1	:return 0;
			case 11	:return 0;
			case 101:return 0;
			case 111:return 0;
			case 2	:
				m++;
				row = r-a*m;
				col = c-b*m;
				if(row>=0&&col>=0&&col<SIZE)
					if(tempB[row][col]!=-side)
						return L_TWO;
				n++;
				row = r+a*n;
				col = c+b*n;
				if(row<SIZE&&col>=0&&col<SIZE)
					if(tempB[row][col]!=-side)
						return L_TWO;
				return 0;
			case 12	:
				n=n+2;
				row = r+a*n;
				col = c+b*n;
				if(row<SIZE&&col>=0&&col<SIZE)
					if(tempB[row][col]!=-side&&tempB[row-a][col-b]!=-side)
						return D_TWO;
				return 0;
			case 102:
				m=m+2;
				row = r-a*m;
				col = c-b*m;
				if(row>=0&&col>=0&&col<SIZE)
					if(tempB[row][col]!=-side&&tempB[row+a][col+b]!=-side)
						return D_TWO;
				return 0;
			case 112:return 0;
			case 3	:return L_THREE;
			case 13:
				n++;
				row = r+a*n;
				col = c+b*n;
				if(row<SIZE&&col>=0&&col<SIZE)
					if(tempB[row][col]!=-side)
						return D_THREE;
				return 0;
			case 103:
				m++;
				row = r-a*m;
				col = c-b*m;
				if(row>=0&&col>=0&&col<SIZE)
					if(tempB[row][col]!=-side)
						return D_THREE;
				return 0;
			case 113:return 0;
			case 4	:return L_FOUR;
			case 14	:return D_FOUR;
			case 104:return D_FOUR;
			case 114:return 0;
			default :return FIVE;
		}
	}


	final class AI implements Runnable//ai线程类
	{
		
		private int aiR,aiC;//记录电脑所下的位置
		public final int INFINITY = 10000000;
		
		private void play(int d)
		{
			if(stepNum == 1){//第一步在人下周围随机选择
				Random r = new Random(new Date().getTime());
				int row = 0,
					col = 0,
					humR = rows[0],
					humC = cols[0];
				do
				{
					switch(r.nextInt(8))
					{
						case 0: row = humR+1; col = humC+1; break;
						case 1: row = humR+1; col = humC;   break;
						case 2: row = humR+1; col = humC-1; break;
						case 3: row = humR  ; col = humC+1; break;
						case 4: row = humR  ; col = humC-1; break;
						case 5: row = humR-1; col = humC+1; break;
						case 6: row = humR-1; col = humC  ; break;
						case 7: row = humR-1; col = humC-1; break;
					}
				}while(!step(row,col,aiSide));
				 
			}
			else if(!must()){//判断有没有必须应的着,若没,进行搜索
					search(d,aiSide,-INFINITY,INFINITY);
					step(aiR,aiC,aiSide);
			}
			oneRoundisEnd = true;
		}
		
		private int search(int d,int side,int alpha, int beta)
		{//alpha beta搜索
			if(d <= 0)
				return evlation();	
			for (int row = minRow; row <= maxRow; row++)
	    		for (int col = minCol; col <= maxCol; col++)
	    		{
	    			if(tempB[row][col] == NONE)
	    			{	
	    				tempB[row][col] = side;
	    				int v = -search(d-1,-side,-beta,-alpha);
	    				tempB[row][col] = NONE;
	    				if (v >= beta) { 
	    					return beta; 
	    				}
	    				if (v > alpha) {
	    					if(d == level){
	    						aiR = row;
	    						aiC = col;
	    					}
	    					alpha = v; 
	    				} 

	    			}
	    		}
			return alpha;
		}
		
		private boolean must()
		{//判断有没有必须应的着,如五连双三之类
			int aiR = 0,aiC = 0,aiScore = 0,
				humR = 0,humC = 0,humScore = 0;
			for (int r = 0; r < SIZE; r++)
	    		for (int c = 0; c < SIZE; c++){
	    			if(tempB[r][c] == NONE){
	    				int ais =score(aiSide,r,c,WANG)+
							score(aiSide,r,c,SHAFT)+
							score(aiSide,r,c,R_RAMP)+
							score(aiSide,r,c,L_RAMP);
	    				int hums = score(humSide,r,c,WANG)+
							score(humSide,r,c,SHAFT)+
							score(humSide,r,c,R_RAMP)+
							score(humSide,r,c,L_RAMP);
	    				if(aiScore < ais){
	    					aiScore = ais;
	    					aiR = r;
	    					aiC = c;
	    				}
	    				if(humScore < hums){
	    					humScore = hums;
	    					humR = r;
	    					humC = c;
	    				}
	    			
	    			}
	    		}
			if(aiScore>=humScore&&aiScore>=L_THREE*2){
				step(aiR,aiC,aiSide);
				return true;
			}
			if(aiScore<humScore&&humScore>=L_THREE*2){
				step(humR,humC,aiSide);
				return true;
			}					
			return false;
		}
				
		private int evlation()//评价函数
		{
			int s1, s2, s3, s4,score = 0;
			for (int r = minRow; r <= maxRow; r++)
	    		for (int c = minCol; c <= maxRow; c++)
	    			if(tempB[r][c] == NONE)
	    			{
	    				s1=score(aiSide,r,c,WANG)-score(-aiSide,r,c,WANG)/2;
	    				s2=score(aiSide,r,c,SHAFT)-score(-aiSide,r,c,SHAFT)/2;
	    				s3=score(aiSide,r,c,R_RAMP)-score(-aiSide,r,c,R_RAMP)/2;
	    				s4=score(aiSide,r,c,L_RAMP)-score(-aiSide,r,c,L_RAMP)/2;
	    				score = score+s1+s2+s3+s4;
	    			}
			return score;
		}
		
		
		public void run() {
			play(level);
		}
		
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -