基于JAVA的康威生命游戏二次开发

引言:

       康威生命游戏(Conway's Game of Life)是一种基于细胞自动机的零玩家游戏,由数学家约翰·康威(John Conway)于1970年创建。这个游戏并不是传统意义上的游戏,而是一种模拟生命演变的规则系统。康威生命游戏的“宇宙”是一个由无限的二维网格组成的平面,每个格子被称为一个“细胞”。每个细胞可以处于两种状态:存活或死亡。这些细胞根据一组简单的规则演变。

规则如下:

  1. 活细胞周围有2或3个活细胞时,它在下一代保持活跃。
  2. 活细胞周围有少于2个活细胞时,它在下一代死亡(因为孤立)。
  3. 活细胞周围有超过3个活细胞时,它在下一代死亡(因为过度拥挤)。
  4. 死细胞周围有3个活细胞时,它在下一代复活。
       这些简单的规则导致了复杂的模式和演变,有时候出现周期性、稳定的图案,有时候则呈现出随机性和混沌。康威生命游戏被广泛用于计算机科学和数学中,作为细胞自动机的经典示例,同时也因其简洁的规则而受到人们的喜爱。

代码概览

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类中以二维数组的形式存储,根据游戏规则

游戏演示

![](https://img2024.cnblogs.com/blog/3397826/202403/3397826-20240305172342833-1513409917.png)

源代码缺陷

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;
				}

二次开发后的结果

每一次生成的世界中,细胞都会因为内斗而快速死亡,只剩下小部分可以稳定存活(或稳定发生战争)的群落,大大缩短了细胞游戏的时间
![](https://img2024.cnblogs.com/blog/3397826/202403/3397826-20240305171821608-1043935803.png)

二次开发后的不足

与原本的生命游戏一样,无法生成大型的细胞群落

总结

在此次作业中,我了解到了生命游戏程序运行的逻辑,掌握了修改游戏逻辑的方法,使我能够更熟练的运用JAVA语言编写程序。通过这次作业,我锻炼了自己的创新能力,也认识到了我在软件开发与创新方面的不足之处,今后我将继续努力。
![](https://img2024.cnblogs.com/blog/3397826/202403/3397826-20240305173432843-1330588788.png)
posted @   Fenqiii  阅读(112)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示