Java五子棋

今天来分享一个Java五子棋。

所涉及到的知识

  1. 画图板的重绘
  2. 权值算法

接口##

首先定义一个BorderSize的接口,用来设置棋盘和棋子的相关属性。凡是需要用到接口中相关属性的类都必须实现BorderSize接口。

public interface BorderSize {
	int SIZE = 50;
	int ROW = 19;
	int COLUM = 19;
	int X = 30;
	int Y = 30;
	int[][] chessArray = new int[ROW][COLUM];
	int[][] weightArray = new int[ROW][COLUM];

}

棋盘界面类

棋盘界面类中主要定义了界面的样式以及重绘方法

public class ChessBorder extends JPanel implements BorderSize{
	
	public void showBorder(){
		JFrame frame = new JFrame();
		frame.setTitle("我的五子棋");
		frame.setSize(1100, 1000);
		//设置窗体不可改变大小
		frame.setResizable(false);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//设置棋盘背景图片
		ImageIcon centerIcon = new ImageIcon("C:\\Users\\sunxiaona\\Desktop\\Java\\蓝杰\\Image\\4.jpg");
		JLabel centerLabel = new JLabel(centerIcon);
		this.add(centerLabel);
		//设置容器为边框布局
		frame.setLayout(new BorderLayout());
		//this.setBackground(Color.LIGHT_GRAY);
		frame.add(this, BorderLayout.CENTER);
		//添加按钮面板并设置大小
		JPanel eastPanel = new JPanel();
		eastPanel.setBackground(Color.DARK_GRAY);
		Dimension eastPsize = new Dimension(120,1000);
		eastPanel.setPreferredSize(eastPsize);
		frame.add(eastPanel, BorderLayout.EAST);
		//添加标签,使按钮居中
		JLabel label = new JLabel();
		Dimension labelSize = new Dimension(110,300);
		label.setPreferredSize(labelSize);
		eastPanel.add(label);
		//创建监听器对象
		BorderListener BL = new BorderListener();
		//添加鼠标监听器到棋盘面板
		//this.addMouseListener(BL);
		//设置按钮的大小
		Dimension buttonSize = new Dimension(110,50);
		String[] btn ={"开始新游戏","认输","悔棋"};
		for(int i=0;i<btn.length;i++){
			JButton button = new JButton(btn[i]);
			button.setPreferredSize(buttonSize);
			button.addActionListener(BL);
			eastPanel.add(button);
		}
		String[] item = {"人人对战","人机对战"};
		JComboBox<String> JCB = new JComboBox<String>(item);
		JCB.setPreferredSize(buttonSize);
		eastPanel.add(JCB);
		JCB.addActionListener(BL);
		
		//显示可见
		frame.setVisible(true);
		BL.setPanel(this);
		BL.setJCB(JCB);
		BL.setCHB(this);
	}
	
	public void paint(Graphics g){
		super.paint(g);
		for(int i=0;i<ROW;i++){
			//画横线
			g.drawLine(X,Y+SIZE*i,X+(ROW-1)*SIZE,Y+SIZE*i);
			g.drawLine(X+SIZE*i, Y, X+SIZE*i,Y+SIZE*(COLUM-1));
		}
		//画棋子
		for(int i=0;i<ROW;i++){
			for(int j=0;j<COLUM;j++){
				if(chessArray[i][j]==1){
					g.setColor(Color.BLACK);
					g.fillOval(X+i*SIZE-SIZE/2, Y+j*SIZE-SIZE/2, SIZE, SIZE);
				}
				if(chessArray[i][j]==2){
					g.setColor(Color.WHITE);
					g.fillOval(X+i*SIZE-SIZE/2, Y+j*SIZE-SIZE/2, SIZE, SIZE);
				}
			}
		}
	}
	
