五字棋(JAVA小项目)

前言:老师上课布置的一个课后作业(写一个棋类的游戏),我就选了一个自我感觉最简单的一个来写--五子棋。第一次写这这样的有界面的工程,参考了一些网上的代码。

源码链接点击这里

由于我们学的是Swing 所以这里就用Swing来实现这个工程。


首先得有一个主类(StartChess.java)程序的入口。用来加载窗口,然后在窗口上添加组件。

这里我的窗口采用的BorderLayout 布局管理器 在北部添加一个工具面板 上面放一些 开始,悔棋的按钮以及提示框,再在窗口上填加一个棋盘面板下棋用

然后是一棋盘类(ChessBoard.java)继承 JPanel 

最后是一个棋子类(Point.java)

运行效果图:




package sc.job.wuziqi;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/*
 * 游戏主类(main)
 * 加载窗口加载组件
 * */
public class StartChess extends JFrame {
	private ChessBoard chessboard;// 棋盘面板
	private JPanel tool; // 工具面板
	private Button restartB;// 重新开始按钮
	private Button exitB;// 退出按钮
	private Button backB;// 悔棋按钮
	public static JLabel tooltip; // 游戏提示框,用做显示游戏结束和获胜方

	public static void main(String[] args) {
		StartChess sc = new StartChess();
		sc.setVisible(true);// 显示窗口
	}

