五子棋游戏源码 2026 编者注这是 2015 年写的一个 Java Swing 五子棋小项目当年直接贴代码没加结构这次补上章节说明和编译运行指引。代码本身未改动JDK 8 均可运行。最新源码在 GitHub文末链接。一、项目简介这是一个五子棋Gobang桌面游戏最终效果图中棋盘以及棋子均是程序作图Java Swing 绘制无图片资源。整体结构源文件职责GoBangGUI.java主界面窗口、按钮、事件分发GoBangBoard.java棋盘绘制GobangColor.java棋子颜色枚举Place.java棋子位置定义Gobang.java核心逻辑落子、胜负判定运行方式源码包名为game.gobang按目录结构放好后javac game/gobang/*.java java game.gobang.Gobang # 控制台版入口 java game.gobang.GoBangGUI # GUI 版入口需显示器环境二、GoBangGUI.java —— 界面实现这个源文件主要是界面的实现package game.gobang; import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridLayout; 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 javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; public class GoBangGUI extends JFrame{ private JPanel mainframe; private GoBangBoard board; private JPanel control; private GridLayout grid; private BorderLayout border; private JButton start; private JButton end; private JLabel label; private int row; private int column; private Gobang gobang; private MouseAdapter mouselistener; private boolean flag; private boolean ok; private ActionListener actionlistener; public GoBangGUI(){ this(GoBang Game, 10, 10); } public GoBangGUI(String title, int row, int column){ super(title); // this.setUndecorated(true); this.row row; this.column column; this.flag false; this.ok false; initial(); setSize(600, 600); this.setResizable(false); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationByPlatform(true); this.setVisible(true); this.requestFocus(); } private void initial() { createComponent(); layOut(); listener(); } private void createComponent() { mainframe new JPanel(); control new JPanel(); border new BorderLayout(); grid new GridLayout(); start new JButton(Start); label new JLabel(); gobang new Gobang(row, column); board new GoBangBoard(gobang, row, column); end new JButton(Exit); // gobang.getData()[0][0] GobangColor.WHITE; } private void layOut() { this.getContentPane().add(mainframe); // setBackpicture(); // mainframe.setBackground(Color.yellow); mainframe.setLayout(border); mainframe.add(board, BorderLayout.CENTER); // board.setBounds(0, 0, 500, 500); mainframe.add(control, BorderLayout.EAST); Box ve Box.createVerticalBox(); ve.add(start); ve.add(Box.createVerticalStrut(50)); end.setSize(start.getWidth(), start.getHeight()); ve.add(end); control.add(ve); } private void setBackpicture() { ImageIcon a new ImageIcon(/home/qcq/1.jpg); JLabel p new JLabel(a); p.setBounds(0, 0, a.getIconWidth(), a.getIconHeight()); this.getLayeredPane().add(p, Integer.MIN_VALUE); } /* * 判断鼠标落入棋盘窗格的位置索引 (x, y)为当前鼠标的坐标。 */ private Place judgePlace(int indexx, int indexy, int x, int y, int squre){ for (int i 0; i row; i){ for (int j 0; j column; j){ if (x indexx j * squre x indexx (j 1) * squre y indexy i * squre y indexy (i 1) * squre){ return new Place(i, j); } } } return null; } private void listener() { mouselistener new MouseAdapter() { Override public void mousePressed(MouseEvent e) { int x e.getX(); int y e.getY(); /* * (25, 10) is a special coordinate. the board draw begins here, * when the board added to the this JFrame the begin change to * (25, 10 25), However, I do not know why. just keep it; * */ if (ok){ Place temp judgePlace(25, 10, x, y, board.getSqure()); System.out.println(temp); if (flag){ if (!gobang.check(temp.getX(), temp.getY())){ JOptionPane.showMessageDialog(mainframe, Change another place); } else { gobang.setChess(temp.getX(), temp.getY(), GobangColor.WHITE); repaint(); if (gobang.isSuccess(new Place(0, 0), new Place(row - 1, column - 1), GobangColor.WHITE)){ // JOptionPane.showMessageDialog(mainframe, The white player is win); int choice JOptionPane.showConfirmDialog(mainframe, The white player is win, DO you want try again, JOptionPane.YES_NO_OPTION); if (choice JOptionPane.YES_OPTION){ gobang.initial(); ok false; repaint(); } } flag false; } } else { if (!gobang.check(temp.getX(), temp.getY())){ JOptionPane.showMessageDialog(mainframe, Change another place); } else { gobang.setChess(temp.getX(), temp.getY(), GobangColor.BLACK); repaint(); if (gobang.isSuccess(new Place(0, 0), new Place(row - 1, column - 1), GobangColor.BLACK)){ // JOptionPane.showMessageDialog(mainframe, The black player is win); int choice JOptionPane.showConfirmDialog(mainframe, The black player is win, DO you want try again, JOptionPane.YES_NO_OPTION); if (choice JOptionPane.YES_OPTION){ gobang.initial(); ok false; repaint(); } } flag true; } } } else { JOptionPane.showMessageDialog(mainframe, please start the game); } } }; actionlistener new ActionListener() { Override public void actionPerformed(ActionEvent e) { if (((JButton)(e.getSource())).getText().equals(Start)){ ok true; } else if (((JButton)(e.getSource())).getText().equals(Exit)){ System.exit(0); } } }; board.addMouseListener(mouselistener); start.addActionListener(actionlistener); end.addActionListener(actionlistener); } public static void main(String[] args) { GoBangGUI game new GoBangGUI(null, 20, 20); } }三、GoBangBoard.java —— 棋盘绘制本文件是棋盘的绘图package game.gobang; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.LayoutManager; import javax.swing.JPanel; public class GoBangBoard extends JPanel { private Gobang gobang; private int row; private int column; private int squre; public GoBangBoard() { //this.setBounds(x, y, width, height); } public GoBangBoard(Gobang gobang, int row, int column){ this.gobang gobang; this.column column; this.row row; } public int getSqure(){ return squre; } public void paint(Graphics g){ Graphics2D gg (Graphics2D)g; squre (this.getWidth() - 50) / Math.max(row, column); /** * from the point (25, 10) draw the games background. * */ /* * below draw the background gird. * */ int x 25; int y 10; gg.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f,new float[]{5f, 5f},0f)); gg.setColor(Color.blue); for (int i 0; i row; i){ for (int j 0; j column; j){ gg.drawRect(x j * squre, y i * squre, squre, squre); } } for (int i 0; i gobang.getData().length; i){ for (int j 0; j gobang.getData()[i].length; j){ if (GobangColor.WHITE gobang.getData()[i][j]){ gg.setColor(Color.blue); gg.fillOval(x j * squre, y i * squre, squre, squre); } else if (GobangColor.BLACK gobang.getData()[i][j]){ gg.setColor(Color.BLACK); gg.fillOval(x j * squre, y i * squre, squre, squre); } } } gg.setStroke(new BasicStroke(5f)); gg.setColor(Color.blue); gg.drawRect(x - 1, y - 1, squre * column 2, squre * row 2); gg.dispose(); } }四、GobangColor.java —— 棋子颜色枚举本文件是棋子颜色的枚举定义package game.gobang; public enum GobangColor { BLACK, WHITE, NULL }五、Place.java —— 棋子位置本文件是关于棋子位置的定义package game.gobang; /** * here lays the snakes body coordinate information. * */ public class Place { private int x; private int y; public Place(){ this(0, 0); } public Place(int x, int y) { this.x x; this.y y; } public int getX() { return x; } public void setX(int x) { this.x x; } public int getY() { return y; } Override public String toString() { return Place [x x , y y ]; } public void setY(int y) { this.y y; } Override public int hashCode() { final int prime 31; int result 1; result prime * result x; result prime * result y; return result; } Override public boolean equals(Object obj) { if (this obj) return true; if (obj null) return false; if (getClass() ! obj.getClass()) return false; Place other (Place) obj; if (x ! other.x) return false; if (y ! other.y) return false; return true; } }六、Gobang.java —— 核心逻辑本文件是五子棋实现的核心逻辑代码落子、行/列/对角线胜负判定、人机对弈流程package game.gobang; import java.util.Scanner; /** * Question 19、利用二维数组实现五子棋下棋功能 * */ public class Gobang { private GobangColor[][] data; private int row 10; private int column 10; public Gobang() { /* * The default checkerboard is 10 * 10 boxes; * */ this(10, 10); initial(); } /* * Initial the Game * */ public void initial(){ for (int i 0; i row; i){ for (int j 0; j column; j){ data[i][j] GobangColor.NULL; } } } /* * The piece move * */ public void setChess(int row, int column,GobangColor color){ data[row][column] color; } public Gobang(int row, int column){ /* * set the Chess squre to row * line * */ this.row row; this.column column; data new GobangColor[row][]; for (int i 0; i row; i){ data[i] new GobangColor[column]; } initial(); } public GobangColor[][] getData() { return data; } public void setData(GobangColor[][] data) { this.data data; } public int getRow() { return row; } public void setRow(int row) { this.row row; } public int getColumn() { return column; } public void setColumn(int column) { this.column column; } /* * print out the current checkerboard * */ public void printCheckerBoard(){ /* * print out the chessboard layout * */ for (GobangColor[] i: data){ for (GobangColor j : i){ System.out.print(j.toString() ); } System.out.println(); } } /* * verify the input data to insure the piece is in the range * and not put this piece in the history place * 验证棋子在合适的位置上 * */ public boolean check(int x, int y){ if (x 0 || x row || y 0 || y column){ System.out.println(The input is error); System.out.println(The input should from(0, 0) to ( (x - 1) , (y - 1) )); return false; } if (GobangColor.NULL ! data[x][y]){ System.out.println(This place already has one piece!); return false; } return true; } /* * judge if successed, The parameter x and y * is the range which need to be scanning. * The Scanning range can zoom in a range which is a circle(a square) * center in current move, radius is 5. * 扫描棋盘看是不是有棋子获胜可以优化扫描方案将扫描的范围局限于一个以落子处为中心 * 5为半径的棋盘(isSucess的重载方法实现这一个思想)。 */ public boolean isSuccess(Place x, Place y, GobangColor color){ boolean flag false; int counter 0; label: for (int i (int) x.getX(); i (int)y.getX(); i){ for (int j (int)x.getY(); j (int)y.getY(); j){ /* * scanning the [x,y] range in 4 directions. * */ // check the horizontal counter 0; if (j 4 (int)y.getY()){ for (int index j; index j 4; index){ if (color data[i][index]){ counter; } } } if (5 counter){ flag true; break label; } // check the vertical counter 0; if (i 4 (int)y.getX()){ for (int index i; index i 4; index){ if (color data[index][j]){ counter; } } } if (5 counter){ flag true; break label; } //check the dig line counter 0; if ((i 4 (int)y.getX()) (j 4 (int)y.getY())){ for (int indexX i, indexY j; indexX i 4 ;indexX, indexY){ if (color data[indexX][indexY]){ counter; } } } if (5 counter){ flag true; break label; } //check the reverse dig line counter 0; if ((i 4 (int)y.getX()) (j - 4 (int)x.getY())){ for (int indexX i, indexY j; indexX i 4;indexX, indexY--){ if (color data[indexX][indexY]){ counter; } } } if (5 counter){ flag true; break label; } } } return flag; } /* * 这是一个重载的方法与上一个方法不同的是没有使用扫描来实现判定 * 而是基于落子的地方来基于四个方向进行计数判断。 * */ public boolean isSuccess(Place x, GobangColor color){ boolean flag false; /* * horizontal direction * */ int counter 0; for (int i x.getY(); i Math.min(x.getY() - 4, row); i--){ if (color data[x.getX()][i]){ counter; }else{ break; } } for (int i x.getY() 1; i Math.min(x.getY() 4, column - 1); i){ if (color data[x.getX()][i]){ counter; }else{ break; } } if (5 counter){ flag true; } /* * vertical direction * */ counter 0; for (int i x.getX(); i Math.min(x.getX() - 4, row); i--){ if (color data[i][x.getY()]){ counter; }else{ break; } } for (int i x.getY() 1; i Math.min(x.getY() 4, column - 1); i){ if (color data[i][x.getY()]){ counter; }else{ break; } } if (5 counter){ flag true; } /* * diagonal direction * */ counter 0; for (int i x.getX(), j x.getY(); i Math.min(x.getX() - 4, row) j Math.min(x.getY() - 4, row); i--, j--){ if (color data[i][j]){ counter; }else{ break; } } for (int i x.getX() 1, j x.getY() 1; i Math.min(x.getX() 4, column - 1) j Math.min(x.getY() 4, column - 1); i, j){ if (color data[i][j]){ counter; }else{ break; } } if (5 counter){ flag true; } /* * reverse diagonal direction * */ counter 0; for (int i x.getX(), j x.getY(); i Math.min(x.getX() 4, column - 1) j Math.min(x.getY() - 4, row); i, j--){ if (color data[i][j]){ counter; }else{ break; } } for (int i x.getX() 1, j x.getY() 1; i Math.min(x.getX() - 4, row) j Math.min(x.getY() 4, column - 1); i--, j){ if (color data[i][j]){ counter; }else{ break; } } if (5 counter){ flag true; } return flag; } /* * The actual game start here, where black first, white second, * we can optimize the game which do not call * the method isSuccess in the first segment. such as 8 moves. * and we can narrow the scanning the range to a square just talk above. * */ public void playChess(){ Scanner in new Scanner(System.in); Place x new Place(0, 0); Place y new Place(row - 1, column - 1); label: while (true){ //The input should like 1,2 while (in.hasNext()){ String[] str in.next().split(,); int indexX Integer.valueOf(str[0]); int indexY Integer.valueOf(str[1]); if (!check(indexX, indexY)){ System.out.println(please input again); continue; }else{ setChess(indexX, indexY, GobangColor.BLACK); printCheckerBoard(); // if (isSuccess(x, y, GobangColor.BLACK)){ if (isSuccess(new Place(indexX, indexY), GobangColor.BLACK)){ System.out.println(The Black is win); break label; } break; } } while (in.hasNext()){ String[] str in.next().split(,); int indexX Integer.valueOf(str[0]); int indexY Integer.valueOf(str[1]); if (!check(indexX, indexY)){ System.out.println(please input again); continue; }else{ setChess(indexX, indexY, GobangColor.WHITE); printCheckerBoard(); // if (isSuccess(x, y, GobangColor.WHITE)){ if (isSuccess(new Place(indexX, indexY), GobangColor.WHITE)){ System.out.println(The White is win); break label; } break; } } } in.close(); } public static void main(String[] args) { Gobang chess new Gobang(); chess.playChess(); } }七、总结一个完整的 Swing 小游戏适合初学者理解1.界面与逻辑分离GUI 只做展示和事件转发胜负判定集中在Gobang 2.绘图即视图GoBangBoard用Graphics画棋盘网格和棋子 3.胜负判定落子后检查横、竖、两条对角线方向是否五子连珠。代码写于 2015 年风格略显稚嫩比如 GUI 类里字段偏多但胜在完整可跑。欢迎在 GitHub 上继续改进。*GitHub 最新源码见作者仓库 qcq/WeChat 同名目录。*