前言
欢迎阅读本文,本文将介绍如何使用Java语言实现一个简易的五子棋游戏。五子棋,作为一种经典的棋类游戏,不仅简单易学,而且富有策略性,深受广大玩家喜爱。通过本文,读者将了解到如何利用Java编程语言,结合基本的图形用户界面(GUI)技术,实现一个基本的五子棋游戏程序。
本文内容分为几个部分。首先,我们将简要介绍五子棋的规则和基本玩法,以便读者对游戏有一个清晰的认识。接着,我们将详细讨论如何利用Java的面向对象编程思想,设计游戏所需的关键组件和功能模块,包括棋盘的表示、玩家交互、胜负判断等。随后,我们将通过代码示例逐步展示如何实现这些功能,包括如何处理用户输入、如何绘制游戏界面等。
本文假设读者已具备一定的Java编程基础,对面向对象编程有一定的了解。如果您是初学者,建议先熟悉Java语言的基本语法和面向对象的基本概念。如果您已经具备相关知识,那么通过本文的学习,您将能够进一步提升自己的编程能力,并且亲手实现一个完整的五子棋游戏程序。
希望本文能够帮助读者更好地理解Java编程在游戏开发中的应用,同时也能够为对五子棋感兴趣的朋友提供一个有趣的学习和实践机会。祝愿大家阅读愉快,游戏编程乐趣无穷!
整体架构流程
-
主窗口设置及初始化
GomokuGUI
类继承自JFrame
,用于创建游戏窗口。- 初始化棋盘大小、格子大小等参数,并创建棋盘二维数组
board
用于存储棋盘状态,以及currentPlayer
用于标识当前玩家。
-
棋盘绘制
BoardPanel
内部类继承自JPanel
,重写paintComponent
方法实现棋盘的绘制。- 绘制棋盘网格和棋子,根据
board
数组的状态绘制黑白棋子。
-
鼠标事件处理
- 在
GomokuGUI
构造函数中,为BoardPanel
添加了鼠标点击事件监听器。 - 当玩家点击空白处时,检查移动是否有效,若有效则在
board
数组中放置当前玩家的棋子,并检查是否获胜或切换玩家。
- 在
-
游戏逻辑实现
isValidMove
方法检查是否可以在指定位置放置棋子。placeStone
方法放置棋子。switchPlayer
方法切换当前玩家。checkWin
方法检查当前玩家是否获胜,通过checkDirection
方法实现四个方向的连续棋子检查。resetGame
方法重置游戏状态,清空棋盘并重新设置当前玩家为黑方。
-
主程序入口
main
方法使用SwingUtilities.invokeLater
来确保在事件分派线程(EDT)中创建和显示游戏窗口,以保证线程安全性。
代码展示
设置棋盘
private static final int SIZE = 15; // 棋盘大小
private static final int CELL_SIZE = 40; // 每个单元格的像素大小
private static final int BOARD_SIZE = SIZE * CELL_SIZE; // 棋盘的像素大小
private static final int SIZE = 15; // 棋盘大小
private static final int CELL_SIZE = 40; // 每个单元格的像素大小
private static final int BOARD_SIZE = SIZE * CELL_SIZE; // 棋盘的像素大小
private static final char EMPTY = '.'; // 空白单元格
private static final char BLACK = 'X'; // 黑方棋子
private static final char WHITE = 'O'; // 白方棋子
private char[][] board = new char[SIZE][SIZE]; // 游戏棋盘
private char currentPlayer = BLACK; // 当前玩家
private boolean gameStarted = false; // 游戏状态
棋盘面板
setTitle("五子棋");
setSize(BOARD_SIZE, BOARD_SIZE + 50); // 为按钮留出额外空间
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null); // 窗口居中显示
initializeBoard(); // 初始化棋盘
// 棋盘面板
BoardPanel boardPanel = new BoardPanel();
boardPanel.setPreferredSize(new Dimension(BOARD_SIZE, BOARD_SIZE));
boardPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (gameStarted) { // 只有在游戏开始后才响应鼠标点击事件
int col = e.getX() / CELL_SIZE; // 计算点击的列
int row = e.getY() / CELL_SIZE; // 计算点击的行
if (isValidMove(row, col)) { // 检查点击位置是否有效
placeStone(row, col); // 放置棋子
if (checkWin(row, col)) { // 检查是否胜利
JOptionPane.showMessageDialog(null, "玩家 " + (currentPlayer == BLACK ? "黑方" : "白方") + " 获胜!");
gameStarted = false; // 游戏结束
} else {
switchPlayer(); // 切换玩家
}
boardPanel.repaint(); // 重新绘制棋盘
}
}
}
});
功能设计
// 开始游戏按钮
JButton startButton = new JButton("开始游戏");
startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
gameStarted = true; // 标记游戏开始
initializeBoard(); // 初始化棋盘
currentPlayer = BLACK; // 设置当前玩家为黑方
boardPanel.repaint(); // 重新绘制棋盘
}
});
// 重新开始按钮
JButton resetButton = new JButton("重新开始");
resetButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
gameStarted = false; // 标记游戏未开始
initializeBoard(); // 初始化棋盘
currentPlayer = BLACK; // 设置当前玩家为黑方
boardPanel.repaint(); // 重新绘制棋盘
}
});
// 控制面板,包含按钮
JPanel controlPanel = new JPanel();
controlPanel.add(startButton);
controlPanel.add(resetButton);
// 设置布局
setLayout(new BorderLayout());
add(boardPanel, BorderLayout.CENTER); // 添加棋盘面板到中间
add(controlPanel, BorderLayout.SOUTH); // 添加控制面板到南部
}
// 初始化棋盘为空白
private void initializeBoard() {
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
board[i][j] = EMPTY;
}
}
}
// 检查移动是否有效
private boolean isValidMove(int row, int col) {
return row >= 0 && row < SIZE && col >= 0 && col < SIZE && board[row][col] == EMPTY;
}
// 在棋盘上放置棋子
private void placeStone(int row, int col) {
board[row][col] = currentPlayer;
}
// 切换玩家
private void switchPlayer() {
currentPlayer = (currentPlayer == BLACK) ? WHITE : BLACK;
}
// 检查当前玩家是否获胜
private boolean checkWin(int row, int col) {
return checkDirection(row, col, 1, 0) || // 水平检查
checkDirection(row, col, 0, 1) || // 垂直检查
checkDirection(row, col, 1, 1) || // 斜向检查 \
checkDirection(row, col, 1, -1); // 斜向检查 /
}
// 检查特定方向是否有连续的五个棋子
private boolean checkDirection(int row, int col, int dRow, int dCol) {
int count = 1;
int r = row + dRow;
int c = col + dCol;
while (r >= 0 && r < SIZE && c >= 0 && c < SIZE && board[r][c] == currentPlayer) {
count++;
r += dRow;
c += dCol;
}
r = row - dRow;
c = col - dCol;
while (r >= 0 && r < SIZE && c >= 0 && c < SIZE && board[r][c] == currentPlayer) {
count++;
r -= dRow;
c -= dCol;
}
return count >= 5;
}
绘制棋盘
private class BoardPanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 绘制网格
for (int i = 0; i <= SIZE; i++) {
g.drawLine(i * CELL_SIZE, 0, i * CELL_SIZE, BOARD_SIZE);
g.drawLine(0, i * CELL_SIZE, BOARD_SIZE, i * CELL_SIZE);
}
// 绘制棋子
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (board[i][j] == BLACK) {
g.setColor(Color.BLACK);
g.fillOval(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE);
} else if (board[i][j] == WHITE) {
g.setColor(Color.WHITE);
g.fillOval(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE);
g.setColor(Color.BLACK);
g.drawOval(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE);
}
}
}
}
}
项目运行
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
GomokuGUI game = new GomokuGUI();
game.setVisible(true);
});
}
小结
通过面向对象的方法,合理分割代码为多个类,并使用事件驱动的编程方式实现了用户与游戏界面的交互。游戏逻辑部分通过简单的判断和数组操作实现了基本的规则和胜负判定,展示了一个完整的桌面应用程序的基本架构。