java五子棋(AI)

2019 精帖
0 821

java实现五子棋人机对战

menu.saveimg.savepath20190320192020.jpg

package fir;
import java.awt.*;  
import javax.swing.JPanel;  
/** 
 * 有背景图片的Panel类 
 * @author tntxia 
 */  
public class BackgroundPanel extends JPanel {  
    private static final long serialVersionUID = -6352788025440244338L;  
    private Image image = null;  
    public BackgroundPanel(Image image) {  
        this.image = image;  
    }  
    // 固定背景图片,允许这个JPanel可以在图片上添加其他组件  
    protected void paintComponent(Graphics g) {  
        g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), this);  
    }  
}
package fir;
/**
 * 初始化
 * @author Administrator
 */
public class Ready {
	private int x;
	private int y;
	private int count;
	
	public int getCount(){
		return this.count;
	}
	/**
	 * 计算所有赢法种类
	 * @return
	 */
	public Ready(int x,int y){
		this.x=x;
		this.y=y;
		count=initCount();
	}
	private int initCount(){
		int count=0;
		for (int i = 0; i < x; i++) {
			for (int j = 0; j < y-4; j++) {
				count++;
			}
		}
		// 横线上
		for (int i = 0; i < x; i++) {
			for (int j = 0; j < y-4; j++) {
				count++;
			}
		}
		// 斜线上
		for (int i = 0; i < x-4; i++) {
			for (int j = 0; j < y-4; j++) {
				count++;
			}
		}
		// 反斜线上
		for (int i = 0; i < x-4; i++) {
			for (int j = y-1; j > 3; j--) {
				count++;
			}
		}
		return count;
	}
	/**
	 * 初始化所有赢法
	 * @param c
	 * @return
	 */
	public boolean[][][] initChess(){
		boolean wins[][][]=new boolean[15][15][this.count];
		int count=0;
		for (int i = 0; i < x; i++) {
			for (int j = 0; j < y-4; j++) {
				for (int k = 0; k < 5; k++) {
					wins[i][j + k][count] = true;
				}
				count++;
			}
		}
		for (int i = 0; i < x; i++) {
			for (int j = 0; j < y-4; j++) {
				for (int k = 0; k < 5; k++) {
					wins[j + k][i][count] = true;
				}
				count++;
			}
		}
		for (int i = 0; i < x-4; i++) {
			for (int j = 0; j < y-4; j++) {
				for (int k = 0; k < 5; k++) {
					wins[i + k][j + k][count] = true;
				}
				count++;
			}
		}
		for (int i = 0; i < x-4; i++) {
			for (int j = y-1; j > 3; j--) {
				for (int k = 0; k < 5; k++) {
					wins[i + k][j - k][count] = true;//记录赢得可能性
				}
				count++;
			}
		}
		return wins;
	}
	
	public int[] getMyWin(){
		int []myWin=new int[count];
		return myWin;
	}
	
	public int[] getConputerWin(){
		int []conputer=new int[count];
		return conputer;
	}
	/**
	 * 初始化棋盘
	 * @return
	 */
	public int[][] getChessBorad(){
		int [][]chessBorad=new int[x][y];
		return chessBorad;
	}
}
package fir;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Toolkit;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.ActionEvent;
import javax.swing.border.BevelBorder;
import javax.swing.JLabel;
import java.awt.Color;
/**
 * 五子棋
 * @author Administrator
 * 
 * 棋子的大小为46像素(宽/高)
 * 棋盘的大小为690像素(宽/高)
 * 有效棋子总量(14*14)
 */
public class Fir extends JFrame {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JPanel contentPane;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Fir frame = new Fir();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	
	public static int s=0;
	
	public static boolean wins[][][];//五子棋的所有赢法,前两维代表棋盘,第三位代表所有赢法,每一个棋子都可以有多种赢法。
	public static int[] myWin;//我方第i中赢法中,有n颗棋子,如果有5颗棋子代表已经赢了,例如:myWin[5]=2;代表第5中赢法中,已经有2颗棋子,
	public static int[] computerWin;//计算机方第i中赢法中,有n颗棋子
	public static int[][] chessBorad;//代表棋盘,值0代表没有下棋子,其他值代表已经下棋子了。
	
	public Ready re=new Ready(15,15);//初始化数据
	
	public boolean me=true;//true代表应该我方下棋
	public boolean over=false;//游戏是否结束
	
