五子棋AI程序设计

最近做了一个简单的五子棋游戏,其中涉及到界面的布局设计,以及简单的AI算法的应用。
我创建了五个类。
1、public class ChessJpanel extends JPanel implements Config:这个类中我主要写棋盘的设计以及画面的还原代码。
2、public interface Config:写了一个接口,其中主要是关于棋盘内棋子,网格等尺寸的参数的保存,一般也在此处修改参数。
3、public class DrawFrame:此类中我写界面的初始化设计,主函数也在其中。
4、public class DrawMouse implements ActionListener, MouseMotionListener, MouseListener, Config:这个类中我写了监听器的程序,以及AI算法,这个类也是包含内容最多的类了。用到了动作监听器、鼠标监听器,继承了参数接口。
5、public class Shape implements Config:此类用于设置棋子的位置颜色等参数,继承接口。
我们先贴出界面的部分代码:

public class DrawFrame {
   
		public static void main(String[] args) {
   
			DrawFrame frame = new DrawFrame();
			frame.showUI();
		}
		public void showUI() {
   
			// 创建窗体对象
			javax.swing.JFrame jf = new javax.swing.JFrame();
			ImageIcon img = new ImageIcon("E:\\workspace\\mayifan\\src\\com\\myf\\gobang1030\\timg.jpg");
			JLabel jla = new JLabel(img);
			jf.getLayeredPane().add(jla, new Integer(Integer.MIN_VALUE));
			jla.setBounds(0, 0, 950, 640);
			JPanel jp1 = (JPanel) jf.getContentPane();
			jp1.setOpaque(false); 
			jf.setSize(950, 640);
			//jf.getContentPane().setBackground(Color.ORANGE);//设置背景色
			jf.setTitle("五子棋");
			jf.setDefaultCloseOperation(3);
			// 设置居中显示
			jf.setLocationRelativeTo(null);
			DrawMouse mouse = new DrawMouse();
			JButton jb1=new JButton("新游戏");
			jf.add(jb1);
			jb1.setBounds(675, 185, 100,40);
			jb1.addActionListener(mouse);
			JButton jb2=new JButton("悔棋");
			jf.add(jb2);
			jb2.setBounds(675, 265, 100,40);
			jb2.addActionListener(mouse);				
			JButton jb3=new JButton("人机对战");
			jf.add(jb3);
			jb3.setBounds(675, 345, 100,40);	
			jb3.addActionListener(mouse);
			//棋盘对象
			ChessJpanel cp = new ChessJpanel();
			//cp.setBackground(Color.ORANGE);
			jf.add(cp,BorderLayout.CENTER);			
			cp.setOpaque(false); 		
			cp.addMouseListener(mouse);
			cp.addMouseMotionListener(mouse);	    
			jf.setVisible(true);
			Graphics g=cp.getGraphics();
			mouse.setgr(g);
			mouse.setcp(cp);
			cp.setMouse(mouse);					
		}		
}

我们在界面的底层容器加上了背景图片,添加了几个功能按键,设置了其坐标和大小。创建了一些对象,调用了相应传递对象的方法。并添加了若干监听器。

public class ChessJpanel extends JPanel implements Config{
   
	
	     private Shape[] arrayshape;
	     private DrawMouse mouse;
	     
	     public void setarray(Shape[] arrayshape)
	     {
   
	    	 this.arrayshape=arrayshape;
	     }
	     public void setMouse(DrawMouse mouse) 
	     {
   
	    	 this.mouse=mouse;
	     }
        public void paint (Graphics g)
        {
         	
            super.paint(g); 
           	ImageIcon img = new ImageIcon("E:\\workspace\\mayifan\\src\\com\\myf\\gobang1030\\muban.jpg");//加载图片,绘制图片
           	g.drawImage(img.getImage(), 175, 80, 455, 455, null);         	        	
        	for(int i=0;i<LINE;i++)
        	{
   
    			g.drawLine(X0, Y0+i*SIZE, X0+(LINE-1)*SIZE, Y0+i*SIZE);
    			g.drawLine(X0+i*SIZE, Y0, X0+i*SIZE,  Y0+(LINE-1)*SIZE);    					
        	}
        	g.drawLine(X0-10,Y0-10,X0+(LINE-1)*SIZE+10,Y0-10);
         	g.drawLine(X0-10,Y0+(LINE-1)*SIZE+10,X0+(LINE-1)*SIZE+10,Y0+(LINE-1)*SIZE+10);
        	g.drawLine(X0-10,Y0-10,X0-10,Y0+(LINE-1)*SIZE+10);
        	g.drawLine(X0+(LINE-1)*SIZE+10,Y0-10,X0+(LINE-1)*SIZE+10,Y0+(LINE-1)*SIZE+10);
        	 for(int i=0;i<mouse.index;i++)
             {
   
        		Shape shape=arrayshape[i];
        		if(shape!=null) 
        		{
   
             	shape.drawShape(g);
        		}
        		else
        		break;
             }        	
        }
        public void paint1 (Graphics g)
        {
   
        	super.paint(g);
           	ImageIcon img1 = new ImageIcon("E:\\workspace\\mayifan\\src\\com\\myf\\gobang1030\\muban.jpg");//加载图片,绘制图片
           	g.drawImage(img1.getImage(), 175, 80, 455, 455, null);           
        	for(int i=0;i<LINE;i++)
        	{
   
    			g.drawLine(X0, Y0+i*SIZE, X0+(LINE-1)*SIZE, Y0+i*SIZE);
    			g.drawLine(X0+i*SIZE, Y0, X0+i*SIZE,  Y0+(LINE-1)*SIZE);       		
        	}
        	g.drawLine(X0-10,Y0-10,X0+(LINE-1)*SIZE+10,Y0-10);
         	g.drawLine(X0-10,Y0+(LINE-1)*SIZE+10,X0+(LINE-1)*SIZE+10,Y0+(LINE-1)*SIZE+10);
        	g.drawLine(X0-10,Y0-10,X0-10,Y0+(LINE-1)*SIZE+10);
        	g.drawLine(X0+(LINE-1)*SIZE+10,Y0-10,X0+(LINE-1)*SIZE+10,Y0+(LINE-1)*SIZE+10);        	
        }
}

