五子棋的基本实现

1.效果图。第一次写有点粗糙。

2.五子棋设计要求

          (1)实现界面按钮的基本功能。

          (2)实现双人对战和电脑对战(水平太low还没写出来)

3.设计思路

          (1)棋盘类设计,黑白棋盘,落子位于交叉点,存储棋子。

          (2)棋盘类重绘。

          (3)判断输赢。

          (4)实现按钮功能。

4.具体代码

          (1)为后续可能更改棋盘以及棋子设计要求的方便性,写一个接口定义常量。

public interface Config {
	public static final int xo = 30;//起点横坐标
	public static final int yo = 30;//起点纵坐标
	public static final int rows = 16;//横向线条数
	public static final int columns = 16;//纵向线条数
	public static final int chesssize = 40;//棋子直径
	public static final int size = 50;//单元格大小
}

             (2)①主界面棋盘类的设计,以及棋盘和棋子重绘。重绘要先super.paint(g)父类。抗锯齿方法是Graphics2D的方法,强制转换。创建JFrame绘制绘制窗口,继承的JPanel绘制棋盘,实例化一个JPanel对象用来创建按钮,同时给按钮添加鼠标监听器(事件处理类中实现接口ActionListener完成监听)。

                        棋盘也需要用set方法传递给事件处理类,实现“开始游戏”“悔棋”按钮功能时需要重绘。

                        重绘方法中也需要重绘棋盘(drawChessTable(g);)以及抗锯齿。

import java.awt.BorderLayout;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class FiveChess extends JPanel implements Config {
	private int[][] chess = new int[100][100];
	private int count;
	//private static FiveChess fi;
	static	FiveChess fi = new FiveChess();
	public static void main(String[] args) {
		
		fi.initUI();
	}

	public void initUI() {
		JFrame frame = new JFrame("五子棋");// JFrame默认边界布局
		frame.getContentPane().setBackground(Color.LIGHT_GRAY);
		frame.setSize(1000, 860);
		frame.setDefaultCloseOperation(3);
		frame.setLocationRelativeTo(null);// 居中显示必须设置在窗体大小之后
		// frame.setResizable(false);//禁止窗体大小改变

		this.setBackground(Color.lightGray);
		frame.add(this, BorderLayout.CENTER);
		
		ChessListener ch = new ChessListener();// 创建事件处理类的对象

		JPanel eastJPanel = new JPanel();// JPanel默认流式布局
		eastJPanel.setPreferredSize(new Dimension(170, 0));
		eastJPanel.setBackground(Color.darkGray);
		frame.add(eastJPanel, BorderLayout.EAST);

		String[] array = { "开始游戏", "悔棋", "认输" };
		for (int i = 0; i < array.length; i++) {
			JButton jbu = new JButton(array[i]);
			
			jbu.setPreferredSize(new Dimension(150, 75));
			jbu.addActionListener(ch);
			eastJPanel.add(jbu);
		}

		String[] itemArray = { "人机对战", "人人对战" };// 设置下拉按钮
		JComboBox<String> cbArray = new JComboBox<String>(itemArray);//建下拉框对象
		eastJPanel.add(cbArray);
		cbArray.setPreferredSize(new Dimension(150, 75));
		frame.setVisible(true);
		cbArray.addActionListener(ch);

		Graphics gr = this.getGraphics();// 从JPanel获取画笔
		ch.setChessListener(gr);// 调用事件处理类的方法,将画笔传给事件处理类的画笔对象
		ch.setC(chess);// 调用事件处理类的方法,将数组传给事件处理类的数组对象
		this.addMouseListener(ch);// 给事件源JPanel添加鼠标监听器
		ch.setFiveChess(fi);//调用事件处理类的方法,将棋盘传给事件处理类的棋盘对象
        ch.setItemArray(cbArray);
	}

	public void drawChessTable(Graphics g) {
		for (int i = 0; i < Config.rows; i++) {// 棋盘横线
			g.drawLine(Config.xo, Config.yo + i * Config.size, Config.xo + (Config.columns - 1) * Config.size,	Config.yo + i * Config.size);
		}
		for (int j = 0; j < Config.columns; j++) {// 竖线
			g.drawLine(Config.xo + j * Config.size, Config.yo, Config.xo + j * Config.size,Config.yo + (Config.rows - 1) * Config.size);
		}
	}
	public void paint(Graphics g) {// 继承JFrame,重绘
		super.paint(g);
		drawChessTable(g);//本类中重绘棋盘
		System.out.println("重绘!");
		
		Graphics2D gr ;//重绘抗锯齿
		gr = (Graphics2D)g;
		  
  gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

		for (int i = 0; i < chess.length; i++) {
			for (int j = 0; j < chess.length; j++) {
				if (chess[i][j] == 1) {
					gr.setColor(Color.BLACK);
					gr.fillOval(xo + i * size - chesssize / 2, yo + j * size - chesssize / 2, chesssize, chesssize);
				} else if (chess[i][j] == 2) {
					gr.setColor(Color.WHITE);
					gr.fillOval(xo + i * size - chesssize / 2, yo + j * size - chesssize / 2, chesssize, chesssize);
				}
			}
		}
	}

}

           ③事件处理类中落子设计,同一交点不能下两次。

              绘制棋子时继承MouseAdapter类,只需要重写一个方法如    public void mouseReleased(MouseEvent e)(接口需要重写每个方法)。

               判断输赢后改变boolean值后,不满足落子条件无法落子。

               创建二维数组,给交点赋值记录棋子颜色。

               创建数列对象(ArrayList<Point> list = new ArrayList<Point>();)用于保存棋子的交点信息。每画出一颗棋子将point点坐标存入队列。。