	JPanel panel=null;
	public Fir() {//初始化界面
		wins=re.initChess();
		myWin=re.getMyWin();
		computerWin=re.getConputerWin();
		chessBorad=re.getChessBorad();
		
		setTitle("fir");
		
		Toolkit kit = Toolkit.getDefaultToolkit(); // 定义工具包 
		Dimension screenSize = kit.getScreenSize(); // 获取屏幕的尺寸 
		int screenWidth = screenSize.width; // 获取屏幕的宽
		int screenHeight = screenSize.height; // 获取屏幕的高
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds((screenWidth-700)/2, (screenHeight-780)/2, 715, 770);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		this.setResizable(false);
		
		Image image=new ImageIcon("image/background.jpg").getImage();
		panel = new BackgroundPanel(image);//初始化背景面板
		panel.setForeground(Color.BLACK);
		panel.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
		panel.setBounds(10, 10, 690, 690);
		contentPane.add(panel);
		panel.setLayout(null);
		
		JButton btnBegin = new JButton("begin");
		btnBegin.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
			}
		});
		btnBegin.setBounds(10, 710, 93, 23);
		contentPane.add(btnBegin);
		
		JButton btnRestart = new JButton("restart");
		btnRestart.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			}
		});
		btnRestart.setBounds(113, 710, 93, 23);
		contentPane.add(btnRestart);
		
		JButton btnClose = new JButton("close");//退出
		btnClose.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		btnClose.setBounds(216, 710, 93, 23);
		contentPane.add(btnClose);
		
		/**
		 * 鼠标点击事件
		 */
		panel.addMouseListener(new MouseListener() {
			public void mouseReleased(MouseEvent e) { }//鼠标抬起			
			public void mousePressed(MouseEvent e) { }//鼠标按下			
			public void mouseExited(MouseEvent e) { }//鼠标离开		
			public void mouseEntered(MouseEvent e) { }//鼠标进入		
			public void mouseClicked(MouseEvent e) {//鼠标点击
				if(!me||over){//如果不该我方下棋或已结束,则返回
					return;
				}
				/**
				 * 计算点击时棋盘位置,坐标位置
				 */
				int i=e.getX();//棋盘位置(像素)
				int j=e.getY();//棋盘位置(像素)
				
				int px=i%46;//通过鼠标点击的位置计算棋子应该下的位置
				int py=j%46;//通过鼠标点击的位置计算棋子应该下的位置
				i=i-(px)+(px<=23?-23:23);//通过鼠标点击的位置计算棋子应该下的位置
				j=j-(py)+(py<=23?-23:23);//通过鼠标点击的位置计算棋子应该下的位置
				
				int x=(i+23)/46;//坐标位置(数组)
				int y=(j+23)/46;//坐标位置(数组)
				if(x==0||y==0||x>=15||y>=15){//规则:第一行,第一列不能下棋。
					return ;
				}
				myStep(i,j,x,y);//我方下棋,
			}
		});
	}
	/**
	 * 我下棋
	 * @param i
	 * @param j
	 * @param x
	 * @param y
	 */
	public void myStep(int i,int j,int x,int y){
		if (chessBorad[x][y] == 0) {
			play(i,j);
			chessBorad[x][y] = 1;
			for (int k = 0; k < re.getCount(); k++) {
				if (wins[x][y][k]) {
					myWin[k]++;
					computerWin[k] = 999;
					if (myWin[k] == 5) {
						System.out.println("my win");
						over=true;
						return;
					}
				}
			}
		}
		me=!me;
		computerStep();
	}
	/**
	 * 计算机下棋
	 */
	public void computerStep(){
		if(over){//游戏结束
			return;
		}
		int myScore[][] = new int[15][15];//评估我方评分
		int computerScore[][] = new int[15][15];//评估计算机评分
		int max = 0;
		int x = 0;
		int y = 0;
		// 遍历棋盘
		for (int i = 1; i < 15; i++) {//x轴
			for (int j = 1; j < 15; j++) {//y轴
				if (chessBorad[i][j] == 0) {// 当前可落子,如果不等于0代表已经有棋子
					for (int k = 0; k < re.getCount(); k++) { // 每个点都在 多种赢法中,所以要遍历所有赢法
						if (wins[i][j][k]) {// 计算他在K赢法中的 重要性
							switch (myWin[k]) {//我方棋路,当前赢法中已经连上了几颗棋子
								case 1:
									myScore[i][j] += 200;
									break;
								case 2:
									myScore[i][j] += 400;
									break;
								case 3:
									myScore[i][j] += 2000;
									break;
								case 4:
									myScore[i][j] += 10000;
									break;
							}
							switch (computerWin[k]) {//计算机棋路,当前赢法中已经连上了几颗棋子
								case 1:
									computerScore[i][j] += 300;
									break;
								case 2:
									computerScore[i][j] += 500;
									break;
								case 3:
									computerScore[i][j] += 3000;
									break;
								case 4:
									computerScore[i][j] += 20000;
									break;
							}
						}
					}
					// 玩家最重要的落点
					if (myScore[i][j] > max) {
						max = myScore[i][j];
						x = i;
						y = j;
					} else if (myScore[i][j] == max) {
						if (computerScore[i][j] > computerScore[x][y]) { // 
							x = i;
							y = j;
						}
					}
					// AI最重要的落点
					if (computerScore[i][j] > max) {
						max = computerScore[i][j];
						x = i;
						y = j;
					} else if (computerScore[i][j] == max) {
						if (myScore[i][j] > myScore[x][y]) {
							x = i;
							y = j;
						}
					}
				}
			}
		}
		play(x*46-23,y*46-23);//下棋
		chessBorad[x][y] = 2;//棋盘标记已下棋
		for (int k = 0; k < re.getCount(); k++) {//遍历所有的赢法
			if (wins[x][y][k]) {//如果(x,y)这个点在某一种赢法中
				computerWin[k]++; 	//那么该种赢法中有多了一个棋子
				myWin[k] = 999; 	//那么我方的这种赢法就不可能赢了,设一个异常的值
				if (computerWin[k] == 5) { //如果计算机在某种赢法上连上了五个子,那么计算机就赢了,我方就输了
					System.err.println("lose");
					over = true; //结束游戏
					return;
				}
			}
		}
		if (!over) {//如果没有结束游戏
			me = !me;//换我方下棋
		}
	}
	/***
	 * 把棋子放入棋盘
	 * @param x
	 * @param y
	 */
	public void play(int x,int y){
		Icon icon;
		if(s%2==0){
			icon=new ImageIcon("image/black.png");//黑棋
		}else{
			icon=new ImageIcon("image/white.png");//白旗
		}
		s++;
		JLabel lblNewLabel = new JLabel(icon);
		lblNewLabel.setBounds(x,y, 46, 46);
		panel.add(lblNewLabel);
		panel.repaint();
	}
}


