前言:老师上课布置的一个课后作业(写一个棋类的游戏),我就选了一个自我感觉最简单的一个来写--五子棋。第一次写这这样的有界面的工程,参考了一些网上的代码。
源码链接点击这里
由于我们学的是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;
}
}