import java.awt.Color;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.JOptionPane;

public class ChessListener extends MouseAdapter implements Config, ActionListener {
	// 为什么不继承Graphics也可以使用
	private Graphics2D gr;// 创建画笔对象
	private int x, y, x1, y1, m, n;
	private int count = 0;
	private int[][] chess;
	private FiveChess fc;
	private int q = 0;
	private boolean game = true;
	ArrayList<Point> list = new ArrayList<Point>();//创建数列对象,保存棋子交点数据
    private JComboBox<String> cbArray;
	ArrayList<Point> list = new ArrayList<Point>();

	public void setItemArray(JComboBox<String> cbArray) {
		this.cbArray = cbArray;
	}

	public void setChessListener(Graphics g) {// 实例化对象
		gr = (Graphics2D) g;
		gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 抗锯齿
	}

	public void setC(int[][] chess) {
		this.chess = chess;
	}

	public void setFiveChess(FiveChess fc) {
		this.fc = fc;
	}
	public void mouseReleased(MouseEvent e) {// 方法重写
		x1 = e.getX();// 点击获得横坐标
		y1 = e.getY();// 点击获得纵坐标
		for (int j = 0; j < rows; j++) {
			for (int i = 0; i < columns; i++) {
				x = xo + size * i;//交点x坐标
				y = yo + size * j;//交点y坐标
				if (x1 > x - size / 3 && x1 < x + size / 3 && y1 > y - size / 3 && y1 < y + size / 3) {
					if (chess[i][j] == 0 && q > 0 && game == true) {// 如果选择的位置没有棋子,且点击了开始游戏,且可以落子
						if (count == 0) {
							chess[i][j] = 1;
							Point p = new Point();// 创建数列对象用来保存坐标
							p.setLocation(i, j);// 得到坐标
							list.add(p);// 存入p点坐标
							gr.setColor(Color.BLACK);
							gr.fillOval(x - chesssize / 2, y - chesssize / 2, chesssize, chesssize);
							count++;
							// System.out.println("chess[i][j] = "+chess[i][j]);
						} else {
							chess[i][j] = 2;
							Point p = new Point();
							p.setLocation(i, j);
							list.add(p);
							gr.setColor(Color.WHITE);
							gr.fillOval(x - chesssize / 2, y - chesssize / 2, chesssize, chesssize);
							count--;
							// System.out.println("chess[i][j] = "+chess[i][j]);
						}
						m = i;
						n = j;

						this.checkRow(i, j);//调用方法判断输赢
					}
				}
			}
		}
		System.out.println();
	}






