基于JAVA的康威生命游戏二次开发
引言:
康威生命游戏(Conway's Game of Life)是一种基于细胞自动机的零玩家游戏,由数学家约翰·康威(John Conway)于1970年创建。这个游戏并不是传统意义上的游戏,而是一种模拟生命演变的规则系统。康威生命游戏的“宇宙”是一个由无限的二维网格组成的平面,每个格子被称为一个“细胞”。每个细胞可以处于两种状态:存活或死亡。这些细胞根据一组简单的规则演变。
规则如下:
- 活细胞周围有2或3个活细胞时,它在下一代保持活跃。
- 活细胞周围有少于2个活细胞时,它在下一代死亡(因为孤立)。
- 活细胞周围有超过3个活细胞时,它在下一代死亡(因为过度拥挤)。
- 死细胞周围有3个活细胞时,它在下一代复活。
这些简单的规则导致了复杂的模式和演变,有时候出现周期性、稳定的图案,有时候则呈现出随机性和混沌。康威生命游戏被广泛用于计算机科学和数学中,作为细胞自动机的经典示例,同时也因其简洁的规则而受到人们的喜爱。
2. 画布:LifeGame类的子类,继承自JPanel,负责根据计算结果为方格填色,以展示游戏的内容
3. 方格:在LifeGame类中以二维数组的形式存储,根据游戏规则
2. 部分注释错误
3. 原游戏中“细胞”的死亡方式过少,只有过度拥挤才会导致死亡
2. 修改了部分注释,使程序更易懂
3. 修改了游戏规则,添加了新的细胞状态(红色),当活细胞周围的细胞数大于等于5才会死亡,在细胞存活数为4时,它会杀死上下左右的细胞
4. 当细胞状态为红色,它会使四角方向的死细胞复活,活细胞死亡,而后自身变为普通存活状态


代码概览
LifeGame.java
//创建一个类,继承自JFrame,表示窗口
public class LifeGame extends JFrame {
//定义方格子世界的行数和列数
private static final int rows = 200;
private static final int cols = 200;
//定义方格子世界的二维数组
private int[][] world = new int[rows][cols];
//定义每个方格子的大小
private static final int cellSize = 4;
//定义窗口的宽度和高度
private static final int width = cols * cellSize;
private static final int height = rows * cellSize;
//创建一个构造方法,初始化窗口和方格子世界
public LifeGame() {
// 调用父类的构造方法,设置窗口的标题
super("生命游戏");
// 设置窗口的大小和位置
setSize(width, height);
setLocationRelativeTo(null);
// 设置窗口关闭时退出程序
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗口不可调整大小
setResizable(false);
// 初始化方格子世界,随机给每个细胞赋值0或1
Random random = new Random();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
world[i][j] = random.nextInt(2);
}
}
// 创建一个画布对象,用来绘制方格子世界
Canvas canvas = new Canvas();
// 将画布添加到窗口中,并使之可见
add(canvas);
setVisible(true);
// 创建一个定时器对象,用来定时更新方格子世界并重绘画布
Timer timer = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 每隔100毫秒,调用update方法更新方格子世界,并重绘画布
update();
canvas.repaint();
}
});
// 启动定时器
timer.start();
}
// 定义一个方法,根据当前状态更新下一时刻的状态
public void update() {
// 创建一个新的二维数组,用来存储下一时刻的状态
int[][] nextWorld = new int[rows][cols];
// 遍历每个细胞,根据规则计算下一时刻的状态
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// 获取当前细胞的状态和周围八个细胞的存活数
int state = world[i][j];
int liveNeighbors = countLiveNeighbors(i, j);
// 根据规则更新下一时刻的状态
if (state == 0 && liveNeighbors == 3) {
nextWorld[i][j] = 1;
} else if (state == 1 && (liveNeighbors == 2 || liveNeighbors == 3)) {
nextWorld[i][j] = 1;
} else {
nextWorld[i][j] = 0;
}
}
}
// 将新的二维数组赋值给原来的二维数组,完成更新
world = nextWorld;
}
// 定义一个方法,计算某个细胞周围八个细胞的存活数
public int countLiveNeighbors(int row, int col) {
// 定义一个变量,用来记录存活数
int liveCount = 0;
// 遍历周围八个细胞,如果是存活状态,就增加存活数
for (int i = row - 1; i <= row + 1; i++) {
for (int j = col - 1; j <= col + 1; j++) {
// 跳过自身和越界的情况
if (i == row && j == col)
continue;
if (i < 0 || i >= rows || j < 0 || j >= cols)
continue;
// 获取周围细胞的状态
int state = world[i][j];
// 如果是存活状态,就增加存活数
if (state == 1) {
liveCount++;
}
}
}
// 返回存活数
return liveCount;
}
// 创建一个内部类,继承自Jpanel,表示画布
class Canvas extends JPanel {
// 重写paint方法,在画布上绘制方格子世界的每个细胞
@Override
public void paint(Graphics g) {
super.paint(g);
// 遍历每个细胞,根据状态设置颜色,并填充矩形
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// 获取当前细胞的状态
int state = world[i][j];
// 根据状态设置颜色,死亡为白色,存活为黑色
if (state == 0) {
g.setColor(Color.WHITE);
} else {
g.setColor(Color.BLACK);
}
// 计算当前细胞在画布上的位置和大小,并填充矩形
int x = j * cellSize;
int y = i * cellSize;
g.fillRect(x, y, cellSize, cellSize);
}
}
// 在画布上画出方格子的边框线,颜色为灰色
g.setColor(Color.GRAY);
for (int i = 0; i <= rows; i++) {
int y = i * cellSize;
g.drawLine(0, y, width, y);
}
for (int j = 0; j <= cols; j++) {
int x = j * cellSize;
g.drawLine(x, 0, x, height);
}
}
}
}
LifeGame_main.java
public class LifeGame_main {
public static void main(String[] args) {
LifeGame t1=new LifeGame();
System.out.print("结束");
}
}
主要构成部分
1. 窗口:LifeGame类,继承自JFrame,负责展示游戏底层的方格字世界2. 画布:LifeGame类的子类,继承自JPanel,负责根据计算结果为方格填色,以展示游戏的内容
3. 方格:在LifeGame类中以二维数组的形式存储,根据游戏规则
游戏演示