	public static void main(String[] args){
		ChessBorder CHB = new ChessBorder();
		CHB.showBorder();
	}

监听器类

所有的逻辑实现全部在监听器类中,在本五子棋中有“人人对战”和“人机对战”两种对战模式,并且有开始新游戏、悔棋、认输等操作。所有的这些操作所产生的效果都在监听器类中定义了。细节之处见代码!


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.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class BorderListener implements BorderSize,MouseListener,ActionListener{
	int x,y;
	JPanel panel;
	JComboBox JCB;
	ChessBorder CHB;
	int count = 0;
	String fightType = "人人对战";
	int huiX,huiY;
	int max,row,colum;	//人机大战需要用的数据
	
	//获取画布
	public void setPanel(JPanel panel){
		this.panel = panel;
	}
	//传递JComboBox
	public void setJCB(JComboBox JCB){
		this.JCB = JCB;
	}
	//传递ChessBorder
	public void setCHB(ChessBorder CHB){
		this.CHB = CHB;
	}
	public void actionPerformed(ActionEvent e){
		String action = e.getActionCommand();
		if("开始新游戏".equals(action)){
			//清空棋盘
			for(int i=0;i<ROW;i++){
				for(int j=0;j<COLUM;j++){
					chessArray[i][j] = 0;
				}
			}
			//设置JComboBox不可用
			JCB.setEnabled(false);
			panel.addMouseListener(this);
			//画的时候获取画布(游戏重新开始后清空画板)
			Graphics g = panel.getGraphics();
			Graphics2D g2d = (Graphics2D) g;
			g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			CHB.paint(g);
		}else if("认输".equals(action)){
			if(count==0){
				JOptionPane.showMessageDialog(null, "白棋获胜!!!");
			}else {
				JOptionPane.showMessageDialog(null, "黑棋获胜!!!");
			}
			//黑棋先下
			count = 0;
			JCB.setEnabled(true);
			panel.removeMouseListener(this);
		}else if("悔棋".equals(action)){
			chessArray[huiX][huiY] = 0;
			Graphics g = panel.getGraphics();
			//抗锯齿效果
			Graphics2D g2d = (Graphics2D) g;
			g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			if(count==0){
				count = 1;
			}else {
				count = 0;
			}
			CHB.paint(g);
		}else {
			String s =(String)JCB.getSelectedItem();
			fightType = s;
		}
	}
	
	public void mouseReleased(MouseEvent e){
		x = e.getX();
		y = e.getY();
		Result result = new Result();
		if(panel!=null){
			Graphics g = panel.getGraphics();
			//抗锯齿处理	添加此行后,棋子边缘光滑 
			Graphics2D g2d = (Graphics2D) g;
			g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			int index = 0;
			int r,c;
			for(int i=X;i<=(ROW-1)*SIZE;i=i+SIZE){
				for(int j=Y;j<=(COLUM-1)*SIZE;j=j+SIZE){
					if((x-i>-SIZE/2&&x-i<SIZE/2)&&(y-j>-SIZE/2&&y-j<SIZE/2)){
						r = (i-X)/SIZE;
						c = (j-Y)/SIZE;
						//画黑棋
						if(count==0 && chessArray[r][c]!=1 && chessArray[r][c]!=2){
							chessArray[r][c] = 1;
							g.setColor(Color.BLACK);
							g.fillOval(i-SIZE/2, j-SIZE/2, SIZE, SIZE);
							count++;	//转换到白棋
							result.r = r;
							result.c = c;
							//悔棋的棋子
							huiX = r;
							huiY = c;
						}
						//画白棋
						if(count==1 && chessArray[r][c]!=1 && chessArray[r][c]!=2){
							chessArray[r][c] = 2;
							g.setColor(Color.WHITE);
							g.fillOval(i-SIZE/2, j-SIZE/2, SIZE, SIZE);
							count--;	//转换到黑棋
							result.r = r;
							result.c = c;
							//悔棋的棋子
							huiX = r;
							huiY = c;
						}
						
					}
				}
			}
			//(人人对战判断黑白棋胜利)和(人机对战判断黑棋部分)
			if(result.WinOrLoss()){
				if(chessArray[result.r][result.c]==1){
					JOptionPane.showMessageDialog(null, "黑棋获胜!");
				}
				if(chessArray[result.r][result.c]==2){
					JOptionPane.showMessageDialog(null, "白棋胜利!");
				}
				//重新开始后黑棋先下
				count = 0;	
				//游戏结束后设置下拉列表框为可用
				JCB.setEnabled(true);
				//游戏结束后不可继续下棋  (移除鼠标监听器)
				panel.removeMouseListener(this);
			}
			//人机对战部分
			if("人机对战".equals(fightType)){
				AI ai = new AI();
				ai.AIplay();
				int max=0;
				//寻找最大权重
				for(int i=0;i<ROW;i++){
					for(int j=0;j<COLUM;j++){
						if(weightArray[i][j]>max){
							max = weightArray[i][j];
							row = i;
							colum = j;
						}
						System.out.print(weightArray[i][j]+" ");
					}
					System.out.println();
				}
				System.out.println(max);
				//人机对战中画电脑的棋子
				if(count==1){
					chessArray[row][colum] = 2;
					g.setColor(Color.WHITE);
					System.out.println(row+" "+colum);
					g.fillOval(row*SIZE+X-SIZE/2,colum*SIZE+Y-SIZE/2 ,SIZE, SIZE);
					count--;
				}
			result.r = row;
			result.c = colum;
			}
			if(result.WinOrLoss()&&"人机对战".equals(fightType)){
				if(chessArray[row][colum]==2){
					JOptionPane.showMessageDialog(null, "白棋胜利!");
					row = 0;
					colum = 0;
				}
				//重新开始后黑棋先下
				count = 0;	
				//游戏结束后设置下拉列表框为可用
				JCB.setEnabled(true);
				//游戏结束后不可继续下棋  (移除鼠标监听器)
				panel.removeMouseListener(this);
				
			}
		}
	}
	
	
	public void mouseClicked(MouseEvent e){}
    public void mousePressed(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}

}

Win Or Lost

实现了上述内容之后,我们已经可以在棋盘上顺利下棋了,那么接下来当然是判断输赢了。判断输赢分别从4个方向上统计:水平、垂直、左斜、右斜。只要搞清楚原理即可,这部分的代码大同小异,基本上都是重复工作。

package goBang;

public class Result implements BorderSize{
	