	public void checkRow(int x, int y) {// 判断输赢
		int count1 = 0;
		int count2 = 0;
		int count3 = 0;
		// 判断行赢
		for (int i1 = x + 1; i1 < chess.length; i1++) {
			if (chess[i1][y] == chess[x][y]) {
				count1++;

			} else {
				break;
			}
			System.out.println("count1 = " + count1);
		}
		for (int i2 = x; i2 >= 0; i2--) {
			if (chess[i2][y] == chess[x][y]) {
				count1++;
			} else {
				break;
			}
			System.out.println("count1 =" + count1);
		}
		if (count1 == 5) {
			game = false;
			// System.out.println("chess[m][n] ="+chess[m][n]);
			if (chess[m][n] == 1) {
				JOptionPane.showConfirmDialog(null, "黑棋赢了");
			} else {
				JOptionPane.showConfirmDialog(null, "白棋赢了");
			}
			fc.removeMouseListener(this);//由一方胜利或者投降移除鼠标监听器,也可以赋值game = false,不满足条件不能落子
			System.out.println("移除鼠标监听器");
		}

		// 判断列赢
		for (int j = y + 1; j < chess.length; j++) {
			if (chess[x][j] == chess[x][y]) {
				count2++;
			} else {
				break;
			}
			System.out.println("count2 =" + count2);
		}
		for (int j = y; j >= 0; j--) {
			if (chess[x][j] == chess[x][y]) {
				count2++;
			} else {
				break;
			}
			System.out.println("count2 =" + count2);
		}
		if (count2 > 4) {
			game = false;
			if (chess[m][n] == 1) {
				JOptionPane.showConfirmDialog(null, "黑棋赢了");
			} else if (chess[m][n] == 2) {
				JOptionPane.showConfirmDialog(null, "白棋赢了");
			}
			fc.removeMouseListener(this);
		}
		// 判断斜赢
		for (int i = x, j = y; i < rows && j < columns; i++, j++) {
			if (chess[i][j] == chess[x + 1][y + 1]) {
				count3++;
			} else {
				break;
			}
			System.out.println("count3 =" + count3);
		}
		for (int i = x, j = y; i < rows && j < columns; i--, j--) {
			if (chess[i][j] == chess[x - 1][y - 1]) {
				count3++;
			} else {
				break;
			}
			System.out.println("count3 =" + count3);
		}
		for (int i = x, j = y; i < rows && j < columns; i++, j--) {
			if (chess[i][j] == chess[x + 1][y - 1]) {
				count3++;
			} else {
				break;
			}
			System.out.println("count3 =" + count3);
		}
		for (int i = x, j = y; i < rows && j < columns; i--, j++) {
			if (chess[i][j] == chess[x - 1][y + 1]) {
				count3++;
			} else {
				break;
			}
			System.out.println("count3 =" + count3);
		}
		if (count3 > 4) {
			game = false;
			if (chess[m][n] == 1) {
				JOptionPane.showConfirmDialog(null, "黑棋赢了");
			} else if (chess[m][n] == 2) {
				JOptionPane.showConfirmDialog(null, "白棋赢了");
			}
			fc.removeMouseListener(this);
		}
	}

             ④实现按钮功能。动作监听器ActionListener接口的方法重写。变量值控制按下按钮以后是否还可以落子。

                new一个point对象用来存储从队列中移出的交点数据,把交点chess[x][y]=0;即悔棋。

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals("开始游戏")) {
			count = 0;
			q++;
			fc.addMouseListener(this);
			for (int i = 0; i < rows; i++) {
				for (int j = 0; j < columns; j++) {
					chess[i][j] = 0;
				}
			}
			fc.paint(gr);//结束一局游戏重绘棋盘,开始一局新游戏
			game = true;
		}

		if (e.getActionCommand().equals("认输")) {
			if (count == 0) {
				JOptionPane.showConfirmDialog(null, "黑棋认输");//直接弹出对话框黑棋认输
				
			}
			if (count == 1) {
				JOptionPane.showConfirmDialog(null, "白棋认输");
			}
			game = false;
		}

		if (e.getActionCommand().equals("悔棋")) {
			Point p = new Point();创建对象用来存储队列中取出来的点
			p = list.remove(list.size() - 1);赋值p,存储
			chess[(int) p.getX()][(int) p.getY()] = 0;该点重绘为无点
			fc.paint(gr);重绘棋盘
			if (count == 1) {//悔棋后下一颗棋子的颜色判断
				count--;
			} else if (count == 0) {
				count++;
			}
		}
		if(cbArray.getSelectedItem().equals("人人对战")) {
			game= true;
		}else if(cbArray.getSelectedItem().equals("人机对战")){
			JOptionPane.showConfirmDialog(null, "很抱歉!功能正在开发。。。");
		}
	}

猜你喜欢

转载自blog.csdn.net/weixin_42621338/article/details/81121831