五子棋(人人对战、人机对战均可)

    这是我第一次做个人项目,虽然难度不大,但也还是花了挺多时间的。

   第一步建立了棋子类,用于定义棋子。

import java.awt.Color;
import java.awt.Graphics;

public class Chess implements ChessInterface {
	protected Color color;
	public int x, y;

	public Chess(int x, int y, Color color) {
		this.x = x;
		this.y = y;
		this.color = color;
	}

	public void draw(Graphics g) {
		g.setColor(color);
		g.fillOval(X + x * Size - Size / 2, Y + y * Size - Size / 2, Size, Size);

	}

}

    第二步画棋盘,同时将监听器也进行绑定,我将监听器绑定在了按键而非棋盘上。重写paint方法用于重绘。这里要注意的一点是,最好创建一个接口保存棋盘的间距、行数、列数等信息,方便之后修改。同时在这个接口中,还声明了一个二维数组用于保存棋局(棋子的颜色)。第二个二维数组是之后人机对战用到的,之后再详述。棋盘代码如下:

public class ChessPane extends JPanel implements ChessInterface {
	/**
		 * 
		 */
	private static final long serialVersionUID = 1L;
	Chess chess[] = new Chess[100];

	public static void main(String[] args) {
		ChessPane chesspanel = new ChessPane();
		chesspanel.showUI();
	
	}

	// 创建窗体对象
	public void showUI() {
		JFrame jf = new JFrame();
		jf.setSize(800, 660);
		jf.setTitle("五子棋");
		// 设置进程的方法
		jf.setDefaultCloseOperation(3);
		// 设置居中显示
		jf.setLocationRelativeTo(null);
		jf.getContentPane().setBackground(Color.WHITE);
		jf.setLayout(new BorderLayout());

		// this.setBackground(Color.BLUE);
		jf.add(this, BorderLayout.CENTER);

		JPanel pan = new JPanel();
		pan.setBackground(Color.DARK_GRAY);
		pan.setPreferredSize(new Dimension(150, 0));

		jf.add(pan, BorderLayout.EAST);
		
		// 添加监听器
		ChessListener mouse = new ChessListener();
		this.addMouseListener(mouse);
		mouse.setC(chess);
		mouse.setP(this);
		String button[] = { "开始游戏", "悔         棋", "认         输", "人机对战", "双人对战" };
		for (int i = 0; i < button.length; i++) {
			JButton jbu = new JButton(button[i]);
			pan.add(jbu);
			jbu.addActionListener(mouse);

		}
		jf.setVisible(true);
		Graphics g = this.getGraphics();
		mouse.setGr(g);
		
		
		

	}

	public void paint(Graphics g) {
		super.paint(g);
		// 画棋盘
		for (int i = 0; i < 15; i++) {
			g.drawLine(X, Y + i * Size, X + (Coloum - 1) * Size, Y + i * Size);
			g.drawLine(X + i * Size, Y, X + i * Size, Y + (Row - 1) * Size);
		}
		// 画棋子
		for (int i = 0; i < chess.length; i++) {
			Chess ch = chess[i];
			if (ch != null)
				ch.draw(g);
		}

	}
}
接口代码:
public interface ChessInterface {
	//棋子和棋盘的大小
public static final int Size=40;
public static final int  X=30;
public static final int Y=30;
public static final int Row=15;
public static final int Coloum=15;

//存棋子
public static final int[][]array=new int[Row][Coloum];

public static final int[][]chessValue=new int[Row][Coloum];
}

接下来是监听器部分,由于功能比较多,所以写的有些混乱,请多包涵。

几个功能的实现思想如下:

1)双人对战:通过监听器获取点击坐标,但是要注意把坐标进行转换,才能让棋子落在棋盘的交叉点处。通过一个num变量用于计数,从而判定棋子的颜色。用filloval函数绘制棋子,注意的是要将棋子保存进数组,因为要进行重绘。(事实上,每下一颗棋子就进行了一次重绘)。

2)开始游戏:这个按钮的意思是重新开始游戏,其实只要明白“下子就是重绘”这一原理,就很好解决了。只需要将保存棋子的数组清空,棋盘就无法进行重绘,也就是重新开始新的一轮游戏了。

