设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间12 现在时间12 缓存数据 做人啊,最要紧的是开心 你饿不饿,我去给你煮碗面 其实我不想给你煮面我只是想见你一面

做人啊,最要紧的是开心 你饿不饿,我去给你煮碗面 其实我不想给你煮面我只是想见你一面 -- 问你是否跟我走

查看: 1239|回复: 1

使用Java实现生命游戏串行代码示例

[复制链接]

  离线 

TA的专栏

  • 打卡等级:即来则安
  • 打卡总天数:16
  • 打卡月天数:0
  • 打卡总奖励:276
  • 最近打卡:2024-09-24 11:09:05
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
49
主题
39
精华
0
金钱
420
积分
102
注册时间
2023-8-13
最后登录
2025-5-31

发表于 2024-10-29 01:26:53 | 显示全部楼层 |阅读模式
目录
  • 生命游戏介绍
  • 一、效果展示
    • 1.初始界面
    • 2.启动游戏
  • 二、代码实现
    • 三、代码解释
      • 1.常量设置
      • 2.图形化
      • 3.计算“生死”情况与统计邻居细胞数量
    • 四、结语

      生命游戏介绍

      生命游戏,是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。

      一个方格游戏棋盘上,每个方格中都可放置一个生命细胞,每个生命细胞只有两种状态:“生”或“死”(状态往往随机决定)。然后细胞根据某些规则,计算出下一代每个细胞的状态,并且不停迭代。

      在游戏的进行中,杂乱无序的细胞会逐渐演化出各种精致、有形的结构;这些结构往往有很好的对称性,而且每一代都在变化形状。一些形状已经锁定,不会逐代变化。有时,一些已经成形的结构会因为一些无序细胞的“入侵”而被破坏。但是形状和秩序经常能从杂乱中产生出来。

      现设定其规则是:

      • 如果一个细胞周围有3个细胞为生(一个细胞周围共有8个细胞),则该细胞为生(即该细胞若原先为死,则转为生,若原先为生,则保持不变) 。
      •  如果一个细胞周围有2个细胞为生,则该细胞的生死状态保持不变;
      •  在其它情况下,该细胞为死(即该细胞若原先为生,则转为死,若原先为死,则保持不变)

      下面就此规则,使用java来编写100*100的棋盘,并使用简单的JavaFX来实现简易图形化来观察游戏的迭代过程。

      一、效果展示

      1.初始界面

      100*100的棋盘上随机生成“生”和“死”细胞(黑为生,白为死)。底部有“运行”和“暂停”按钮。

      1.png

      2.启动游戏

      2.gif

      二、代码实现

      1. package com.itheima.gameOfLife;
      2. import javafx.animation.AnimationTimer;
      3. import javafx.application.Application;
      4. import javafx.scene.Scene;
      5. import javafx.scene.control.Button;
      6. import javafx.scene.layout.BorderPane;
      7. import javafx.scene.layout.Pane;
      8. import javafx.scene.paint.Color;
      9. import javafx.scene.shape.Rectangle;
      10. import javafx.stage.Stage;
      11. import java.util.Random;
      12. public class GameOfLife extends Application {
      13. private static final int GRID_SIZE = 100;
      14. private static final int CELL_SIZE = 10; // 每个细胞的像素大小
      15. private static final int GENERATIONS = 1000; // 演化代数
      16. private int[][] grid = new int[GRID_SIZE][GRID_SIZE]; // 当前代棋盘
      17. private int[][] nextGrid = new int[GRID_SIZE][GRID_SIZE]; // 下一代棋盘
      18. private Pane pane = new Pane();
      19. private AnimationTimer timer;
      20. private boolean isRunning = false; // 运行状态标志
      21. public static void main(String[] args) {
      22. launch(args);
      23. }
      24. @Override
      25. public void start(Stage primaryStage) {
      26. initializeGrid(); // 随机初始化棋盘
      27. // 创建JavaFX界面
      28. BorderPane root = new BorderPane();
      29. Scene scene = new Scene(root, GRID_SIZE * CELL_SIZE, GRID_SIZE * CELL_SIZE + 50);
      30. primaryStage.setTitle("生命游戏");
      31. primaryStage.setScene(scene);
      32. // 创建按钮,便于停止观察当前棋盘状态
      33. Button startButton = new Button("运行");
      34. Button pauseButton = new Button("暂停");
      35. startButton.setOnAction(e -> startGame());
      36. pauseButton.setOnAction(e -> pauseGame());
      37. // 设置按钮位置
      38. root.setBottom(new Pane(startButton, pauseButton));
      39. Pane buttonPane = new Pane();
      40. buttonPane.getChildren().addAll(startButton, pauseButton);
      41. buttonPane.setPrefSize(GRID_SIZE * CELL_SIZE, 50);
      42. buttonPane.setLayoutY(GRID_SIZE * CELL_SIZE);
      43. startButton.setLayoutX(20);
      44. pauseButton.setLayoutX(80);
      45. root.setCenter(pane);
      46. root.setBottom(buttonPane);
      47. primaryStage.show();
      48. drawGrid(); // 绘制初始棋盘
      49. // 使用AnimationTimer更新棋盘
      50. timer = new AnimationTimer() {
      51. private int generationCount = 0;
      52. @Override
      53. public void handle(long now) {
      54. if (isRunning && generationCount < GENERATIONS) {
      55. runGeneration(); // 运行一代
      56. drawGrid(); // 更新绘制
      57. generationCount++;
      58. } else if (generationCount >= GENERATIONS) {
      59. stop(); // 结束动画
      60. }
      61. }
      62. };
      63. }
      64. // 随机初始化棋盘
      65. private void initializeGrid() {
      66. Random random = new Random();
      67. for (int i = 0; i < GRID_SIZE; i++) {
      68. for (int j = 0; j < GRID_SIZE; j++) {
      69. grid[i][j] = random.nextInt(2); // 随机生成0或1
      70. }
      71. }
      72. }
      73. // 启动
      74. private void startGame() {
      75. if (!isRunning) {
      76. isRunning = true; // 设置为运行状态
      77. timer.start(); // 启动计时器
      78. }
      79. }
      80. // 暂停
      81. private void pauseGame() {
      82. isRunning = false; // 设置为暂停状态
      83. timer.stop(); // 停止计时器
      84. }
      85. // 运行一代
      86. private void runGeneration() {
      87. for (int i = 0; i < GRID_SIZE; i++) {
      88. for (int j = 0; j < GRID_SIZE; j++) {
      89. int liveNeighbors = countLiveNeighbors(i, j);
      90. if (grid[i][j] == 1) { // 当前细胞是活的
      91. nextGrid[i][j] = (liveNeighbors == 2 || liveNeighbors == 3) ? 1 : 0;
      92. } else { // 当前细胞是死的
      93. nextGrid[i][j] = (liveNeighbors == 3) ? 1 : 0;
      94. }
      95. }
      96. }
      97. copyNextGridToCurrent();
      98. }
      99. // 计算邻居活细胞数量
      100. private int countLiveNeighbors(int row, int col) {
      101. int liveNeighbors = 0;
      102. for (int i = -1; i <= 1; i++) {
      103. for (int j = -1; j <= 1; j++) {
      104. if (i == 0 && j == 0) continue; // 跳过自身
      105. int newRow = (row + i + GRID_SIZE) % GRID_SIZE; // 考虑边界
      106. int newCol = (col + j + GRID_SIZE) % GRID_SIZE;
      107. liveNeighbors += grid[newRow][newCol];
      108. }
      109. }
      110. return liveNeighbors;
      111. }
      112. // 将nextGrid复制到grid
      113. private void copyNextGridToCurrent() {
      114. for (int i = 0; i < GRID_SIZE; i++) {
      115. System.arraycopy(nextGrid[i], 0, grid[i], 0, GRID_SIZE);
      116. }
      117. }
      118. // 绘制当前棋盘状态
      119. private void drawGrid() {
      120. pane.getChildren().clear(); // 清除旧的图形
      121. for (int i = 0; i < GRID_SIZE; i++) {
      122. for (int j = 0; j < GRID_SIZE; j++) {
      123. Rectangle cell = new Rectangle(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE);
      124. cell.setFill(grid[i][j] == 1 ? Color.BLACK : Color.WHITE); // 黑色表示活细胞,白色表示死细胞
      125. cell.setStroke(Color.GRAY); //细胞之间的边框
      126. pane.getChildren().add(cell); // 将细胞添加到面板
      127. }
      128. }
      129. }
      130. }
      复制代码

      三、代码解释

      1.常量设置

      1. private static final int GRID_SIZE = 100;
      2. private static final int CELL_SIZE = 10; // 每个细胞的像素大小
      3. private static final int GENERATIONS = 1000; // 演化代数
      4. private int[][] grid = new int[GRID_SIZE][GRID_SIZE]; // 当前代棋盘
      5. private int[][] nextGrid = new int[GRID_SIZE][GRID_SIZE]; // 下一代棋盘
      6. private Pane pane = new Pane();
      7. private AnimationTimer timer;
      8. private boolean isRunning = false; // 运行状态标志
      复制代码

      GRID_SIZE: 定义了棋盘的大小,当前设置为 

      1. 100
      复制代码
      。即棋盘是一个 
      1. 100 x 100
      复制代码
       的格子。

      CELL_SIZE: 定义了每个细胞的像素大小,当前设置为 

      1. 10
      复制代码
      。因此,每个细胞在界面上将显示为一个 
      1. 10 x 10
      复制代码
       像素的正方形。

      棋盘总大小: 因此,整个棋盘的实际像素大小为:

      • 宽度: 
        1. GRID_SIZE * CELL_SIZE = 100 * 10 = 1000
        复制代码
         像素
      • 高度: 
        1. GRID_SIZE * CELL_SIZE = 100 * 10 = 1000
        复制代码
         像素

      2.图形化

      1. // 创建JavaFX界面
      2. BorderPane root = new BorderPane();
      3. Scene scene = new Scene(root, GRID_SIZE * CELL_SIZE, GRID_SIZE * CELL_SIZE + 50);
      4. primaryStage.setTitle("生命游戏");
      5. primaryStage.setScene(scene);
      6. // 创建按钮
      7. Button startButton = new Button("运行");
      8. Button pauseButton = new Button("暂停");
      9. startButton.setOnAction(e -> startGame());
      10. pauseButton.setOnAction(e -> pauseGame());
      11. // 将按钮放置在界面底部
      12. root.setBottom(new Pane(startButton, pauseButton));
      13. Pane buttonPane = new Pane();
      14. buttonPane.getChildren().addAll(startButton, pauseButton);
      15. buttonPane.setPrefSize(GRID_SIZE * CELL_SIZE, 50);
      16. buttonPane.setLayoutY(GRID_SIZE * CELL_SIZE);
      17. startButton.setLayoutX(20);
      18. pauseButton.setLayoutX(80);
      19. root.setCenter(pane);
      20. root.setBottom(buttonPane);
      21. primaryStage.show();
      22. drawGrid(); // 绘制初始棋盘
      23. // 使用AnimationTimer更新棋盘
      24. timer = new AnimationTimer() {
      25. private int generationCount = 0;
      26. @Override
      27. public void handle(long now) {
      28. if (isRunning && generationCount < GENERATIONS) {
      29. runGeneration(); // 运行一代
      30. drawGrid(); // 更新绘制
      31. generationCount++;
      32. } else if (generationCount >= GENERATIONS) {
      33. stop(); // 结束动画
      34. }
      35. }
      36. };
      37. }
      复制代码

      上面这段代码是JavaFX的核心部分,创建棋盘界面和处理游戏逻辑。部分解释已经在代码中注释出来。

      在“使用AnimationTimer更新棋盘”这部分中,创建了一个 

      1. AnimationTimer
      复制代码
       对象,并重写其handle方法,用于定时更新棋盘状态。

      3.计算“生死”情况与统计邻居细胞数量

      1. //根据规则判断生死
      2. private void runGeneration() {
      3. for (int i = 0; i < GRID_SIZE; i++) {
      4. for (int j = 0; j < GRID_SIZE; j++) {
      5. int liveNeighbors = countLiveNeighbors(i, j);
      6. if (grid[i][j] == 1) { // 当前细胞是活的
      7. nextGrid[i][j] = (liveNeighbors == 2 || liveNeighbors == 3) ? 1 : 0;
      8. } else { // 当前细胞是死的
      9. nextGrid[i][j] = (liveNeighbors == 3) ? 1 : 0;
      10. }
      11. }
      12. }
      13. copyNextGridToCurrent();
      14. }
      15. // 计算邻居活细胞数量
      16. private int countLiveNeighbors(int row, int col) {
      17. int liveNeighbors = 0;
      18. for (int i = -1; i <= 1; i++) {
      19. for (int j = -1; j <= 1; j++) {
      20. if (i == 0 && j == 0) continue; // 跳过自身
      21. int newRow = (row + i + GRID_SIZE) % GRID_SIZE; // 考虑边界
      22. int newCol = (col + j + GRID_SIZE) % GRID_SIZE;
      23. liveNeighbors += grid[newRow][newCol];
      24. }
      25. }
      26. return liveNeighbors;
      27. }
      复制代码

      比较简单的代码,使用最基本的双重循环来遍历整个棋盘的细胞,得到其邻居的数量用于判断下一次迭代的状态。

      在“计算邻居活细胞数量”中,用取模运算来处理边界情况,使得棋盘具有环绕效果。例如,如果当前细胞在第一行,且要检查上方的细胞,则通过取模确保索引循环回到棋盘的底部。

      四、结语

      以上主要浅显的实现了生命游戏的基本逻辑,并用简单的图形可视化来创建一个直观的界面来观察细胞的迭代,更直接的观察到由简单规则产生的复杂动态行为。在这个串行的生命游戏基础上,后续可以改写为多线程的生命游戏,并通过一些方法来比对串行与并行代码的效率。

      到此这篇关于使用Java实现生命游戏串行的文章就介绍到这了,更多相关Java生命游戏串行代码内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!


      免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
      晓枫资讯-科技资讯社区-免责声明
      免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
            1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
            2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
            3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
            4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
            5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
      http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

        离线 

      TA的专栏

      等级头衔

      等級:晓枫资讯-列兵

      在线时间
      0 小时

      积分成就
      威望
      0
      贡献
      0
      主题
      0
      精华
      0
      金钱
      20
      积分
      20
      注册时间
      2022-12-25
      最后登录
      2022-12-25

      发表于 昨天 10:28 | 显示全部楼层
      路过,支持一下
      http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
      严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
      您需要登录后才可以回帖 登录 | 立即注册

      本版积分规则

      1楼
      2楼

      手机版|晓枫资讯--科技资讯社区 本站已运行

      CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

      晓枫资讯--科技资讯社区

      本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

      如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

      Powered by Discuz! X3.5

      快速回复 返回顶部 返回列表