	boolean flag = false;
	int r,c;
	
	public boolean WinOrLoss(){
		
		if(resultH(r,c)>=5||resultS(r,c)>=5||resultL(r,c)>=5||resultR(r,c)>=5){
			return !flag;
		}else {
			return flag;
		}
		
	}
	
	//横向判断
		public int resultH(int r,int c){
			int count=1;
			//往左走
			for(int i=c-1;i>=0;i--){
				if(chessArray[r][c]==chessArray[r][i]&&chessArray[r][i]!=0){
					count++;
				}else {
					break;
				}
			}
			//往右走
			for(int i=c+1;i<ROW;i++){
				if(chessArray[r][c]==chessArray[r][i]&&chessArray[r][i]!=0){
					count++;
				}else {
					break;
				}
			}
			return count;
		}
		
		//竖向判断
		public int resultS(int r,int c){
			int count=1;
			//往上走
			for(int i=r-1;i>=0;i--){
				if(chessArray[r][c]==chessArray[i][c]&&chessArray[i][c]!=0){
					count++;
				}else {
					break;
				}
			}
			//往下走
			for(int i=r+1;i<ROW;i++){
				if(chessArray[r][c]==chessArray[i][c]&&chessArray[i][c]!=0){
					count++;
				}else {
					break;
				}
			}
			return count;
		}
		//斜向判断(左上到右下)
		public int resultL(int r,int c){
			int count=1;
			//往左走
			for(int i=r-1,j=c-1;i>=0&&j>=0;i--,j--){
				if(chessArray[i][j]==chessArray[r][c]&&chessArray[i][j]!=0){
					count++;
				}else{
					break;
				}
			}
			//往右走
			for(int i=r+1,j=c+1;i<ROW&&j<COLUM;i++,j++){
				if(chessArray[i][j]==chessArray[r][c]&&chessArray[i][j]!=0){
					count++;
				}else {
					break;
				}
			}
			return count;
		}
		//斜向判断(左下到右上)
		public int resultR(int r,int c){
			int count=1;
			//往左走
			for(int i=r+1,j=c-1;i<ROW&&j>=0;i++,j--){
				if(chessArray[i][j]==chessArray[r][c]&&chessArray[i][j]!=0){
					count++;
				}else {
					break;
				}
			}
			//往右走
			for(int i=r-1,j=c+1;i>=0&&j<ROW;i--,j++){
				if(chessArray[i][j]==chessArray[r][c]&&chessArray[i][j]!=0){
					count++;
				}else {
					break;
				}
			}
			return count;
		}

}

AI

如果想为我们的五子棋增添一点点人工智能的色彩,就需要知道如何指挥电脑下棋了。想深入了解的小伙伴可以参考一下权值算法、博弈树…我用的是权值算法(下面内容,算法不是特别完善哈,你们可以参考参考自己写一个更厉害的AI)

package goBang;

import java.util.HashMap;

public class AI implements BorderSize{
	
