基于Java Swing开发的五子棋游戏(2)
本项目实现了一个功能完善的五子棋游戏,采用面向对象设计,核心类包括GomokuGame和GamePanel。系统使用15x15二维数组存储棋盘状态,并采用三维缓存数组优化AI性能。AI算法包含三个难度级别:初级(贪心)、中级(Minimax)和高级(Alpha-Beta剪枝)。胜负判定采用中心扩展法检查四个方向的连续棋子。项目进行了全面测试,包括功能测试(界面、落子、悔棋等)、性能测试(响应时间、
·
1、演示视频
基于Java Swing开发的五子棋游戏
2、项目截图






3. 设计说明
3.1 总体架构
项目采用面向对象的设计思想,主要包含以下核心类:
GomokuGame:主类,负责创建窗口、初始化UI组件、管理游戏状态(如模式、难度、步数、时间)。GamePanel:继承自JPanel,是游戏的核心逻辑类,负责绘制棋盘、处理鼠标事件、管理棋盘状态、执行AI逻辑。
3.2 数据结构
int[][] board:二维数组,大小为15x15,用于存储棋盘状态(0=空,1=黑棋,2=白棋)。int[][][] cachedScores:三维数组,用于缓存每个位置在每个方向上的棋型分数,是性能优化的关键。List<Point> chessList:列表,记录所有已落子的位置,用于悔棋和标记最后一步。Deque<Integer> history:双端队列,记录每一步的棋子总数,用于悔棋时恢复状态。
3.3 性能优化
项目在AI评估函数方面进行了多项性能优化,以确保在中级和高级难度下AI能够快速响应:
- 缓存机制:使用
cachedScores数组缓存每个位置的棋型分数。每次落子后,只需更新受影响区域的缓存,避免了每次评估时都重新计算整个棋盘的复杂度。 - 局部搜索:在
evaluateBoard和findPossibleMoves方法中,只评估和搜索棋子附近的区域,而非整个棋盘,大大减少了计算量。 - 位运算存储:在
getPatternScore中,将AI和玩家的分数存储在同一个整数的高低16位中,提高了内存访问和数据处理效率。
4. 算法说明
4.1 胜负判定算法
胜负判定采用中心扩展法。当一个棋子落下后,程序会以该棋子为中心,检查四个方向(水平、垂直、两个对角线)上连续同色棋子的数量。如果任一方向达到或超过5个,则判定该颜色的玩家获胜。
private boolean checkWin(int row, int col) {
int player = board[row][col];
return (countConnectedStones(row, col, 1, 0, player) >= 5 || // 水平
countConnectedStones(row, col, 0, 1, player) >= 5 || // 垂直
countConnectedStones(row, col, 1, 1, player) >= 5 || // 右下对角
countConnectedStones(row, col, 1, -1, player) >= 5); // 右上对角
}
4.2 AI评估函数
AI的决策基于一个综合评估函数,该函数计算棋盘上每个空位对AI的价值。评估值由三部分组成:
- 位置权重:中心位置权重更高,边缘位置权重较低。
- 棋型分数:评估在该位置落子后形成的棋型(如活三、活四、冲四等)带来的价值。
- 攻防平衡:AI不仅考虑自己的进攻得分,也考虑阻止对手的防守得分。
评估函数利用缓存的棋型分数,避免了重复计算,显著提升了性能。
4.3 AI搜索算法
- 初级 (贪心):遍历所有空位,计算每个位置的评估得分,选择得分最高的位置落子。
- 中级 (Minimax):使用Minimax算法,递归搜索未来几步的棋局,模拟AI和玩家的轮流下棋,选择能获得最大收益的移动。搜索深度为2。
- 高级 (Alpha-Beta剪枝):在Minimax基础上引入Alpha-Beta剪枝技术,通过剪除无效分支来减少搜索节点,提高搜索效率。搜索深度为3。
5. 测试说明
5.1 功能测试
- 界面测试:验证窗口、按钮、标签、下拉框等UI组件是否正常显示和响应。
- 落子测试:验证鼠标点击是否能正确转换为棋盘坐标并放置棋子。
- 模式切换测试:验证双人模式和人机模式之间的切换是否正常。
- 难度切换测试:验证AI难度选择和算法信息显示是否正确。
- 悔棋测试:验证在不同模式下悔棋功能是否按预期工作(双人模式悔一步,人机模式悔两步)。
- 胜负判定测试:手动构建五子连线场景,验证胜负判定是否准确。
5.2 性能测试
- AI响应时间:在中级和高级难度下,测试AI下棋的响应时间,确保在可接受范围内(通常小于1秒)。
- 内存使用:监控程序运行时的内存占用,确保没有内存泄漏。
- CPU占用:在AI思考时监控CPU占用率,确保算法优化有效。
5.3 边界测试
- 棋盘边界:测试在棋盘边缘落子的行为。
- 游戏结束:测试游戏结束后,点击棋盘、悔棋等操作是否被正确阻止。
- 模式切换:测试在游戏进行中切换模式的行为。
6. 关键代码
6.1 棋盘状态管理
private int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
private List<Point> chessList = new ArrayList<>();
private Deque<Integer> history = new ArrayDeque<>();
6.2 AI评估函数核心
private int evaluatePosition(int row, int col) {
int positionValue = POSITION_WEIGHTS[row][col];
int score = 0;
int aiScore = 0;
int playerScore = 0;
for (int d = 0; d < 4; d++) {
int cachedValue = cachedScores[row][col][d];
aiScore += cachedValue & 0xFFFF;
playerScore += (cachedValue >> 16) & 0xFFFF;
}
score = (int)(aiScore * 1.0 + playerScore * 0.9) + positionValue;
return score;
}
6.3 棋型分数缓存与更新
private int getPatternScore(int row, int col, int direction) {
// ... (棋型分析逻辑) ...
return (playerPatternScore << 16) | (aiPatternScore & 0xFFFF);
}
private void updateCachedScores(int row, int col) {
int range = 4;
for (int r = Math.max(0, row - range); r < Math.min(BOARD_SIZE, row + range + 1); r++) {
for (int c = Math.max(0, col - range); c < Math.min(BOARD_SIZE, col + range + 1); c++) {
for (int d = 0; d < 4; d++) {
cachedScores[r][c][d] = getPatternScore(r, c, d);
}
}
}
}
6.4 Alpha-Beta剪枝算法
private int[] findBestMoveWithAlphaBeta(int depth) {
// ... (初始化) ...
List<Point> possibleMoves = findPossibleMoves();
for (Point p : possibleMoves) {
// ... (尝试移动) ...
int score = alphaBeta(depth - 1, alpha, beta, false);
// ... (撤销移动) ...
if (score > bestScore) {
bestScore = score;
bestRow = i;
bestCol = j;
alpha = Math.max(alpha, score);
if (beta <= alpha) { // Beta剪枝
break;
}
}
}
return new int[]{bestRow, bestCol};
}
6.5 悔棋逻辑
public void undoLastMove() {
if (GomokuGame.this.isPVPMode) {
if (!chessList.isEmpty()) {
Point lastPoint = chessList.remove(chessList.size() - 1);
board[lastPoint.y][lastPoint.x] = 0;
updateCachedScores(lastPoint.y, lastPoint.x);
isBlackTurn = !isBlackTurn;
GomokuGame.this.moveCount = Math.max(0, GomokuGame.this.moveCount - 1);
}
} else {
if (isBlackTurn && chessList.size() >= 2) {
Point aiPoint = chessList.remove(chessList.size() - 1);
board[aiPoint.y][aiPoint.x] = 0;
updateCachedScores(aiPoint.y, aiPoint.x);
Point humanPoint = chessList.remove(chessList.size() - 1);
board[humanPoint.y][humanPoint.x] = 0;
updateCachedScores(humanPoint.y, humanPoint.x);
GomokuGame.this.moveCount = Math.max(0, GomokuGame.this.moveCount - 2);
}
}
// ... (更新UI) ...
}
本项目代码结构清晰,注释详细,性能优化得当,是一个功能完整、易于理解和扩展的五子棋游戏实现。
更多推荐


所有评论(0)