Java利用权值法实现简单AI五子棋

前言

利用权值法实现简单的人机五子棋,没有利用博弈树等高深的方法。而且里面的权值判断法都是本人自己设定的,只是基本实现了自动下棋功能,而且时不时会有几步臭棋。

效果图

Java利用权值法实现简单AI五子棋_第1张图片

图片有点大    基本上要实现的功能就是如图所示

实现步骤

UI过程:

1.首先是要将棋盘画出来 再添加按钮,再加监听

所要用到的API类:JFrame  BorderLayout  JPanel  MouseListener  MouseEvent

Graphics  Color   数组

代码示例:

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
public class GobangMain extends JPanel implements GobangConfig{    //界面的实现

	public static void main(String[] args) {
		GobangMain pa=new GobangMain();              //实例化界面对象
		pa.showUI();
	}

	public void setarray(int [][]array) {            //预先对数组初始化(数组用于记录棋子   0 空   1黑子   2白子
		for(int i=0;i

可以看到这里我们继承了GobangConfig接口  先来看看这个接口

public interface GobangConfig {

	public static final int X=20,Y=20,SIZE=50, ROW = 15, COLUMN = 15,QSIZE=40;
	public static final int [][]chessArray=new int [ROW][COLUMN];
	public static final int [][]weightArray=new int [ROW][COLUMN];    //权值数组,每个点的权值分数存储
}

这里我们利用此接口设置了棋盘行列 ROW COLUMN,棋子大小QSIZE  画出来之后每个格子的大小SIZE  ,X Y 为开始画棋盘时离界面边缘的距离

到这里,界面就可以出现了,现在窗体上面已经出现了棋盘,按钮等组件

接下来  自然就是要在棋盘上面画出棋子,这里我们就用到了监听

废话少说,直接上代码:

package 五子棋1;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;

import javax.imageio.ImageIO;
import javax.swing.JLabel;

public class GobangListener extends MouseAdapter implements GobangConfig,ActionListener{

	static HashMap map = new HashMap();           //定义了两个HashMap 键值对,分别用于对电脑和玩家的棋进行对应的评分
	static {
		map.put("012",10);      //眠1
		map.put("210",10);      //眠1
		map.put("010",40);      //活1
		map.put("0110",100);      //活2
		map.put("0112",50);      //眠2
		map.put("2110",50);      //眠2
		map.put("01110",4500);     //活3
		map.put("01112",500);     //眠3
		map.put("21110",500);     //眠3
		map.put("011112",3500);    //眠四
		map.put("211110",3500);    //眠四
		map.put("011110",5500);    //活四
		map.put("21112",80);      //死三
		map.put("211112",100);     //死四
		map.put("2112",60);
		map.put("0111110",20000);   //活五
		map.put("2111110",20000);   //眠五
		map.put("0111112",20000);
	}
	
	static HashMap map2 = new HashMap();
	static {
		map2.put("012",15);      //眠1
		map2.put("210",15);      //眠1
		map2.put("010",55);      //活1
		map2.put("0110",150);      //活2
		map2.put("0112",70);      //眠2
		map2.put("2110",70);      //眠2
		map2.put("01110",6000);     //活3
		map2.put("01112",800);     //眠3
		map2.put("21110",800);     //眠3
		map2.put("011112",9000);    //眠四
		map2.put("211110",9000);    //眠四
		map2.put("011110",20000);    //活四
		map2.put("21112",200);       //
		map2.put("211112",500);     //
		map2.put("2112",30);       //
	}
	
	public GameOver1 robotwin=new GameOver1();      //实例化窗口对象,用于游戏结束后弹出此提示窗口
	public GameOver2 peoplewin=new GameOver2();
	public GobangMain pa;                         //将GobangMain 传到监听,用于调用重绘
	public Graphics2D g;
	private int flag;                             //用于记录当前棋子   黑棋1 白棋2
	public GobangListener(GobangMain pa) {         //传入GobangMain  重写构造函数
		this.pa=pa;
	}
	private int [] hr=new int [150];             //用于记录每次下棋的行位置(用于多次悔棋时使用)
	private int [] hc=new int [150];             //用于记录每次下棋的列位置(用于多次悔棋时使用)
	private int hui=0;                           //记录下棋步数(悔棋时利用)
	private String name="wu";                   //用于记录点击"开始新游戏"之前的状态 
	private String name2;                        
	public void actionPerformed(ActionEvent e) {
		name2=name;                        //用name2记录点击按钮之前的状态
		name=e.getActionCommand();
		if(name.equals("悔棋")&&(name2.equals("玩家对战"))) {
			int m=hr[hui-1];
			int n=hc[hui-1];
			flag=chessArray[m][n];
			chessArray[m][n]=0;
			pa.paint(g);
			hui--;
			name=name2;
		}
		if(name.equals("悔棋")&&(name2.equals("人机对战"))) {
			int m1=hr[hui-1];
			int n1=hc[hui-1];
			int m2=hr[hui-2];
			int n2=hc[hui-2];
			chessArray[m1][n1]=0;
			chessArray[m2][n2]=0;
			pa.paint(g);
			hui=hui-2;
			name=name2;
		}
		if(name.equals("开始新游戏")) {
			for(int i=0;imax) {
					max=weightArray[i][j];
					mi=i;
					mj=j;
				}
			}
		g.setColor(Color.BLACK);                                //电脑在权值最大点处下棋
    	g.fillOval(mi*SIZE+X-QSIZE/2, mj*SIZE+Y-QSIZE/2, QSIZE, QSIZE);
    	hr[hui]=mi;
	    hc[hui]=mj;
	    hui++;
	    chessArray[mi][mj]=1;
	    Check(chessArray[mi][mj],mi,mj);
	}
	
	public int getvalue(int flag1,int flag2) {    //getvalue(1,2)为计算电脑权值    getvalue(2,1) 为计算玩家权值
		int zvalue=0;   
		String code;
		Integer value;
		Integer value1;
		int []flags=new int[8];
		for(int j=0;j0) {
						if(chessArray[i-1][j]==0&&chessArray[i-2][j]==flag1&&chessArray[i-3][j]==flag1&&chessArray[i-4][j]==flag1) {
							if(flag1==1) zvalue=zvalue+3499;
							else zvalue=zvalue+10000;
							flags[2]=1;
						}
						else if(chessArray[i-1][j]==flag1&&chessArray[i-2][j]==0&&chessArray[i-3][j]==flag1&&chessArray[i-4][j]==flag1) {
							if(flag1==1) zvalue=zvalue+3499;
							else zvalue=zvalue+10000;
						}
					}
					if(j-4>0) {
						if(chessArray[i][j-1]==0&&chessArray[i][j-2]==flag1&&chessArray[i][j-3]==flag1&&chessArray[i][j-4]==flag1) {
							if(flag1==1) zvalue=zvalue+3499;
							else zvalue=zvalue+10000;
							flags[3]=1;
						}
						else if(chessArray[i][j-1]==flag1&&chessArray[i][j-2]==0&&chessArray[i][j-3]==flag1&&chessArray[i][j-4]==flag1) {
							if(flag1==1) zvalue=zvalue+3499;
							else zvalue=zvalue+10000;
						}
					}
					if((i+40)&&(j-4>0)) {
						if(chessArray[i-1][j-1]==0&&chessArray[i-2][j-2]==flag1&&chessArray[i-3][j-3]==flag1&&chessArray[i-4][j-4]==flag1) {
							if(flag1==1) zvalue=zvalue+3499;
							else zvalue=zvalue+10000;
							flags[5]=1;
						}
						else if(chessArray[i-1][j-1]==flag1&&chessArray[i-2][j-2]==0&&chessArray[i-3][j-3]==flag1&&chessArray[i-4][j-4]==flag1) {
							if(flag1==1) zvalue=zvalue+3499;
							else zvalue=zvalue+10000;
						}
					}
					if((i+40)) {
						if(chessArray[i+1][j-1]==0&&chessArray[i+2][j-2]==flag1&&chessArray[i+3][j-3]==flag1&&chessArray[i+4][j-4]==flag1) {
							if(flag1==1) zvalue=zvalue+3499;
							else zvalue=zvalue+10000;
							flags[6]=1;
						}
						else if(chessArray[i+1][j-1]==flag1&&chessArray[i+2][j-2]==0&&chessArray[i+3][j-3]==flag1&&chessArray[i+4][j-4]==flag1) {
							if(flag1==1) zvalue=zvalue+3499;
							else zvalue=zvalue+10000;
						}
					}
					if((j+40)) {
						if(chessArray[i-1][j+1]==0&&chessArray[i-2][j+2]==flag1&&chessArray[i-3][j+3]==flag1&&chessArray[i-4][j+4]==flag1) {
							if(flag1==1) zvalue=zvalue+3499;
							else zvalue=zvalue+10000;
							flags[7]=1;
						}
						else if(chessArray[i-1][j+1]==flag1&&chessArray[i-2][j+2]==0&&chessArray[i-3][j+3]==flag1&&chessArray[i-4][j+4]==flag1) {
							if(flag1==1) zvalue=zvalue+3499;
							else zvalue=zvalue+10000;
						}
					}
					
					
					
					if(i+30) {
						if(chessArray[i-1][j]==0&&chessArray[i-2][j]==flag1&&chessArray[i-3][j]==flag1&&flags[2]!=1) {
							if(flag1==1) zvalue=zvalue+3300;
							else zvalue=zvalue+5500;
							flags[2]=1;
						}
					}
					if(j-3>0) {
						if(chessArray[i][j-1]==0&&chessArray[i][j-2]==flag1&&chessArray[i][j-3]==flag1&&flags[3]!=1) {
							if(flag1==1) zvalue=zvalue+3300;
							else zvalue=zvalue+5500;
							flags[3]=1;
						}
					}
					if((i+30)&&(j-3>0)) {
						if(chessArray[i-1][j-1]==0&&chessArray[i-2][j-2]==flag1&&chessArray[i-3][j-3]==flag1&&flags[5]!=1) {
							if(flag1==1) zvalue=zvalue+3300;
							else zvalue=zvalue+5500;
							flags[5]=1;
						}
					}
					if((i+30)) {
						if(chessArray[i+1][j-1]==0&&chessArray[i+2][j-2]==flag1&&chessArray[i+3][j-3]==flag1&&flags[6]!=1) {
							if(flag1==1) zvalue=zvalue+3300;
							else zvalue=zvalue+5500;
							flags[6]=1;
						}
					}
					if((j+30)) {
						if(chessArray[i-1][j+1]==0&&chessArray[i-2][j+2]==flag1&&chessArray[i-3][j+3]==flag1&&flags[7]!=1) {
							if(flag1==1) zvalue=zvalue+3300;
							else zvalue=zvalue+5500;
							flags[7]=1;
						}
					}
					
					
					
					if(i>0) {                                         //水平方向判断————————————
						if(chessArray[i-1][j]==flag1) code="3";        //避免重复判断
						if(chessArray[i-1][j]==0) code="0";
						else code="2";
					}
					else {          //处于边界位置时
						code="2";
					}
					for(int ti=i;ti0) {                                           //竖直方向判断
						if(chessArray[i][j-1]==flag1) code="3";
						if(chessArray[i][j-1]==0) code="0";
						else code="2";
					}
					else code="2";
					for(int tj=j;tj0&&j>0) {                                     //斜向右下判断 
						if(chessArray[i-1][j-1]==flag1) code="3";
						else if(chessArray[i-1][j-1]==flag2) code="2";
						else code="0";
					}
					else code="2";
					int ti=i,tj=j;
					int min=(chessArray.length-ti)<(chessArray[0].length-tj)? (chessArray.length-ti):(chessArray[0].length-tj);
					for(int m=0;m0&&j>0) {                                     //斜向左下判断
						if(chessArray[i+1][j-1]==flag1) code="3";
						else if(chessArray[i+1][j-1]==flag2) code="2";
						else code="0";
					}
					else code="2";
					ti=i;
					tj=j;
					min=ti<(chessArray[0].length-tj)? ti:(chessArray[0].length-tj);
					for(int m=0;m=0;i--){      //纵向
			if(chessArray[x][i]==f) count++;
			else break;
		}
		for(int i=y+1;i=0;i--){      //横向
				if(chessArray[i][y]==f) count++;
				else break;
			}
			for(int i=x+1;i


几点说明,除了里面的权值函数,其他的悔棋,玩家自己对战,等等都已经实现了基本的使用, 其中最多的就是对棋局打分的函数,个人认为这个函数依每个人想法不同而不同,读者尽量还是自己想想    完全可以按照自己的思路来写  更有大牛可以用博弈树等高端手法    本人写的权值判断函数个人认为一般,还算基础   大家对此还是看看就行,因为本人实在写得杂乱无章()

忘了把窗体代码加上   补一个:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;


public class GameOver1 extends JFrame{

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		GameOver1 frame=new GameOver1();
		frame.setUI();
	}

	public void setUI() {
		this.setTitle("结束窗口");
		this.setDefaultCloseOperation(3);
		this.setLocationRelativeTo(null);
		this.setSize(300, 300);
		
		JLabel l=new JLabel("        电脑胜利!");
		JLabel l2=new JLabel();
		l2.setLayout(new FlowLayout());
		Font F=new Font("楷体",Font.BOLD+ Font.ITALIC,20);
		l.setFont(F);
		JButton b=new JButton("确定");
		l2.add(b);
		b.setPreferredSize(new Dimension(80,40));
		this.setLayout(new BorderLayout());
		this.add(l,BorderLayout.NORTH);
		this.add(l2,BorderLayout.CENTER);
		this.setVisible(true);
		
	}
}

还有一个:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class GameOver2 extends JFrame{

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		GameOver2 frame=new GameOver2();
		frame.setUI();
	}

	public void setUI() {
		this.setTitle("结束窗口");
		this.setDefaultCloseOperation(3);
		this.setLocationRelativeTo(null);
		this.setSize(300, 300);
		
		JLabel l=new JLabel("        玩家胜利!");
		JLabel l2=new JLabel();
		l2.setLayout(new FlowLayout());
		Font F=new Font("楷体",Font.BOLD+ Font.ITALIC,20);
		l.setFont(F);
		JButton b=new JButton("确定");
		l2.add(b);
		b.setPreferredSize(new Dimension(80,40));
		this.setLayout(new BorderLayout());
		this.add(l,BorderLayout.NORTH);
		this.add(l2,BorderLayout.CENTER);
		this.setVisible(true);
		
	}
}
end

你可能感兴趣的:(Java项目学习)