	static HashMap<String,Integer> map = new HashMap<String,Integer>();
	static {
		//防守
		map.put("0", 1);
		map.put("010",10);
		map.put("021", 15);
		map.put("0112",20);
		map.put("0221",150);
		map.put("02221",400);
		map.put("01112",500);
		map.put("0110", 800);
		map.put("022221", 5000);
		map.put("01110", 2000);
		map.put("011112", 7000);
		map.put("02020", 300);
		map.put("02220", 5000);
		map.put("020", 25);
		map.put("0220",280);
		map.put("022220",100000);
		map.put("01111", 4000);
		map.put("02", 5);
		
		
	}
	
	//判断每个点的权值
		public void AIplay(){
			for(int i=0;i<ROW;i++){
				for(int j=0;j<COLUM;j++){
					weightArray[i][j]=0;
				}
			}
			for(int r=0;r<ROW;r++){
				for(int c=0;c<COLUM;c++){
					if(chessArray[r][c]==0){		//判断该位是否为空位
						//水平方向
						String code = "0";	//用来记录棋子相连的情况
						int chess = 0;   //记录第一次出现的棋子
						int number = 0;	//记录空位出现的次数
						//水平向左统计
						for(int i=c-1;i>=0;i--){
							if(chessArray[r][i]==0){//判断是否为空位
								if(c==i+1){
									break;	//如果有两个连续的空位,跳出
								}else if(number==0){	//第一次出现空位
									code = code +chessArray[r][i];	//记录棋子相连的情况
									number++;
								}else if(number==1){	//第二次出现空位
									if(chessArray[r][i]==chessArray[r][i+1]){	//判断是否又为2个连续的空位
										break;
									}
									code = code +chessArray[r][i];
									number++;
								}else if(number==2){	//第三次出现空位
									if(chessArray[r][i]==chessArray[r][i+1]){	//空位连续
										break;
									}
								}
							}else{		//该位是棋子
								if(chess==0){	//第一次出现棋子
									chess =chessArray[r][i];
									code = code +chessArray[r][i];
								}else if(chess==chessArray[r][i]){
									code = code +chessArray[r][i];
								}else {
									code = code +chessArray[r][i];
									break;
								}
							}
						}
						System.out.print(code+" ");
						Integer value0 = map.get(code);	//Inter 整数类
						if(value0!=null){
							weightArray[r][c] += value0;
						}
						code = "0";
						chess = 0;
						number=0;
						//水平向右统计
						for(int i=c+1;i<COLUM;i++){
							if(chessArray[r][i]==0){
								if(c==i-1){
									break;	//相邻2空位,跳出
								}else if(number==0){	//第一次出现空位
									code = code +chessArray[r][i];
									number++;
								}else if(number==1){	第2次出现空位
									if(chessArray[r][i]==chessArray[r][i-1]){
										break;		//连续2空位跳出
									}else{
										code = code + chessArray[r][i];
										number++;
									}
								}else if(number==2){	//第3次出现空位
									if(chessArray[r][i]==chessArray[r][i-1]){
										break;
									}
								}
							}else {	//该位位棋子
								if(chess==0){
									chess = chessArray[r][i];
									code = code +chessArray[r][i];
								}else if(chess==chessArray[r][i]){
									code = code +chessArray[r][i];
								}else {			//碰到不同颜色的棋子跳出循环
									code = code +chessArray[r][i];
									break;
								}
							}
						}
						System.out.print(code+" ");
						Integer value1 = map.get(code);	//Inter 整数类
						if(value1!=null){
							weightArray[r][c] += value1;
						}
						//垂直方向
						code = "0";
						chess = 0;
						number=0;
						//垂直向上
						for(int i=r-1;i>=0;i--){
							if(chessArray[i][c]==0){
								if(r==i+1){
									break;		//连续2个空位跳出循环
								}else if(number==0){	//第一次出现空位
									code = code +chessArray[i][c];
									number++;
								}else if(number==1){//第2次出现空位
									if(chessArray[i][c]==chessArray[i+1][c]){
										break;
									}else {
										code = code +chessArray[i][c];
										number++;
									}
								}else if(number==2){//第3次出现空位
									if(chessArray[i][c]==chessArray[i+1][c]){
										break;
									}
								}
							}else {
								if(chess==0){
									chess = chessArray[i][c];
									code = code +chessArray[i][c];
								}else if(chess==chessArray[i][c]){
									code = code +chessArray[i][c];
								}else {
									code = code +chessArray[i][c];
									break;
								}
							}
						}
						System.out.print(code+" ");
						Integer value2 = map.get(code);	//Inter 整数类
						if(value2!=null){
							weightArray[r][c] += value2;
						}
						code = "0";
						chess = 0;
						number=0;
						//垂直向下
						for(int i=r+1;i<ROW;i++){
							if(chessArray[i][c]==0){
								if(r==i-1){
									break;
								}else if(number==0){
									code = code +chessArray[i][c];
									number++;
								}else if(number==1){
									if(chessArray[i][c]==chessArray[i-1][c]){
										break;
									}else {
										code = code +chessArray[i][c];
									}
								}else if(number==2){
									if(chessArray[i][c]==chessArray[i-1][c]){
										break;
									}
								}
							}else {
								if(chess==0){
									chess = chessArray[i][c];
									code = code +chessArray[i][c];
								}else if(chess==chessArray[i][c]){
									code = code +chessArray[i][c];
								}else {
									code = code +chessArray[i][c]; 
									break;
								}
							}
						}
						Integer value3 = map.get(code);	//Inter 整数类
						if(value3!=null){
							weightArray[r][c] += value3;
//						}
						//左斜
						code = "0";
						chess = 0;
						number=0;
						//往左上
						int i,j;
						for(i=r-1,j=c-1;i>=0&&j>=0;i--,j--){
							if(chessArray[i][j]==0){
								if(r==i+1&&c==j+1){
									break;
								}else if(number==0){
									code = code +chessArray[i][j];
									number++;
								}else if(number==1){
									if(chessArray[i][j]==chessArray[i+1][j+1]){
										break;
									}else {
										code = code +chessArray[i][j];
										number++;
									}
								}else if(number==2){
									if(chessArray[i][j]==chessArray[i+1][j+1]){
										break;
									}
								}
							}else {
								if(chess==0){
									chess=chessArray[i][j];
									code = code +chessArray[i][j];
								}else if(chess==chessArray[i][j]){
									code = code +chessArray[i][j];
								}else {
									code = code +chessArray[i][j];
									break;
								}
							}
						}
						System.out.println(code+" ");
						Integer value4 = map.get(code);	//Inter 整数类
						if(value4!=null){
							weightArray[r][c] += value4;
						}
						code = "0";
						chess = 0;
						number = 0;
						//往右下
						for(i=r+1,j=c+1;i<ROW&&j<COLUM;i++,j++){
							if(chessArray[i][j]==0){
								if(r==i-1&&c==j-1){
									break;
								}else if(number==0){
									code = code +chessArray[i][j];
									number++;
								}else if(number==1){
									if(chessArray[i][j]==chessArray[i-1][j-1]){
										break;
									}else {
										code = code +chessArray[i][j];
										number++;
									}
								}else if(number==2){
									if(chessArray[i][j]==chessArray[i-1][j-1]){
										break;
									}
								}
							}else {
								if(chess==0){
									chess = chessArray[i][j];
									code = code +chessArray[i][j];
								}else if(chess==chessArray[i][j]){
									code = code +chessArray[i][j];
								}else {
									code = code +chessArray[i][j];
									break;
								}
							}
						}
						System.out.println(code+" ");
						Integer value5 = map.get(code);	//Inter 整数类
						if(value5!=null){
							weightArray[r][c] += value5;
						}
						//右斜
						code = "0";
						chess = 0;
						number = 0;
						//往左
						for(i=r+1,j=c-1;i<ROW&&j>=0;i++,j--){
							if(chessArray[i][j]==0){
								if(r==i-1&&c==j+1){
									break;
								}else if(number==0){
									code = code +chessArray[i][j];
									number++;
								}else if(number==1){
									if(chessArray[i][j]==chessArray[i-1][j+1]){
										break;
									}else {
										code = code +chessArray[i][j];
										number++;
									}
								}else if(number==2){
									if(chessArray[i][j]==chessArray[i-1][j+1]){
										break;
									}
								}
							}else {
								if(chess==0){
									chess=chessArray[i][j];
									code = code +chessArray[i][j];
								}else if(chess==chessArray[i][j]){
									code = code +chessArray[i][j];
								}else {
									code = code +chessArray[i][j];
									break;
								}
							}
						}
						System.out.println(code+" ");
						Integer value6 = map.get(code);	//Inter 整数类
						if(value6!=null){
							weightArray[r][c] += value6;
						}
						//往右
						code = "0";
						chess = 0;
						number = 0;
						for(i=r-1,j=c+1;i>=0&&j<COLUM;i--,j++){
							if(chessArray[i][j]==0){
								if(r==i+1&&c==j-1){
									break;
								}else if(number==0){
									code = code +chessArray[i][j];
									number++;
								}else if(number==1){
									if(chessArray[i][j]==chessArray[i+1][j-1]){
										break;
									}else {
										code = code +chessArray[i][j];
										number++;
									}
								}else if(number==2){
									if(chessArray[i][j]==chessArray[i+1][j-1]){
										break;
									}
								}
							}else {
								if(chess==0){
									chess=chessArray[i][j];
									code = code +chessArray[i][j];
								}else if(chess==chessArray[i][j]){
									code = code +chessArray[i][j];
								}else {
									code = code +chessArray[i][j];
									break;
								}
							}
						}
						System.out.println(code+" ");
						Integer value7 = map.get(code);	//Inter 整数类
						if(value7!=null){
							weightArray[r][c] += value7;
						}
				}
			}
		}
	}
		
	}

}

可承接各种项目,有意者加QQ:1217898975

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

steven_moyu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值