源代码缺陷
1. 游戏更新时间过快,用户可能无法跟上方块的变化2. 部分注释错误
3. 原游戏中“细胞”的死亡方式过少,只有过度拥挤才会导致死亡
二次开发
1. 减缓了画布的更新时间2. 修改了部分注释,使程序更易懂
3. 修改了游戏规则,添加了新的细胞状态(红色),当活细胞周围的细胞数大于等于5才会死亡,在细胞存活数为4时,它会杀死上下左右的细胞
4. 当细胞状态为红色,它会使四角方向的死细胞复活,活细胞死亡,而后自身变为普通存活状态
LifeGame类中的update方法中的部分判断条件
// 根据规则更新下一时刻的状态
if (state == 0 && liveNeighbors == 3) {
nextWorld[i][j] = 1;
}
else if (state == 1 && (liveNeighbors == 2 || liveNeighbors == 3)) {
nextWorld[i][j] = 1;
}
else if (state == 1 && (liveNeighbors == 4 && i!=0 && i!=rows-1 && j!=0 && j!=cols-1)){
nextWorld[i][j] = 2;
nextWorld[i-1][j] = 0;
nextWorld[i+1][j] = 0;
nextWorld[i][j+1] = 0;
nextWorld[i][j-1] = 0;
}
else if(state == 2 && i!=0 && i!=rows-1 && j!=0 && j!=cols-1){
nextWorld[i][j] = 1;
if(world[i-1][j+1] == 0){
nextWorld[i-1][j+1] = 1;
} else nextWorld[i-1][j+1] = 0;
if(world[i-1][j-1] == 0){
nextWorld[i-1][j-1] = 1;
} else nextWorld[i-1][j-1] = 0;
if(world[i+1][j+1] == 0){
nextWorld[i+1][j+1] = 1;
} else nextWorld[i+1][j+1] = 0;
if(world[i+1][j-1] == 0){
nextWorld[i+1][j-1] = 1;
} else nextWorld[i+1][j-1] = 0;
}
else {
nextWorld[i][j] = 0;
}
二次开发后的结果
每一次生成的世界中,细胞都会因为内斗而快速死亡,只剩下小部分可以稳定存活(或稳定发生战争)的群落,大大缩短了细胞游戏的时间
二次开发后的不足
与原本的生命游戏一样,无法生成大型的细胞群落总结
在此次作业中,我了解到了生命游戏程序运行的逻辑,掌握了修改游戏逻辑的方法,使我能够更熟练的运用JAVA语言编写程序。通过这次作业,我锻炼了自己的创新能力,也认识到了我在软件开发与创新方面的不足之处,今后我将继续努力。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!