这段 Java 代码实现了一个三维版本的康威生命游戏(Conway's Game of Life)的图形用户界面(GUI)程序。康威生命游戏是一个零玩家游戏,它包括一个二维或多维的网格,每个网格中的细胞有存活或死亡两种状态,根据其周围细胞的存活情况按照一定规则进行迭代更新。此程序模拟了一个三维的细胞世界,并且通过 JFrame
和 JPanel
提供了可视化的界面,以一定的时间间隔展示细胞状态的演化。
类和成员变量说明
类定义
java
public class ThreeDimensionalConwayGameOfLifeGUI extends JFrame {
ThreeDimensionalConwayGameOfLifeGUI
类继承自JFrame
,这意味着它是一个窗口,用于承载游戏的可视化界面。
静态常量
java
private static final int SIZE_X = 20;
private static final int SIZE_Y = 20;
private static final int SIZE_Z = 20;
private static final int CELL_SIZE = 10;
private static final int DELAY = 500;
SIZE_X
、SIZE_Y
和SIZE_Z
:分别表示三维网格在 x、y、z 三个方向上的大小,即细胞世界的尺寸。CELL_SIZE
:每个细胞在界面上显示的大小(像素)。DELAY
:定时器的延迟时间(毫秒),控制细胞状态更新的时间间隔。
成员变量
java
private boolean[][][] currentGeneration;
private boolean[][][] nextGeneration;
private GamePanel gamePanel;
private Timer timer;
currentGeneration
:一个三维布尔数组,用于存储当前代细胞的存活状态。nextGeneration
:同样是三维布尔数组,用于存储下一代细胞的存活状态。gamePanel
:GamePanel
类的实例,用于绘制细胞的可视化界面。timer
:Timer
类的实例,用于定时触发细胞状态的更新和界面的重绘。
方法说明
构造函数 ThreeDimensionalConwayGameOfLifeGUI()
java
public ThreeDimensionalConwayGameOfLifeGUI() {currentGeneration = new boolean[SIZE_X][SIZE_Y][SIZE_Z];nextGeneration = new boolean[SIZE_X][SIZE_Y][SIZE_Z];initializeRandomly();gamePanel = new GamePanel();add(gamePanel);timer = new Timer(DELAY, new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {evolve();gamePanel.repaint();}});timer.start();setTitle("三维康威生命游戏");setSize(SIZE_X * CELL_SIZE, SIZE_Y * CELL_SIZE);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);setVisible(true);
}
- 初始化
currentGeneration
和nextGeneration
数组。 - 调用
initializeRandomly()
方法随机初始化当前代细胞的存活状态。 - 创建
GamePanel
实例并添加到窗口中。 - 创建一个
Timer
对象,设置延迟时间为DELAY
毫秒,每次触发时调用evolve()
方法更新细胞状态并调用gamePanel.repaint()
方法重绘界面。 - 设置窗口的标题、大小、关闭操作、位置并使其可见。
initializeRandomly()
方法
java
private void initializeRandomly() {Random random = new Random();for (int x = 0; x < SIZE_X; x++) {for (int y = 0; y < SIZE_Y; y++) {for (int z = 0; z < SIZE_Z; z++) {currentGeneration[x][y][z] = random.nextBoolean();}}}
}
- 使用
Random
类随机为currentGeneration
数组中的每个元素赋值(true
或false
),以此随机初始化细胞的存活状态。
countNeighbors(int x, int y, int z)
方法
java
private int countNeighbors(int x, int y, int z) {int count = 0;for (int dx = -1; dx <= 1; dx++) {for (int dy = -1; dy <= 1; dy++) {for (int dz = -1; dz <= 1; dz++) {if (dx == 0 && dy == 0 && dz == 0) {continue;}int newX = x + dx;int newY = y + dy;int newZ = z + dz;if (isValidCoordinate(newX, newY, newZ) && currentGeneration[newX][newY][newZ]) {count++;}}}}return count;
}
- 计算指定坐标
(x, y, z)
处细胞的存活邻居数量。 - 通过三层嵌套循环遍历该细胞周围的 26 个邻居(除去自身),调用
isValidCoordinate()
方法检查邻居坐标是否有效,若有效且邻居细胞存活则计数器加 1。
isValidCoordinate(int x, int y, int z)
方法
java
private boolean isValidCoordinate(int x, int y, int z) {return x >= 0 && x < SIZE_X && y >= 0 && y < SIZE_Y && z >= 0 && z < SIZE_Z;
}
- 检查给定的坐标
(x, y, z)
是否在三维网格的有效范围内。 - 如果坐标在范围内返回
true
,否则返回false
。
evolve()
方法
java
public void evolve() {for (int x = 0; x < SIZE_X; x++) {for (int y = 0; y < SIZE_Y; y++) {for (int z = 0; z < SIZE_Z; z++) {int neighbors = countNeighbors(x, y, z);if (currentGeneration[x][y][z]) {// 存活细胞规则nextGeneration[x][y][z] = neighbors == 3 || neighbors == 4 || neighbors == 5;} else {// 死亡细胞规则nextGeneration[x][y][z] = neighbors == 4;}}}}// 更新当前代for (int x = 0; x < SIZE_X; x++) {for (int y = 0; y < SIZE_Y; y++) {for (int z = 0; z < SIZE_Z; z++) {currentGeneration[x][y][z] = nextGeneration[x][y][z];}}}
}
- 进行细胞状态的更新,模拟一代的演化。
- 首先遍历整个三维网格,对于每个细胞,调用
countNeighbors()
方法计算其存活邻居数量。 - 根据存活邻居数量和当前细胞状态,按照规则更新
nextGeneration
数组:- 若当前细胞存活,当邻居数量为 3、4 或 5 时,下一代细胞存活,否则死亡。
- 若当前细胞死亡,当邻居数量为 4 时,下一代细胞存活,否则死亡。
- 最后将
nextGeneration
数组的值复制到currentGeneration
数组中,完成当前代的更新。
GamePanel
内部类
java
private class GamePanel extends JPanel {@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);for (int x = 0; x < SIZE_X; x++) {for (int y = 0; y < SIZE_Y; y++) {for (int z = 0; z < SIZE_Z; z++) {if (currentGeneration[x][y][z]) {g.setColor(Color.BLACK);} else {g.setColor(Color.WHITE);}g.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE);}}}}
}
GamePanel
类继承自JPanel
,用于绘制细胞的可视化界面。- 重写
paintComponent()
方法,遍历currentGeneration
数组,根据细胞的存活状态设置绘制颜色(存活为黑色,死亡为白色),并在界面上绘制相应的矩形。
main()
方法
java
public static void main(String[] args) {SwingUtilities.invokeLater(new Runnable() {@Overridepublic void run() {new ThreeDimensionalConwayGameOfLifeGUI();}});
}
- 使用
SwingUtilities.invokeLater()
方法确保在事件调度线程中创建和显示 GUI,避免线程安全问题。 - 创建
ThreeDimensionalConwayGameOfLifeGUI
类的实例,启动游戏。
完整代码
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;public class ThreeDimensionalConwayGameOfLifeGUI extends JFrame {private static final int SIZE_X = 20;private static final int SIZE_Y = 20;private static final int SIZE_Z = 20;private static final int CELL_SIZE = 10;private static final int DELAY = 500;private boolean[][][] currentGeneration;private boolean[][][] nextGeneration;private GamePanel gamePanel;private Timer timer;public ThreeDimensionalConwayGameOfLifeGUI() {currentGeneration = new boolean[SIZE_X][SIZE_Y][SIZE_Z];nextGeneration = new boolean[SIZE_X][SIZE_Y][SIZE_Z];initializeRandomly();gamePanel = new GamePanel();add(gamePanel);timer = new Timer(DELAY, new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {evolve();gamePanel.repaint();}});timer.start();setTitle("三维康威生命游戏");setSize(SIZE_X * CELL_SIZE, SIZE_Y * CELL_SIZE);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);setVisible(true);}private void initializeRandomly() {Random random = new Random();for (int x = 0; x < SIZE_X; x++) {for (int y = 0; y < SIZE_Y; y++) {for (int z = 0; z < SIZE_Z; z++) {currentGeneration[x][y][z] = random.nextBoolean();}}}}private int countNeighbors(int x, int y, int z) {int count = 0;for (int dx = -1; dx <= 1; dx++) {for (int dy = -1; dy <= 1; dy++) {for (int dz = -1; dz <= 1; dz++) {if (dx == 0 && dy == 0 && dz == 0) {continue;}int newX = x + dx;int newY = y + dy;int newZ = z + dz;if (isValidCoordinate(newX, newY, newZ) && currentGeneration[newX][newY][newZ]) {count++;}}}}return count;}private boolean isValidCoordinate(int x, int y, int z) {return x >= 0 && x < SIZE_X && y >= 0 && y < SIZE_Y && z >= 0 && z < SIZE_Z;}public void evolve() {for (int x = 0; x < SIZE_X; x++) {for (int y = 0; y < SIZE_Y; y++) {for (int z = 0; z < SIZE_Z; z++) {int neighbors = countNeighbors(x, y, z);if (currentGeneration[x][y][z]) {// 存活细胞规则nextGeneration[x][y][z] = neighbors == 3 || neighbors == 4 || neighbors == 5;} else {// 死亡细胞规则nextGeneration[x][y][z] = neighbors == 4;}}}}// 更新当前代for (int x = 0; x < SIZE_X; x++) {for (int y = 0; y < SIZE_Y; y++) {for (int z = 0; z < SIZE_Z; z++) {currentGeneration[x][y][z] = nextGeneration[x][y][z];}}}}private class GamePanel extends JPanel {@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);for (int x = 0; x < SIZE_X; x++) {for (int y = 0; y < SIZE_Y; y++) {for (int z = 0; z < SIZE_Z; z++) {if (currentGeneration[x][y][z]) {g.setColor(Color.BLACK);} else {g.setColor(Color.WHITE);}g.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE);}}}}}public static void main(String[] args) {SwingUtilities.invokeLater(new Runnable() {@Overridepublic void run() {new ThreeDimensionalConwayGameOfLifeGUI();}});}
}