3)悔棋:悔棋的原理同 2),之前提到用num来计数,只需要更改num值,就能对数组中保存的值进行修改,也就是对棋局进行修改。

4)人机对战:人机对战有很多种实现方式,小白采用的是最简单的权值表法,也就是遍历整个棋盘,根据之前设定的权值生成每一个位置的权值表,选取权值最大的位置下子。这里又创建了一个二维数组,用于存储每个格子的权值。

首先,设立权值;然后,根据权值建立每个可能位置的权值表(八个方位,权值进行累加);通过循环找到权值最大的位置,然后下子(这里要注意的是,不同的方向要记得及时把之前累加的权值清零。);下子之后,把整个棋盘的权值表清零(二维数组清零)这里还有一个小细节,由于我把监听器绑定在按键上,所以是通过获取按键上的字符串来判断当前的功能的,建议还是将不同的功能写成函数进行调用,这样就能提高代码复用。可以通过设定一个变量来控制代码的运行。

package com.fzj.Chess0421;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.HashMap;

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

public class ChessListener extends MouseAdapter
	implements ChessInterface, MouseListener, ActionListener, MouseMotionListener {
	private int x, y, i = 0;
	private Graphics g;
	private int num = 0;
	Chess[] chess;
	private String str;
	Color chessc;
	CheckWin win = new CheckWin();
	ChessPane cp;

	public void setGr(Graphics gr) {
		g = gr;
	}

	public void setC(Chess[] c) {
		chess = c;
	}

	public void setP(ChessPane p) {
		cp = p;
	}

	public void mouseReleased(MouseEvent e) {

		x = e.getX();
		y = e.getY();
		int row = 1;
		int line = 1;

		// 判断棋子的位置
		int a = (x - X) / Size;// 取商
		int b = (x - X) % Size;// 取余数

		if (b <= (Size / 2)) {
			row = a;
		} else {
			row = a + 1;
		}

		int c = (y - Y) / Size;// 取商
		int d = (y - Y) % Size;// 取余数

		if (d <= (Size / 2)) {
			line = c;
		} else {
			line = c + 1;
		}
		if (array[row][line] == 0) {
			if (num % 2 == 0) {
				g.setColor(Color.black);
				array[row][line] = 1;

			} else {
				g.setColor(Color.white);
				array[row][line] = 2;
			}

			g.fillOval(X + row * Size - Size / 2, Y + line * Size - Size / 2, Size, Size);
			Chess ch = new Chess(row, line, g.getColor());
			chess[num] = ch;
			num++;
			if (i == 1) {
				AI();
			}
			win.isWin(row, line);
		}
	}

	public void restart(){
		for (int i = 0; i < chess.length; i++) {
			chess[i] = null;
		}
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array.length; j++) {
				array[i][j] = 0;
			}
		}

		num = 0;
		cp.paint(g);
	}
	public void actionPerformed(ActionEvent e) {

		str = e.getActionCommand();
		if ("开始游戏".equals(str)) {
			restart();
		}

		if ("悔         棋".equals(str)) {
			if(i==2){
			if (num > 0) {
				num--;
				x = chess[num].x;
				y = chess[num].y;
				array[x][y] = 0;
				chess[num] = null;

				cp.repaint();
			}}
		}

		if ("人机对战".equals(str)) {
			
			restart();
			i = 1;

			// 人先下(黑子),并判断输赢

			// AI();

		}
		if ("双人对战".equals(str)) {
			restart();
			i = 0;
			
			// 人先下(黑子),并判断输赢
			
			// AI();

		}

	}

	HashMap hm = new HashMap();
	public ChessListener() {
        //black
        hm.put("1", 10);
        hm.put("11", 100);
        hm.put("111", 5000);
        hm.put("1111", 8000);

        hm.put("12", 5);
        hm.put("112", 80);
        hm.put("1112", 3000);
        hm.put("11112", 10000);

        hm.put("21", 11);
        hm.put("211", 110);
        hm.put("2111", 1100);
        hm.put("21111", 11000);

        //white
        hm.put("2", 20);
        hm.put("22", 200);
        hm.put("222", 4500);
        hm.put("2222", 10000);

        hm.put("221", 100);
        hm.put("2221", 3000);
        hm.put("22221", 12000);
        hm.put("122", 5);
        hm.put("1222", 500);
        hm.put("12222", 10000);

	}

	public void AI() {
		// 人先下(黑子),并判断输赢
		// 建立权值
		// 水平方向
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[i].length; j++) {
				if (array[i][j] == 0) {
					String code = "";
					int color = 0;
					// 向右
					for (int k = i + 1; k < array.length; k++) {
						if (array[k][j] == 0) {
							break;
						} else {
							if (color == 0) {
								color = array[k][j];
								code += array[k][j];
							} else if (array[k][j] == color) {
								code += array[k][j];
							} else {
								code += array[k][j];
								break;
							}
						}
					}
					// 根据code取出对应的权值
					Integer value1 = hm.get(code);
					if (value1 != null) {
						chessValue[i][j] += value1;
					}
					// 向左
					code = "";
					color = 0;
					// 向左
					for (int k = i; k > 0; k--) {
						if (array[k][j] == 0) {
							break;
						} else {
							if (color == 0) {
								color = array[k][j];
								code += array[k][j];
							} else if (array[k][j] == color) {
								code += array[k][j];

							} else {
								code += array[k][j];
								break;
							}
						}
					}
					value1 = hm.get(code);
					if (value1 != null) {
						chessValue[i][j] += value1;
					}

					// 垂直方向
					// 向上
					color = 0;
					code = "";
					for (int k = j + 1; k < array.length; k++) {
						if (array[i][k] == 0) {
							break;
						} else {
							if (color == 0) {
								color = array[i][k];
								code += array[i][k];
							} else if (array[i][k] == color) {
								code += array[i][k];

							} else {
								code += array[i][k];
								break;
							}
						}
					}
					// 根据code取出对应的权值
					Integer value11 = hm.get(code);
					if (value11 != null) {
						chessValue[i][j] += value11;
					}
					// 向下
					color = 0;
					code = "";
					for (int k = j; k > 0; k--) {
						if (array[i][k] == 0) {
							break;
						} else {
							if (color == 0) {
								color = array[i][k];
								code += array[i][k];
							} else if (array[i][k] == color) {
								code += array[i][k];

							} else {
								code += array[i][k];
								break;
							}
						}
					}
					value1 = hm.get(code);
					if (value1 != null) {
						chessValue[i][j] += value1;

					}
					code = "";
					color = 0;
					//右斜
					//向下
					for (int k = 0; k < (array.length - i)&&k<(array.length-j); k++) {
						if (array[i + k][j + k] == 0) {
							break;
						} else {
							if (color == 0) {
								color = array[i + k][j + k];
								code += array[i + k][j + k];
							} else if (array[i + k][j + k] == color) {
								code += array[i + k][j + k];

							} else {
								code += array[i + k][j + k];
								break;
							}
						}
					}
					value1 = hm.get(code);
					if (value1 != null) {
						chessValue[i][j] += value1;

					}
					code = "";
					color = 0;
					// 向上
					for (int k = 0; (j - k) > 0 && (i - k) > 0; k++) {
						if (array[i - k][j - k] == 0) {
							break;
						} else {
							if (color == 0) {
								color = array[i - k][j - k];
								code += array[i - k][j - k];
							} else if (array[i - k][j - k] == color) {
								code += array[i - k][j - k];

							} else {
								code += array[i - k][j - k];
								break;
							}
						}
					}
					value1 = hm.get(code);
					if (value1 != null) {
						chessValue[i][j] += value1;

					}

					code = "";
					color = 0;
					// 向下
					for (int k = 0; (i - k) > 0 && k > (array.length - j); k++) {
						if (array[i - k][j + k] == 0) {
							break;
						} else {
							if (color == 0) {
								color = array[i - k][j + k];
								code += array[i - k][j + k];
							} else if (array[i - k][j + k] == color) {
								code += array[i - k][j + k];

							} else {
								code += array[i - k][j + k];
								break;
							}
						}
					}
					value1 = hm.get(code);
					if (value1 != null) {
						chessValue[i][j] += value1;

					}
					code = "";
					color = 0;
					// 
					for (int k = 0; k < (array.length - i) && (j - k) > 0; k++) {
						if (array[i + k][j - k] == 0) {
							break;
						} else {
							if (color == 0) {
								color = array[i + k][j - k];
								code += array[i + k][j - k];
							} else if (array[i + k][j - k] == color) {
								code += array[i + k][j - k];

							} else {
								code += array[i + k][j - k];
								break;
							}
						}
					}
					value1 = hm.get(code);
					if (value1 != null) {
						chessValue[i][j] += value1;

					}
				}
			}
		}
		// 找到权值最大的位置,并下子
		int max = 0;
		int x1 = 0;
		int y1 = 0;
		for (int a = 0; a < chessValue.length; a++) {
			for (int b = 0; b < chessValue.length; b++) {
				if (chessValue[a][b] > max) {
					max = chessValue[a][b];
					x1 = a;
					y1 = b;
				}
			}
		}

		for (int a = 0; a < chessValue.length; a++) {
			for (int b = 0; b < chessValue.length; b++) {
				System.out.print(chessValue[a][b] + " ");
			}
			System.out.println();
		}
		System.out.println();
		// System.out.println("x1="+x1+" y1="+y1);
		g.setColor(Color.white);
		g.fillOval(X + x1 * Size - Size / 2, Y + y1 * Size - Size / 2, Size, Size);
		array[x1][y1] = 2;
		Chess ch = new Chess(x1, y1, Color.white);
		chess[num] = ch;
		num++;
		win.isWin(x1, y1);

		// 清空权值表
		for (int a = 0; a < chessValue.length; a++) {
			for (int b = 0; b < chessValue.length; b++) {
				chessValue[a][b] = 0;
			}

		}

	}
}

