尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Java五子棋课程设计实战:Swing界面、二维数组与胜负判定

发布时间:2026/9/23 23:16:32

资讯中心
01
ARTICLE

Java五子棋课程设计实战:Swing界面、二维数组与胜负判定

Java五子棋课程设计实战:Swing界面、二维数组与胜负判定
简介一份基于 Java 的五子棋对战系统课程设计源码适合 Java 学习者、高校学生及需要完成课设或实战练手的开发者参考覆盖了从游戏初始化、玩家操作处理到胜负判断的完整流程。资源共 290 个文件、18.26MB核心为 17 个 Java 源文件另有 265 个 GIF 图像用于棋盘、棋子与动画表现3 个 XML 配置文件负责界面布局和参数设置还包含 WAV 音效、JPG 图片、说明文档、Git 忽略文件与 IntelliJ IDEA 项目文件结构与常用的 Java 桌面项目一致。目前已有 281 人学习下载适合作为课程设计作品或 Java GUI 编程的入门样例。通过阅读和运行源码可掌握 GUI 界面搭建、鼠标交互、棋盘状态管理、胜负判定等关键实现也能学习到项目模块划分、资源文件组织与音效播发等实践细节为后续开发更复杂的交互游戏打下基础。1. 从课设答辩到可运行的Java五子棋对战系统答辩现场评委最常追问的一句话是「你这个Java五子棋对战系统的胜负判断到底怎么写的」。如果你能当场打开工程指着棋盘扫描循环讲清四方向连珠计数再花两分钟演示双人对战、悔棋和重新开局设计实现这门课的成绩基本就稳了。这套基于Java五子棋对战系统的设计实现源码包正是这样一个能直接跑、也经得起深挖的课设完整案例17个Java源文件负责逻辑与界面265个GIF图像负责棋盘、棋子和按钮反馈3个XML配置文件控制参数与布局外加WAV音效和IDEA工程文件组成闭环。适合正在做Java课程设计案例源码复现的同学也适合准备Java面试八股文、需要真实项目支撑的开发者对照着拆。2. 工程文件解剖readme入口、17个Java源文件与265个GIF的职责分配拿到任何一个课设源码包第一件事不是打开IDE乱点而是先读文件清单把「谁来启动、谁来画、谁来判」这三个问题确认清楚。2.1 先看readme.txt和module文件再点运行课设包默认会带readme.txt里面一般写清楚JDK版本、入口类名和运行步骤。这个项目根目录下的readme.txt承担的就是这个职责先确认本机JDK版本不低于8然后用IntelliJ IDEA以Open方式加载整个工程目录等模块结构索引完成后找到主类直接运行。这里有个很容易踩的坑IDEA首次打开这类目录结构不严谨的工程时会提示Project SDK未配置。处理方式是在Project Structure里把SDK指向本机JDK再把src目录标记为Sources Root。对这种没有pom.xml的纯JDK工程IDEA里的Maven面板是空的运行按钮可能灰着不用慌右键源码主类手动Run即可。提示不要因为工程里没有Maven或Gradle就怀疑源码不完整。这类课设项目本就是纯JDK工程依赖只有JDK自带的桌面模块反而省去了依赖下载与冲突的麻烦。2.2 用资源清单盘清家底GIF、XML、WAV各自的位置把这个项目的文件按类型摊开看能明显看出它是按「资源驱动型课设」的思路组织的。先看整体清单再逐类说明。文件类型数量主要职责Java源文件17程序入口、窗口、棋盘绘制、游戏逻辑、音效播放、配置解析GIF图像265棋盘、棋子、头像、按钮状态、界面动效XML配置文件3窗口尺寸、棋盘边距、玩家名称等参数WAV音频1落子声、胜负提示音JPG图像1启动画面或背景图IDEA工程文件1保存模块结构供IDEA直接打开Markdown与Git忽略文件2说明文档、版本控制配置单看文件名就能还原大部分用途board.gif是棋盘底图start.gif是开始按钮的常态图标boy1.gif是玩家头像wuziqi.gif是标题区的五子棋logo57-2.gif和83-2.gif这类数字命名的通常是黑白棋子的切图。而xiangqi.gif、xqnoone.gif这种明显是从一套棋类素材包里打包残留的象棋素材不影响运行可以忽略或清理。答辩时评委扫一眼资源目录就知道你对每张图是否心里有数。2.3 为什么用Swing而不是JavaFX做课设从技术栈看这17个Java源文件大概率是基于Swing/AWT完成的原因是Swing的组件树和事件模型天然适合棋盘类交互且JDK自带不需要额外配置JavaFX SDK或引入第三方界面库对纯Java课程设计来说学习成本最低。Swing的套路很固定JFrame负责窗口JPanel负责画布MouseListener负责落子事件ActionListener负责按钮事件。这本身就是观察者模式的直接应用——界面对象订阅事件源事件发生后回调各自处理方法。用「设计模式Java实现」的角度去看这份源码你会发现代码里不止一个可讲的模式棋盘面板只负责绘制游戏引擎只负责规则二者通过控制器衔接这又带了一点MVC的影子。再加上这个项目用265个GIF而不是手绘棋子说明设计重点是「把图片素材正确渲染到组件上」而不是从零实现绘图算法。理解到这一层再去拆代码主线就很清晰了资源加载棋盘状态维护鼠标交互换算胜负判定。2.4 标准工程目录的等效复现源码包里没有给出标准Maven结构但为了便于对照复现整理后的目录等效结构如下src/ ├── StartGame.java # 程序入口 ├── MainFrame.java # 主窗口负责组装组件 ├── BoardPanel.java # 棋盘绘制面板 ├── GameEngine.java # 规则与状态管理 ├── Player.java # 玩家信息与先后手控制 ├── SoundPlayer.java # WAV音效播放 └── ... # 其余辅助类 res/ ├── board.gif # 棋盘底图 ├── start.gif # 开始按钮 ├── boy1.gif # 玩家头像 ├── wuziqi.gif # 标题logo ├── 57-2.gif # 白棋子切图 ├── 83-2.gif # 黑棋子切图 └── ... config/ ├── config.xml # 棋盘格宽、窗口尺寸、玩家名 readme.txt # 运行说明这里列出的类名是对常见实现方式的等效还原并不保证与原项目每个文件名一一对应。真正的价值在于「入口-窗口-面板-逻辑」这四层职责边界在课设源码里普遍成立答辩时能把这四层关系讲清楚比背出全部类名更有说服力。先交代清楚资源与结构下一章进入代码核心棋盘如何建模胜负如何判定。3. 棋盘数据模型与四向连珠检测把五子棋规则压进内存五子棋的规则精简到最后就是两件事一个15×15的棋盘一个五子连珠的判定。3.1 用二维数组建模棋盘用像素换算定位落子最常见的数据结构是int[15][15]二维数组0表示空1表示黑棋2表示白棋。空间占用极小遍历效率高打印调试也直观。public class ChessBoard { public static final int SIZE 15; private final int[][] grid new int[SIZE][SIZE]; private int currentPlayer 1; // 1黑 2白 public boolean place(int row, int col) { if (row 0 || row SIZE || col 0 || col SIZE) { return false; // 边界保护 } if (grid[row][col] ! 0) { return false; // 已有棋子拒绝重复落子 } grid[row][col] currentPlayer; return true; } public void switchPlayer() { currentPlayer 3 - currentPlayer; // 1变22变1 } public int getPiece(int row, int col) { return grid[row][col]; } }place方法里的两个if是整个棋盘合法性的底线越界检测防止数组下标异常占用检测防止同一坐标被重复点击。currentPlayer用1和2表示切换时用3 - currentPlayer避免了if-else代码简洁。getPiece则提供给绘制面板逐格查询棋子颜色。鼠标点击拿到的是像素坐标必须换算成网格索引才能落子。换算公式是int col (mouseX - margin gridSize / 2) / gridSize其中margin是棋盘左边距gridSize是每格的像素宽度。加上gridSize/2这一步做四舍五入再除以格宽就能把点击位置正确归入最近的格子。不这样处理的话点在线附近时翻车概率极高。3.2 四方向连珠检测从落子点向两端延伸胜负判断是五子棋实现里最值得展开讲的部分。常见误区是全盘扫描每个棋子并向四周数连珠这在15×15的棋盘上算不上性能问题但逻辑冗余且不优雅。更清晰的做法是只从「最新落下的那一颗棋子」出发沿四个方向统计同色连续数量。方向行增量(dRow)列增量(dCol)连珠含义水平01左右连珠垂直10上下连珠正斜11左上到右下反斜1-1右上到左下原理是新落子的位置若形成五连这条连线必然穿过当前点。因此只需要在四个方向上分别向两个方向延伸计数正反两个方向合计大于等于5即为胜利。public boolean checkWin(int row, int col) { int color grid[row][col]; if (color 0) { return false; } int[][] directions {{0, 1}, {1, 0}, {1, 1}, {1, -1}}; for (int[] dir : directions) { int count 1; count countDirection(row, col, dir[0], dir[1], color); count countDirection(row, col, -dir[0], -dir[1], color); if (count 5) { return true; } } return false; } private int countDirection(int row, int col, int dRow, int dCol, int color) { int count 0; int step 1; while (true) { int r row dRow * step; int c col dCol * step; if (r 0 || r ChessBoard.SIZE || c 0 || c ChessBoard.SIZE) { break; // 越界立即停止 } if (grid[r][c] ! color) { break; // 遇到异色或空位立即停止 } count; step; } return count; }checkWin先取落子点颜色做前置判断再对四个方向逐一扩展。countDirection里的step控制向某个方向推进的步数越界或遇到异色就break。总连通数等于正向计数加反向计数加自身1。这种写法在落子后立刻判断即可不必每次全盘扫描。对后续扩展人机对战也有好处AI评估候选点时只需要做局部扫描不必重复遍历整个棋盘。3.3 悔棋栈与开局重置小心玩家切换的顺序双人对战模式大概率会被问到「能不能悔棋」。二维数组只保存当前局面所以需要另开一个栈来记录落子历史。private final ArrayDequeint[] history new ArrayDeque(); public boolean undo() { if (history.isEmpty()) { return false; } int[] last history.pop(); grid[last[0]][last[1]] 0; switchPlayer(); // 悔棋后把回合退给被悔掉的一方 return true; }history里存的是int[]{row, col}。悔棋时弹栈清空对应格子再切回玩家。这里最容易出的bug是悔棋操作忘了交换currentPlayer结果一方连续走了两步。开局重置则要做三件事grid全部归零、history清空、currentPlayer置为1少一个都不行。注意如果后续要做网络对战悔棋不能像本地一样直接弹栈执行需要先发给对方确认才能共同回退。数据结构定了接着看JFrame这边如何把状态画出来、如何响应鼠标。4. JFrame事件循环与GIF渲染让棋子响应鼠标与音效Swing程序的骨架是先组窗口再画画布最后挂事件。这一章按顺序把三层串起来讲。4.1 paintComponent绘制背景图垫底棋子循环画棋盘窗口通常是一个主JFrame中间放一个BoardPanel四周放按钮。所有绘制逻辑集中在paintComponent里。Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(boardImg, 0, 0, getWidth(), getHeight(), this); for (int r 0; r ChessBoard.SIZE; r) { for (int c 0; c ChessBoard.SIZE; c) { int piece board.getPiece(r, c); if (piece 1) { g.drawImage(blackPiece, MARGIN c * GRID_SIZE - PIECE_SIZE / 2, MARGIN r * GRID_SIZE - PIECE_SIZE / 2, this); } else if (piece 2) { g.drawImage(whitePiece, MARGIN c * GRID_SIZE - PIECE_SIZE / 2, MARGIN r * GRID_SIZE - PIECE_SIZE / 2, this); } } } }第一张棋盘底图直接拉伸铺满面板确保窗口缩放后棋盘格线与图片自带的格子仍然对齐。棋子绘制用MARGIN加网格索引再减去棋子半径的一半锚点就能精确落在交叉点上。加载图片时建议用Toolkit.getDefaultToolkit().getImage()或ImageIO.read。前者加载GIF不阻塞UI线程后者能拿到宽高做异常判断。不要直接在paintComponent里加载图片文件否则每次重绘都会重新读磁盘拖动窗口时会出现明显卡顿。正确做法是在构造函数里把图片预加载为成员变量重绘时只做内存贴图。4.2 鼠标落子事件与音效联动给BoardPanel挂上MouseAdapter在mouseClicked里完成「像素换算、落子、重绘、判胜」整条链路。boardPanel.addMouseListener(new MouseAdapter() { Override public void mouseClicked(MouseEvent e) { int col (e.getX() - config.margin config.gridSize / 2) / config.gridSize; int row (e.getY() - config.margin config.gridSize / 2) / config.gridSize; if (board.place(row, col)) { soundPlayer.play(move.wav); boardPanel.repaint(); if (board.checkWin(row, col)) { JOptionPane.showMessageDialog(frame, (board.getCurrentPlayer() 1 ? 黑棋 : 白棋) 获胜); board.reset(); boardPanel.repaint(); } else { board.switchPlayer(); } } } });每一行的职责都很明确换算坐标保证点击对齐交叉点place返回false说明点到棋盘外的边距或者该位置已有棋子直接return不做状态变更repaint触发paintComponent重绘棋盘上立刻多出一颗子checkWin判胜后弹窗并reset让下一局从空棋盘开始。图片与音效在这里的分工很清晰对应关系可以整理成一张表资源名使用场景加载位置board.gif棋盘底图背景BoardPanel构造函数start.gif开始按钮常态图标MainFrame按钮初始化boy1.gif玩家信息区头像信息面板WAV音频文件落子与胜负提示SoundPlayer初始化4.3 用XML配置代替硬编码参数源码里的3个XML配置文件常见用途是存储窗口尺寸、棋盘格大小、玩家名称这类随时可调的参数。与其在代码里到处写死15、560这样的魔法数字不如启动时统一解析一次。DocumentBuilderFactory factory DocumentBuilderFactory.newInstance(); DocumentBuilder builder factory.newDocumentBuilder(); Document doc builder.parse(new File(config/config.xml)); int gridSize Integer.parseInt(doc.getElementsByTagName(gridSize).item(0).getTextContent()); int margin Integer.parseInt(doc.getElementsByTagName(margin).item(0).getTextContent());布尔型配置用Boolean.parseBoolean解析非法值则需要捕获NumberFormatException并回退到默认值。把配置外置有两个实际好处一是答辩现场改数字看效果非常直观二是体现了「配置与代码分离」的工程意识。XML在这里没有引入任何第三方依赖JDK自带的DOM解析就足够。至此一局双人五子棋从点击到判胜的完整链路已经闭合。最后聊答辩自测与进阶方向。5. 答辩前自测与三条升级路线5.1 十分钟验收自测表课设深度如何取决于你对自己代码的掌控力。评分老师最怕的不是功能少而是代码一追问就穿帮。下面这组自测建议在答辩前一天完整走一遍发现偏差就回到对应章节排查。走自测的同时也是在练手速现场演示时节奏感很重要。功能点操作预期结果基础对局黑白交替点击棋盘棋子在交叉点上每回合正确切换玩家重复落子点击已落子位置无反应且不消耗当前回合边界落子点棋盘四角棋子落在角交叉点不越界五连判定水平/垂直/斜线各摆出五连弹窗提示对应颜色获胜悔棋功能任意对局后点击悔棋最后一颗子消失回合退回正确一方重新开局对局中点击重新开始棋盘清空黑棋先行自测前的准备动作也值得做一遍先在IDEA里Run一次确认一切正常再打开命令行用javac编译入口类、用java命令执行。命令行能跑出窗口说明源码不依赖任何IDE特定配置这在答辩现场是很有力的证据。5.2 三条不折腾的升级路线第一条是给当前引擎加一个「五子棋网页版人机」里常见的简单AI。做法是先对每个空位打分以该点为中心沿四方向统计周围同色连续数连三连四分别设置不同权重黑方分数与白方分数按攻防策略加权后取最大值落子。这里要特别注意AI评估时一定要通过clone棋盘或「落子再撤销」的方式模拟不能把真实局面改掉否则评估完当前回合就丢了。第二条是改成网络对战。用ServerSocket监听端口两端通过ObjectOutputStream传输序列化的落子对象。核心问题是同步一方落子后对方不能立刻落子需要一个isMyTurn布尔开关控制。这里的同步逻辑不难但对应了网络编程里经典的状态同步问题是答辩时最能展开的加分点。第三条成本最低是重构代码里的观察者关系。给棋盘类定义一个onPiecePlaced回调接口每次落子后触发回调UI侧响应重绘。这样游戏逻辑完全不依赖Swing类以后接控制台或Web层都不用改规则代码。只需要新增一个接口和一行回调调用就能让答辩评审看到你有面向对象设计意识。顺带提一个容易被忽略的细节做完自测表后把存放GIF和WAV文件目录与源码目录的相对路径关系固化下来不要在代码里写死绝对路径否则换一台电脑演示时资源加载不到棋盘直接白屏。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。