这段 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() {
@Override
public 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 {
@Override
protected 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() {
@Override
public 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() {
@Override
public 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 {
@Override
protected 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() {
@Override
public void run() {
new ThreeDimensionalConwayGameOfLifeGUI();
}
});
}
}