基于Alphabet剪枝的五子棋AI

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">之前无聊写的,代码在附件里,仅供参考- -   AB剪枝只有2层,所以AI战斗力很渣。。</span>

AB.java

class AB {
	static int round=1;
	static int n=Jframe.n;
	static int G[][]=new int[20][20];
	static int INF=10000;
	static void copy(int a[][],int b[][]){
		for(int i=0;i<=n;i++){
			for(int j=0;j<=n;j++){
				b[i][j]=a[i][j];
			}
		}
	}
	static int checkVictory(int G[][]){   //黑方胜利返回1,白方胜利返回-1,还没分出胜负返回0
		for(int i=0;i<=n;i++){
			int sum=0,now=0;   //对于每行,从左向右扫
			for(int j=0;j<=n;j++){   
				if(G[i][j]!=now){
					now=G[i][j];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==5){
					return now;
				}
			}
			sum=0;now=0;   //对于每列,从右向左扫
			for(int j=0;j<=n;j++){
				if(G[j][i]!=now){
					now=G[j][i];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==5){
					return now;
				}
			}
			sum=0;now=0;
			for(int j=0;i+j<=n;j++){
				if(G[i+j][j]!=now){
					now=G[i+j][j];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==5){
					return now;
				}
			}
			sum=0;now=0;
			for(int j=0;i+j<=n;j++){
				if(G[j][i+j]!=now){
					now=G[j][i+j];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==5){
					return now;
				}
			}
			sum=0;now=0;
			for(int j=0;i-j>=0;j++){
				if(G[j][i-j]!=now){
					now=G[j][i-j];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==5){
					return now;
				}
			}
			sum=0;now=0;
			for(int j=0;i+j<=n;j++){
				if(G[i+j][n-j]!=now){
					now=G[i+j][n-j];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==5){
					return now;
				}
			}
		}
		return 0;
	}
	static int max(int a,int b){
		if(a>b)return a;
		return b;
	}
	static int min(int a,int b){
		if(a<b)return a;
		return b;
	}
	static int alphabeta(int G[][],int player,int alpha,int beta,int depth){
		if(depth==2) return getScore(G);
		for(int i=0;i<=n;i++){
			for(int j=0;j<=n;j++){
				if(G[i][j]!=0)continue;
				int curG[][]=new int[20][20];
				copy(G,curG);
				curG[i][j]=player;
				int v=alphabeta(curG,player*-1,alpha,beta,depth+1);
				if(player==-1)alpha=max(alpha,v); else beta=min(beta,v);
				if(beta<=alpha) break;
			}
		}
		if(player==-1) return alpha;
		return beta;
	}
	/*
	 * 
	 初步决定估值为双方活三数和活二数。
           以黑白方不同而参数权重不同。
           如果己方占据先机,则估值以自己活三活二数为重。
           如果己方不利,则尽量消除对方活二数。
           一条线连续两个子并且该线两子无对方子为活二。(不连续,两子之间有一空格也算活二)
           活三则是在活二基础上下一个子。
           死三是活三被对方防守一子。
           活四……如果有活四,就已经胜利了。
           有死四或者活三,就必须要防守了。
           以这些参数乘以权值,作为估值函数。
	 */
	static int getScore(int G[][]){
		int score=0;
		// [0]代表ai,[2]代表我方
		int h2[]=new int[3],h3[]=new int[3],h4[]=new int [3];
		//int h2=0,h3=0,h4=0,h5=0;
		int s3[]=new int[3],s4[]=new int [3];
		int hs5[]=new int [3];
		
		for(int i=0;i<=n;i++){
			int sum=0,now=0;   //对于每行,从左向右扫
			for(int j=0;j<=n;j++){   
				if(G[i][j]!=now){
					now=G[i][j];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==2){
					if(j-sum>=0&&j+1<=n)
						if(G[i][j-sum]==0&&G[i][j+1]==0)
					        h2[now+1]++;
				}else if(sum==3){
					if(j-sum>=0&&j+1<=n)
						if(G[i][j-sum]==0&&G[i][j+1]==0)
					        h3[now+1]++;
					s3[now+1]++;
				}else if(sum==4){
					if(j-sum>=0&&j+1<=n)
						if(G[i][j-sum]==0&&G[i][j+1]==0)
					        h4[now+1]++;
					s4[now+1]++;
				}else if(sum==5){
					hs5[now+1]++;
				}
			}
			sum=0;now=0;   //对于每列,从右向左扫
			for(int j=0;j<=n;j++){
				if(G[j][i]!=now){
					now=G[j][i];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==2){
					if(j-sum>=0&&j+1<=n)
						if(G[j-sum][i]==0&&G[j+1][i]==0)
					        h2[now+1]++;
				}else if(sum==3){
					if(j-sum>=0&&j+1<=n)
						if(G[j-sum][i]==0&&G[j+1][i]==0)
					        h3[now+1]++;
					s3[now+1]++;
				}else if(sum==4){
					if(j-sum>=0&&j+1<=n)
						if(G[j-sum][i]==0&&G[j+1][i]==0)
					        h4[now+1]++;
					s4[now+1]++;
				}else if(sum==5){
					hs5[now+1]++;
				}
			}
			sum=0;now=0;
			for(int j=0;i+j<=n;j++){
				if(G[i+j][j]!=now){
					now=G[i+j][j];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==2){
					if(j-sum>=0&&j+1<=n)
						if(G[i+j-sum][j-sum]==0&&G[i+j+1][j+1]==0)
					        h2[now+1]++;
				}else if(sum==3){
					if(j-sum>=0&&j+1<=n)
						if(G[i+j-sum][j-sum]==0&&G[i+j+1][j+1]==0)
					        h3[now+1]++;
					s3[now+1]++;
				}else if(sum==4){
					if(j-sum>=0&&j+1<=n)
						if(G[i+j-sum][j-sum]==0&&G[i+j+1][j+1]==0)
					        h4[now+1]++;
					s4[now+1]++;
				}else if(sum==5){
					hs5[now+1]++;
				}
			}
			sum=0;now=0;
			for(int j=0;i+j<=n;j++){
				if(G[j][i+j]!=now){
					now=G[j][i+j];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==2){
					if(j-sum>=0&&i+j+1<=n)
						if(G[j-sum][i+j-sum]==0&&G[j+1][i+j+1]==0)
					        h2[now+1]++;
				}else if(sum==3){
					if(j-sum>=0&&j+1<=n)
						if(G[j-sum][i+j-sum]==0&&G[j+1][i+j+1]==0)
					        h3[now+1]++;
					s3[now+1]++;
				}else if(sum==4){
					if(j-sum>=0&&j+1<=n)
						if(G[j-sum][i+j-sum]==0&&G[j+1][i+j+1]==0)
					        h4[now+1]++;
					s4[now+1]++;
				}else if(sum==5){
					hs5[now+1]++;
				}
			}
			sum=0;now=0;
			for(int j=0;i-j>=0;j++){
				if(G[j][i-j]!=now){
					now=G[j][i-j];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==2){
					if(j-sum>=0&&i-j-1>=0)
						if(G[j-sum][i-j+sum]==0&&G[j+1][i-j-1]==0)
					        h2[now+1]++;
				}else if(sum==3){
					if(j-sum>=0&&i-j-1>=0)
						if(G[j-sum][i-j+sum]==0&&G[j+1][i-j-1]==0)
					        h3[now+1]++;
					s3[now+1]++;
				}else if(sum==4){
					if(j-sum>=0&&i-j-1>=0)
						if(G[j-sum][i-j+sum]==0&&G[j+1][i-j-1]==0)
					        h4[now+1]++;
					s4[now+1]++;
				}else if(sum==5){
					hs5[now+1]++;
				}
			}
			sum=0;now=0;
			for(int j=0;i+j<=n;j++){
				if(G[i+j][n-j]!=now){
					now=G[i+j][n-j];
					sum=1;
				}else{
					if(now!=0)
					sum++;
				}
				if(sum==2){
					if(i+j+1<=n&&n-j+sum<=n)
						if(G[i+j-sum][n-j+sum]==0&&G[i+j+1][n-j-1]==0)
					        h2[now+1]++;
				}else if(sum==3){
					if(i+j+1<=n&&n-j+sum<=n)
						if(G[i+j-sum][n-j+sum]==0&&G[i+j+1][n-j-1]==0)
					        h3[now+1]++;
					s3[now+1]++;
				}else if(sum==4){
					if(i+j+1<=n&&n-j+sum<=n)
						if(G[i+j-sum][n-j+sum]==0&&G[i+j+1][n-j-1]==0)
					        h4[now+1]++;
					s4[now+1]++;
				}else if(sum==5){
					hs5[now+1]++;
				}
			}
		}
		score=h2[0]*10-h2[2]*8+h3[0]*100-h3[2]*100+s3[0]*20-s3[2]*20;
		score+=h4[0]*1000-h4[2]*1500;
		score+=s4[0]*30-s4[2]*30;
		score+=hs5[0]*5000-hs5[2]*5000;
		return score;
	}
}