	public StartChess() {
		super();
		setTitle("五子棋小游戏");
		setBounds(100, 100, 20 + 30 * 2 + 35 * 15, 40 + 40 + 60 + 35 * 15);// 设置窗口的大小
		chessboard = new ChessBoard();// 实例化棋盘面板
		tool = new JPanel();// 实例化工具面板
		restartB = new Button("重新开始");// 初始化按钮SC
		exitB = new Button("退出");
		backB = new Button("悔棋");
		tooltip = new JLabel("欢迎来到SC的五子棋小游戏");
		tooltip.setFont(new Font("", Font.PLAIN, 16));// 设置提示框的字体和字号
		tooltip.setForeground(Color.blue);// 设置提示框的字体颜色
		tool.setLayout(new FlowLayout(FlowLayout.CENTER));// 用流式布局设为中间对齐
		tool.add(backB);// 将三个按钮添加到面板上
		tool.add(restartB);
		tool.add(exitB);
		tool.add(tooltip);
		/*
		 * 设置三个按钮的事件处理
		 */
		restartB.addActionListener(new ActionListener() {// 重新开始按钮
			public void actionPerformed(ActionEvent e) {
				chessboard.restartGame();
				StartChess.tooltip.setText("游戏重新开始");
				StartChess.tooltip.setForeground(Color.blue);
			}
		});
		exitB.addActionListener(new ActionListener() {// 退出按钮
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		backB.addActionListener(new ActionListener() {// 悔棋按钮
			public void actionPerformed(ActionEvent e) {
				chessboard.goBack();
			}
		});
		add(tool, BorderLayout.NORTH);// 将工具面板添加到窗口的北部
		add(chessboard);// 在窗口上添加棋盘面板
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 设置界面关闭事件
		// pack();
	}
}

package sc.job.wuziqi;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

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

/*
 * 棋盘类
 * 画棋盘和棋子 
 * */
public class ChessBoard extends JPanel {
	public final static int EDGE = 30;// 边距
	public final static int SPACE = 35;// 间距
	public final static int ROCO = 15;// 行列数
	Point[] chessList = new Point[(ROCO + 1) * (ROCO + 1)];// 存储已经下的棋子
	boolean isBack = true;// 默认黑棋先下
	boolean gameOver = false;// 游戏是否结束
	int xId, yId;// 棋子的坐标
	int chessCount;// 棋子个数

	public ChessBoard() {
		setBackground(Color.ORANGE);
		// 添加事件监听器
		addMouseListener(new MouseListener() {// 鼠标事件监听

			@Override
			public void mouseReleased(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
				if (gameOver)
					return;
				xId = (e.getX() - EDGE + SPACE / 2) / SPACE;// 获取鼠标点击位置在棋盘上的索引
				yId = (e.getY() - EDGE + SPACE / 2) / SPACE;
				// System.out.println(xId + " " + yId);
				if (xId < 0 || yId < 0 || xId > ROCO || yId > ROCO)
					return;// 超出棋盘边界
				if (findchess(xId, yId))
					return;// 该棋子已经存在
				Point c = new Point(xId, yId, isBack ? Color.black : Color.white);
				chessList[chessCount++] = c;
				repaint();// 重新画图
				if (isWin()) {
					if (isBack) {
						StartChess.tooltip.setText("黑方胜,游戏结束");
						StartChess.tooltip.setForeground(Color.RED);
					} else {
						StartChess.tooltip.setText("白方胜,游戏结束");
						StartChess.tooltip.setForeground(Color.RED);
					}
					gameOver = true;
				} else if (chessCount == (ROCO + 1) * (ROCO + 1)) {// 棋盘下满的情况
					StartChess.tooltip.setText("平局,旗鼓相当,游戏结束");
					StartChess.tooltip.setForeground(Color.RED);
					gameOver = true;
				}
				isBack = !isBack;// 换另一方下棋
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseClicked(MouseEvent e) {
			}
		});
	}

	// 查找该索引上是否有棋子
	boolean findchess(int x, int y) {
		for (Point obj : chessList) {
			if (obj != null && obj.getY() == y && obj.getX() == x)
				return true;
		}
		return false;
	}

	// 画棋盘和棋子
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		for (int i = 0; i <= ROCO; i++) {// 画横线
			g.drawLine(EDGE, EDGE + i * SPACE, EDGE + ROCO * SPACE, i * SPACE + EDGE);
		}
		for (int i = 0; i <= ROCO; i++) {// 画竖线
			g.drawLine(EDGE + i * SPACE, EDGE, i * SPACE + EDGE, EDGE + ROCO * SPACE);
		}
		//在网格中画五个小点
		g.fillOval(EDGE+3*SPACE-4,EDGE+3*SPACE-4,8,8);
		g.fillOval(EDGE+12*SPACE-4,EDGE+3*SPACE-4,8,8);
		g.fillOval(EDGE+7*SPACE-4,EDGE+7*SPACE-4,8,8);
		g.fillOval(EDGE+3*SPACE-4,EDGE+12*SPACE-4,8,8);
		g.fillOval(EDGE+12*SPACE-4,EDGE+12*SPACE-4,8,8);
		
		
		//画棋子
		for (int i = 0; i < chessCount; i++) {
			int xpos = chessList[i].getX() * SPACE + EDGE;// 获取棋子在棋盘的坐标
			int ypos = chessList[i].getY() * SPACE + EDGE;
			g.setColor(chessList[i].getColor());// 获取棋子的颜色
			g.fillOval(xpos - Point.PSIZE / 2, ypos - Point.PSIZE / 2, Point.PSIZE, Point.PSIZE);// 画出棋子
			if (i == chessCount - 1) {
				g.setColor(Color.red);// 将画笔的颜色改为红色
				g.drawRect(xpos - Point.PSIZE / 2, ypos - Point.PSIZE / 2, Point.PSIZE, Point.PSIZE);// 标记最后一个棋子
			}
		}
	}

	/*
	 * 判断输赢
	 */
	boolean isWin() {
		int count = 1;
		Color c = isBack ? Color.black : Color.white;
		// 以新下的棋子为开始向左右(横向)查找是否有5个连续的同色子
		for (int i = xId - 1; i >= 0; i--)
			if (getChess(i, yId, c))
				count++;
			else
				break;
		for (int i = xId + 1; i <= ROCO; i++)
			if (getChess(i, yId, c))
				count++;
			else
				break;
		if (count >= 5)
			return true;
		// 同上在竖直方向进行检索
		count = 1;
		for (int i = yId - 1; i >= 0; i--)
			if (getChess(xId, i, c))
				count++;
			else
				break;
		for (int i = yId + 1; i <= ROCO; i++)
			if (getChess(xId, i, c))
				count++;
			else
				break;
		if (count >= 5)
			return true;
		// 分别向左上和右下
		count = 1;
		for (int i = xId - 1, j = yId - 1; i >= 0 && j >= 0; i--, j--) {
			if (getChess(i, j, c))
				count++;
			else
				break;
		}
		for (int i = xId + 1, j = yId + 1; i <= ROCO && j <= ROCO; i++, j++) {
			if (getChess(i, j, c))
				count++;
			else
				break;
		}
		if (count >= 5)
			return true;
		// 右上左下
		count = 1;
		for (int i = xId + 1, j = yId - 1; i <= ROCO && j >= 0; i++, j--) {
			if (getChess(i, j, c))
				count++;
			else
				break;
		}
		for (int i = xId - 1, j = yId + 1; i >= 0 && j <= ROCO; i--, j++) {
			if (getChess(i, j, c))
				count++;
			else
				break;
		}
		if (count >= 5)
			return true;
		return false;
	}

	boolean getChess(int x, int y, Color c) { // 查询该棋子是否存在
		for (Point obj : chessList) {
			if (obj != null && obj.getX() == x && obj.getY() == y && obj.getColor() == c)
				return true;
		}
		return false;
	}

	public void restartGame() { // 重新开始游戏的的处理函数
		for (int i = 0; i < chessCount; i++)
			chessList[i] = null;
		isBack = true;
		gameOver = false;
		chessCount = 0;
		repaint();
	}

	public void goBack() { // 悔棋的处理函数
		if (chessCount == 0)
			return;
		chessList[chessCount - 1] = null;
		chessCount--;
		isBack = !isBack;
		gameOver = false;
		repaint();
	}
}


package sc.job.wuziqi;

import java.awt.Color;

/*
 * 棋子类
 * */
public class Point {
	private int x;
	private int y; // 棋子在棋盘上的索引
	private Color color; // 棋子的颜色
	public final static int PSIZE = 30;

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

	/*
	 * 获取棋子的坐标及其颜色
	 */
	public int getX() {
		return x;
	}

	public int getY() {
		return y;
	}

	public Color getColor() {
		return color;
	}
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值