接下来,也是比较重要的一步,判断输赢,我专门建立了一个类用于判断输赢,只需要创建一个对象,就能调用判定的方法。其实判定其实很简单,用一个变量进行计数,再采用一个循环,同色则+1,异色或无子则break,也是对八个方位进行判定,代码如下:

import javax.swing.JOptionPane;

public class CheckWin implements ChessInterface {
	public void isWin(int x,int y){
		if(horizontal(x,y)>=5||vertical(x,y)>=5||westnorth(x,y)>=5||eastnorth(x,y)>=5){
			if(array[x][y]==1)
				JOptionPane.showMessageDialog(null, "black win");
			else if(array[x][y]==2)
				JOptionPane.showMessageDialog(null, "white win");
		}
	}
	public int horizontal(int x, int y) {
		int count = 0;

		for (int i = x + 1; i < array.length; i++) {
			if (array[i][y] == array[x][y]) {
				count++;
			} else
				break;
		}
		for (int i = x; i >= 0; i--) {
			if (array[i][y] == array[x][y]) {
				count++;
			} else
				break;

		}
		return count;
	}

	public int vertical(int x, int y) {
		int count = 0;

		for (int i = y + 1; i < array.length; i++) {
			if (array[x][i] == array[x][y]) {
				count++;
			} else
				break;
		}
		for (int i = y; i >= 0; i--) {
			if (array[x][i] == array[x][y]) {
				count++;
			} else
				break;

		}
		return count;
	}

	public int westnorth(int x, int y) {
		int count = 0;
		
			for (int i = 0; i <(array.length-x)&&i<(array.length-x); i++) {

				if (array[x+i][y+i] == array[x][y]) {
					count++;
				} else
					break;
			}
			for (int i = 1; (x-i)>=0&&(y-i)>=0; i++) {
				if (array[x-i][y-i] == array[x][y]) {
					count++;
				} else
					break;

			}
		
		return count;
	}

	public int eastnorth(int x, int y) {
		int count = 0;
		
		for (int i = 0; i <(array.length-x)&&(y-i)>0; i++) {

			if (array[x+i][y-i] == array[x][y]) {
				count++;
			} else
				break;
		}
		for (int i = 1; (x-i)>=0&&i <(array.length-y); i++) {
			if (array[x-i][y+i] == array[x][y]) {
				count++;
			} else
				break;

		}
	
	return count;
	}

}
至此,一个简陋的五子棋就完成了。



你可能感兴趣的:(五子棋(人人对战、人机对战均可))