begin.java

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Iterator;


public class begin { 
	static Jframe local;
	static int clicknum=0;
	static int over=0;
public static void main (String args[]) { 
	local=new Jframe(); 
    
    while(true){  
    	int last=clicknum;
        Point point = MouseInfo.getPointerInfo().getLocation();  
        if(clicknum>last)
        Jframe.turnPC();
       // System.out.println(point);  
      //  try { Thread.sleep(100); } catch (InterruptedException e) { }  
    
    }  
 } 
}


Jframe.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

class Jframe extends JFrame{ 
static int width=800,height=800,n=15,r=23;
static int  w=width/n,h=height/n,beg=60;
ArrayList<Point> points = null;
public Jframe(){ 
   points = new ArrayList<Point>();
   this.setTitle("老西五子棋v1.0(电脑弱智版)");
   this.setSize(width+100,height+100); 
   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
   setVisible(true); 
   this.addMouseListener(new MyMouseListener());
   this.addWindowListener(new WindowAdapter(){
	   public void windowClosing(WindowEvent e)
	   {
	    setVisible(false);
	    System.exit(0);
	   }
	  });
   this.setBackground(Color.GREEN);
} 
@Override 
public void paint(Graphics g) { 
       super.paint(g); 
       //画边界
       g.setColor(Color.GRAY);
       for(int i=0;i<=n;i++){
    	   g.drawLine(beg+i*w, beg, beg+i*w, beg+n*h);
       }
       for(int i=0;i<=n;i++){
    	   g.drawLine(beg, beg+i*h, beg+n*w, beg+i*h);
       }
       // 画棋子
       
       Iterator<Point> it = points.iterator();
       Color c = g.getColor();
       while(it.hasNext())
       {
        qi p = (qi)it.next();
        if(p.color==1)
        	g.setColor(Color.black);
        else
        	g.setColor(Color.yellow);
        g.fillOval(p.x-r,p.y-r,2*r,2*r);
        if(it.hasNext()==false){
        	g.setColor(Color.red);
        	g.fillOval(p.x-4,p.y-4,8,8);
        }
       }
       g.setColor(Color.black);
       if(AB.round%2==1)
       g.drawString("轮到黑方", beg, beg+n*h+20);
       else
       g.drawString("轮到白方", beg, beg+n*h+20);
       System.out.println();
       for(int i=0;i<=n;i++){
    	   for(int j=0;j<=n;j++){
    		   System.out.print(AB.G[i][j]+" ");
    	   }System.out.println();
       }
       int ans=AB.checkVictory(AB.G);
       if(ans==1){
    	   JOptionPane.showMessageDialog(null, "黑方获胜!"); 
    	 
       }else if(ans==-1){
    	   JOptionPane.showMessageDialog(null, "白方获胜!"); 
    	   
       }
       if(ans!=0){
    	   points.clear();
    	   for(int i=0;i<=n;i++){
    		   for(int j=0;j<=n;j++){
    			   AB.G[i][j]=0;
    		   }
    	   }
    	   AB.round=1;
    	   begin.clicknum=0;
       }
} 
public double dis(double x1,double y1,double  x2,double y2){
	return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

public void addPoint(Point p)
{
 int flag=0;
 for(int i=0;i<=n;i++){
	 for(int j=0;j<=n;j++){
		 if(dis(beg+i*w,beg+j*h,p.x,p.y)<25){
			 flag=1;
			 p.x=beg+i*w;p.y=beg+j*h;
			 break;
		 }
	 }
	 if(flag==1) break;
 }
 if(flag==0)return ;
 Iterator<Point> i = points.iterator();
 while(i.hasNext())
 {
  qi k = (qi)i.next();
  if(k.x==p.x&&k.y==p.y){
	  JOptionPane.showMessageDialog(null, "该区域已经有子,请您重放~"); 
	  return ;
  }
 }
 
 qi temp= new qi(p.x,p.y);
 if(AB.round%2==1){
	 temp.color=1;
 }else{
	 temp.color=-1;
 }
 AB.G[(temp.y-beg)/h][(temp.x-beg)/w]=temp.color;
 AB.round++;
 points.add(temp);
}
  
  static void turnPC(){
	  if(AB.checkVictory(AB.G)!=0)return ;
	  Jframe mf=begin.local;
	  Point ansp = new Point(AB.round/2%(AB.n+1),AB.round/2/(AB.n+1));
	     int maxx=-AB.INF;
	     for(int i=0;i<=AB.n;i++){
	    	 for(int j=0;j<=AB.n;j++){
	    		 if(AB.G[i][j]!=0)continue;
	    		 //下子范围
	    		 if(AB.round<=4){
	    			 int flag=1;
		    		 if(i>=1&&i<=n-1&&j>=1&&j<=n-1){
		    			 for(int k=i-1;k<=i+1;k++){
		    				 for(int l=j-1;l<=j+1;l++){
		    					 if(AB.G[k][l]==-1||AB.G[k][l]==1)
		    						 flag=0;
		    				 }if(flag==0) break;
		    			 }
		    		 }
		    		 if(flag==1)continue;
	    		 }
	    		 int curG[][]=new int[20][20];
	    		 AB.copy(AB.G, curG);
	    		 curG[i][j]=-1;
	    	     int k=AB.alphabeta(curG,1,-AB.INF,AB.INF,1);
	    	   //  System.out.print(k+" ");
	    		 if(k>maxx){
	    			 maxx=k;ansp.x=j;ansp.y=i;
	    		 }
	    	 }
	     }
	     ansp.x*=Jframe.w;ansp.x+=Jframe.beg;
	     ansp.y*=Jframe.h;ansp.y+=Jframe.beg;
	     mf.addPoint(ansp);
	     mf.repaint();
  }

} 
class MyMouseListener extends MouseAdapter
{
 public void mouseClicked(MouseEvent e)
 {
	 if(AB.round%2==0)return ;
	 Jframe mf = (Jframe)e.getSource();
	 int before=AB.round;
     mf.addPoint((new Point(e.getX(),e.getY())));
     mf.repaint();
     if(before==AB.round)return ;
     begin.clicknum++;
 }
 
}


qi.java

import java.awt.Point;


class qi extends Point{
	int color;
	qi(int a,int b){
		super(a,b);
	}
}



  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
======================================================================== MICROSOFT FOUNDATION CLASS LIBRARY : fir ======================================================================== AppWizard has created this fir application for you. This application not only demonstrates the basics of using the Microsoft Foundation classes but is also a starting point for writing your application. This file contains a summary of what you will find in each of the files that make up your fir application. fir.dsp This file (the project file) contains information at the project level and is used to build a single project or subproject. Other users can share the project (.dsp) file, but they should export the makefiles locally. fir.h This is the main header file for the application. It includes other project specific headers (including Resource.h) and declares the CFirApp application class. fir.cpp This is the main application source file that contains the application class CFirApp. fir.rc This is a listing of all of the Microsoft Windows resources that the program uses. It includes the icons, bitmaps, and cursors that are stored in the RES subdirectory. This file can be directly edited in Microsoft Visual C++. fir.clw This file contains information used by ClassWizard to edit existing classes or add new classes. ClassWizard also uses this file to store information needed to create and edit message maps and dialog data maps and to create prototype member functions. res\fir.ico This is an icon file, which is used as the application's icon. This icon is included by the main resource file fir.rc. res\fir.rc2 This file contains resources that are not edited by Microsoft Visual C++. You should place all resources not editable by the resource editor in this file. ///////////////////////////////////////////////////////////////////////////// For the main frame window: MainFrm.h, MainFrm.cpp These files contain the frame class CMainFrame, which is derived from CFrameWnd and controls all SDI frame features. ///////////////////////////////////////////////////////////////////////////// AppWizard creates one document type and one view: firDoc.h, firDoc.cpp - the document These files contain your CFirDoc class. Edit these files to add your special document data and to implement file saving and loading (via CFirDoc::Serialize). firView.h, firView.cpp - the view of the document These files contain your CFirView class. CFirView objects are used to view CFirDoc objects. ///////////////////////////////////////////////////////////////////////////// Other standard files: StdAfx.h, StdAfx.cpp These files are used to build a precompiled header (PCH) file named fir.pch and a precompiled types file named StdAfx.obj. Resource.h This is the standard header file, which defines new resource IDs. Microsoft Visual C++ reads and updates this file. ///////////////////////////////////////////////////////////////////////////// Other notes: AppWizard uses "TODO:" to indicate parts of the source code you should add to or customize. If your application uses MFC in a shared DLL, and your application is in a language other than the operating system's current language, you will need to copy the corresponding localized resources MFC42XXX.DLL from the Microsoft Visual C++ CD-ROM onto the system or system32 directory, and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation. For example, MFC42DEU.DLL contains resources translated to German.) If you don't do this, some of the UI elements of your application will remain in the language of the operating system. /////////////////////////////////////////////////////////////////////////////
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值