留言(0)
加载更多
猜你喜欢
  • blog java序列化和反序列化

    概念:Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程;序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以
  • blog java中有没有goto关键字

    答案:java中有goto关键字,但是goto是java语言中的保留字,目前还没有在java中使用。         其实goto这个词是C语言中的,goto语句通常与条件语句配合使用,可用来实现条
  • blog java线程池

    为什么用线程池:1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率2.线程并发数量过多,抢占系统资源从而导致阻塞3.对线程进行一些简单的管理ThreadPoolExecutor线程池ThreadPoolEx
  • blog java定时器

    定时执行(一秒后执行)import java.util.Timer;import java.util.TimerTask;/** * 定时器 */public class Main3 { public static void ma
  • blog 数据结构和算法-判断一棵二叉树是否为另一颗二叉树的

    题目:判断下方两棵二叉树右方的二叉树是否为左方二叉树的树 例1: | |
  • file 阿里巴巴Java开发手册-终极版.pdf

    <p><img src="http://www.jiajiajia.club:8089/weblog/2019_11_23/61ea8dbd-f630-4257-a12e-9c69a4673955.p
  • blog c#钩程序键盘事件监听(拦截系统组合键)WebBrowser浏览器控件

    1.什么是钩程序 hook(钩)是windows提供的一种消息处理机制平台,是指在程序正常运行中接受信息之前预先启动的函数,用来检查和修改传给该程序的信息,(钩)实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。
  • blog Java异常体系(Throwable、Error、Exception)

    Java异常体系 java异常体系继承图                         Throwable
  • blog java数据类型

    java数据类型java数据类型基本数据类型数值型整数类型(byte,short,int,long)浮点类型(float,double)字符型(chart)布尔型(boolean)引用类型类(class)接口(interface)数组byt
  • blog 32个java面试必考点

    32个java面试必考点