这里我们写了两个paint函数,一个用于恢复初始的棋盘,一个用于恢复棋盘以及棋子(防止最小化或者窗口伸缩导致画面丢失),我们通过循环绘制棋盘线条和棋子。其中基本上所有参数都来自于接口中定义的属性。
值得一提的是我们用到了HashMap:

 HashMap <String,Integer> map =new HashMap<>();

它的作用是用来做数据的存储和调用,创建权值表:
例如:HashMap<String,Integer> hm = new HashMap<String,Integer>();
<>:泛型(泛指类:类,接口,数组)
hm.put(“1”,20);
hm.put(“11”,200);
hm.put(“111”,2000);
使用方法很简单,通过 hm.get(111);即可获取参数2000。
HashMap在代码中的作用就是为各种棋局赋相应的权值,然后通过遍历的方法,做棋局分析,实现AI。我们本次的思路就是遍历棋盘所有的空格,分别对其“上,下,左,右,左上,左下,右上,右下”八个方向进行棋局判断,即从相邻子开始读取并判断存值,把八个方向的权值相加,便可以得到本空位的权值,遍历棋盘可得到权值最大的空位。自然,权值分为进攻和防守两种,假如执黑子,进攻的权值需要看连续黑子的数量,防守权值需要看连续白子的数量,最终要把进攻最大权值和防守最大权值进行比较,选择进攻或者防守,这样一来电脑就可以代替人去“思考”了。仔细一想,确实,电脑的行棋思路也很符合我们的思维习惯,通过观察棋局来判断是该进攻还是防守,以及该在何处落子。
接下来我们先贴监听器类的完整代码,再分别介绍各个方法的作用。

public class DrawMouse implements ActionListener, MouseMotionListener, MouseListener, Config {
   
	private int x, y, z;
	public int x1,y1;
	private int point_x, point_y;
	private Graphics g;
	private int turn = 0;//0:黑子  1:白子
	private ChessJpanel cp;
	private int flagStart = 0;
	private Shape[] arrayshape = new Shape[250];
	public int index = 0;
	public int winFlag=0; 
	public int flagAi=0;
    public int xMax=0;
	public int yMax=0;
    public int xMax1=0;
	public int yMax1=0;	
	public int weightMax=0;
	public int weightMax1=0;
	public int random;
	int add=1;
	private Color color = Color.BLACK;	
	int value[][] = new int[LINE][LINE];// 0:未存 1:黑 2:白 3:边界	
    HashMap <String,Integer> map =new HashMap<>(); 
	public void setgr(Graphics g) {
   
		this.g = g;
	}
	public void setcp(ChessJpanel cp) {
   
		this.cp = cp;
		this.cp.setarray(arrayshape);
	}
	public void actionPerformed(ActionEvent e)
	{
   
		if ("新游戏".equals(e.getActionCommand())) 
		{
   
			System.out.println("新游戏");			
			turn=0;
			cp.paint1(g);
			flagStart = 1;
			winFlag=0;
			index=0;
			for(int i=0;i<LINE;i++)
			{
   
				for(int j=0;j<LINE;j++)
				{
   
					value[i][j]=0;
				}
			}
			if(flagAi==1)
			{
   				
				random=1+(int)(Math.random()*2);
				if(random==1)//AI 先手,执黑子
				{
   			
					map.put("11110", AI_A_1);//活四连    初始化权重
					map.put("11112", AI_A_2);//死四连
					map.put("11113", AI_A_3);
					map.put("1110",AI_A_4);//活三连
					map.put("1112",AI_A_5);//死三连
					map.put("1113",AI_A_6);
					map.put("110",AI_A_7);//活二连
					map.put("112",AI_A_8);//死二连
					map.put("113",AI_A_9);
					map.put("10",AI_A_10);//活一连
					map.put("12",AI_A_11);//死一连
					map.put("13",AI_A_12);					
					map.put("2", AI_A_13);			
					map.put("0", AI_1);		
					map.put("3", AI_2);
					map.put("22220", AI_G_1);
					map.put("22221", AI_G_2);
					map.put("22223", AI_G_3);
					map.put("2220", AI_G_4);
					map.put("2221", AI_G_5);
					map.put("2223", AI_G_6);
					map.put("220", AI_G_7);
					map.put("221", AI_G_8);
					map.put("223", AI_G_9);
					map.put("20", AI_G_10);
					map.put("21", AI_G_11);
					map.put("23", AI_G_12);
					map.put("1", AI_G_13);
			        value[LINE/2][LINE/2]=1;
					g.setColor(Color.BLACK);
			    	g.drawOval(X0+(LINE/2)*SIZE-CHESS_SIZE/2, Y0+(LINE/2)*SIZE-
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值