当前位置: 首页 > news >正文

项目历程—生命数组游戏(两版本)

实现效果

(一)版本1:

(二)版本2:

代码实现:

(一)版本一:

(一)创建AI方法类:

内含方法
1.显现数组
2.初始化数组
3.更新数组
4.计算此处是否可存活
5.备份上一次数组
6.判断这一次数组和上一次数组是否相同

5和6方法是为了检测生命数组是否停止更新用的

package DemoProject.fjm0729_V1;import java.util.Random;public class AILife {static  int g=1;public  static void showUpdate(int [][] LifeArr){upDate(LifeArr);//输出更迭后的数组System.out.println("更新过"+ g++ + "次的数组生命数组为:");for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){System.out.print(LifeArr[i][j] + "  ");if ( j == LifeArr[i].length-1 ){System.out.println();}}}}public static void randomInit(int [][] LifeArr){Random random = new Random();for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){int randomValue = random.nextBoolean() ? 0 : 1;LifeArr[i][j] = randomValue;}}}public static  void upDate(int [][] LifeArr){int [][] CalIsAliveArr = CalSurroundAlive(LifeArr);for( int i = 0 ; i < CalIsAliveArr.length ; i++){for ( int j = 0 ; j < CalIsAliveArr[i].length ; j ++){//条件3if(LifeArr[i][j] == 0){if(CalIsAliveArr[i][j] == 3 ){LifeArr[i][j] = 1;}}else if(LifeArr[i][j] == 1){//条件2if(CalIsAliveArr[i][j] == 3 || CalIsAliveArr[i][j] == 2){LifeArr[i][j] = 1;//条件1}else if(CalIsAliveArr[i][j] > 3 || CalIsAliveArr[i][j] < 2){LifeArr[i][j] = 0;}}}}}public  static int [][] CalSurroundAlive(int [][] LifeArr){int [][] CalIsAliveArr = new int[LifeArr.length][LifeArr[0].length];for( int i = 0 ; i < LifeArr.length ; i ++ ){// i为行 j为列for ( int j = 0 ; j < LifeArr[i].length ;  j ++ ){//判断该点是否活着://如果上方有东西,则向上遍历,如此推广到四个方向int count = 0;if( i - 1 >= 0){if(LifeArr[i-1][j] == 1){count++;}}if( i + 1 < LifeArr.length ){if(LifeArr[i+1][j] == 1){count++;}}if( j + 1 < LifeArr[i].length){if(LifeArr[i][j+1] == 1){count++;}}if( j - 1 >= 0){if(LifeArr[i][j-1] == 1){count++;}}CalIsAliveArr[i][j] = count;}}return CalIsAliveArr;}//备份上一次数组public static int [][] backUpArr(int [][] LifeArr){int [][] Arr = new int[LifeArr.length][LifeArr[0].length];for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){Arr[i][j] = LifeArr[i][j];}}return Arr;}//判断数组元素是否相同public boolean JudgeSame(int [][] backUpArr , int [][] LifeArr){for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){if(backUpArr[i][j]  !=  LifeArr[i][j] ){return false;}}}return true;}}

(二)创建主界面类:

package DemoProject.fjm0729_V1;import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Scanner;public class GameUI extends JFrame {int [][] LifeArr = null;int n = 0;public void showUI(){System.out.println("欢迎来到生命数组游戏!");Scanner scanner=new Scanner(System.in);System.out.print("请输入生命数组的行数:");int row=scanner.nextInt();System.out.print("请输入生命数组的列数:");int col=scanner.nextInt();System.out.println("输入成功!等待生命数组加载.....");LifeArr=new int[row][col];AILife.randomInit(LifeArr);System.out.println("生命数组初始化....");for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){System.out.print(LifeArr[i][j] + "  ");if ( j == LifeArr[i].length-1 ){System.out.println();}}}setTitle("生命游戏");setSize(900,900);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);setVisible(true);while (true){try {Thread.sleep(400);} catch (InterruptedException e) {throw new RuntimeException(e);}repaint();}}public void paint(Graphics g){BufferedImage bfi = new BufferedImage(900,820,BufferedImage.TYPE_4BYTE_ABGR);Graphics graphics = bfi.getGraphics();graphics.setColor(Color.WHITE);graphics.fillRect(0,0,900,820);AILife.showUpdate(LifeArr);graphics.setColor(Color.BLACK);//绘制更迭图像(1次)for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){if(LifeArr[i][j] ==1 ){graphics.fillRect(  i*9, 40+j*8,9,8);}}}System.out.println("重绘了" + ++n + "次");g.drawImage(bfi,0,0,null);}public static void main(String[] args) {new GameUI().showUI();}
}

注意:
1.不要使用for循环来重绘,因为只有最后一次循环里,paint()方法才会被执行。这涉及到repaint的异步机制,不会立即进入paint()方法中
2.Buffered.TYPE_4BYTE_ABGR为透明背景,因此需要每一次绘制,都需要先画一个与窗口齐宽高的白色面板,覆盖掉先前痕迹

(二)版本二:

(一)创建AI方法类:

package DemoProject.fjm0729_V2;import java.util.Random;public class AILife {static  int g=1;public  static void showUpdate(int [][] LifeArr){upDate(LifeArr);//输出更迭后的数组System.out.println("更新过"+ g++ + "次的数组生命数组为:");for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){System.out.print(LifeArr[i][j] + "  ");if ( j == LifeArr[i].length-1 ){System.out.println();}}}}public static void randomInit(int [][] LifeArr){Random random = new Random();for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){int randomValue = random.nextBoolean() ? 0 : 1;LifeArr[i][j] = randomValue;}}}public static  void upDate(int [][] LifeArr){int [][] CalIsAliveArr = CalSurroundAlive(LifeArr);for( int i = 0 ; i < CalIsAliveArr.length ; i++){for ( int j = 0 ; j < CalIsAliveArr[i].length ; j ++){//条件3if(LifeArr[i][j] == 0){if(CalIsAliveArr[i][j] == 3 ){LifeArr[i][j] = 1;}}else if(LifeArr[i][j] == 1){//条件2if(CalIsAliveArr[i][j] == 3 || CalIsAliveArr[i][j] == 2){LifeArr[i][j] = 1;//条件1}else if(CalIsAliveArr[i][j] > 3 || CalIsAliveArr[i][j] < 2){LifeArr[i][j] = 0;}}}}}public  static int [][] CalSurroundAlive(int [][] LifeArr){int [][] CalIsAliveArr = new int[LifeArr.length][LifeArr[0].length];for( int i = 0 ; i < LifeArr.length ; i ++ ){// i为行 j为列for ( int j = 0 ; j < LifeArr[i].length ;  j ++ ){//判断该点是否活着://如果上方有东西,则向上遍历,如此推广到四个方向int count = 0;if( i - 1 >= 0){if(LifeArr[i-1][j] == 1){count++;}}if( i + 1 < LifeArr.length ){if(LifeArr[i+1][j] == 1){count++;}}if( j + 1 < LifeArr[i].length){if(LifeArr[i][j+1] == 1){count++;}}if( j - 1 >= 0){if(LifeArr[i][j-1] == 1){count++;}}CalIsAliveArr[i][j] = count;}}return CalIsAliveArr;}//备份上一次数组public static int [][] backUpArr(int [][] LifeArr){int [][] Arr = new int[LifeArr.length][LifeArr[0].length];for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){Arr[i][j] = LifeArr[i][j];}}return Arr;}//判断数组元素是否相同public boolean JudgeSame(int [][] backUpArr , int [][] LifeArr){for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){if(backUpArr[i][j]  !=  LifeArr[i][j] ){return false;}}}return true;}}

(二)创建监听器类:一方面是鼠标监听器,一方面是键盘监听器

package DemoProject.fjm0729_V2;import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;public class EleListener implements MouseListener, KeyListener {GameUI gameUI;public EleListener( GameUI gameUI){this.gameUI=gameUI;}@Overridepublic void mouseClicked(MouseEvent e) {}@Overridepublic void mousePressed(MouseEvent e) {System.out.println("鼠标可监听");int x = e.getX();//决定的是第几列int y = e.getY();//决定的是第几行int row = (y - 20) / 8;         //决定第几行int col = x / 9;         //决定第几列System.out.println("这是第" + row + "行第" + col + "列");gameUI.LifeArr[row][col] = 1;}@Overridepublic void mouseReleased(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {int Key = e.getKeyCode();switch (Key){case KeyEvent.VK_SPACE:System.out.println("键盘被点击");gameUI.state = 1;}}@Overridepublic void keyReleased(KeyEvent e) {}
}

总结:
1.通过鼠标监听器,监听鼠标位置,将鼠标位置转换成其落在数组内的位置。将此空赋值为1
2.通过键盘监听器,控制运行状态,一开始向数组内赋值,后续使用键盘控制数组的开启
(三)创建主界面

package DemoProject.fjm0729_V2;import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Scanner;public class GameUI extends JFrame {int [][] LifeArr = null;int n = 0;int state = 0;int ImageX = 900;int ImageY = 820;public void showUI(){EleListener el = new EleListener(this);System.out.println("欢迎来到生命数组游戏!");Scanner scanner=new Scanner(System.in);System.out.print("请输入生命数组的行数:");int row=scanner.nextInt();System.out.print("请输入生命数组的列数:");int col=scanner.nextInt();System.out.println("输入成功!等待生命数组加载.....");LifeArr=new int[row][col];System.out.println("生命数组初始化....");setTitle("生命游戏");setSize(900,900);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);addKeyListener(el);addMouseListener(el);setVisible(true);while (true){if(state == 1){System.out.println("本代码被执行");}else if(state == 0){System.out.println("值未被改变");}try {Thread.sleep(400);} catch (InterruptedException e) {throw new RuntimeException(e);}repaint();}}public void paint(Graphics g){if(state == 1){System.out.println("传进来了" + CalAllEle(LifeArr) + "值");if(JudgeHave(LifeArr)){System.out.println("LifeArr被传进来值了");}BufferedImage bfi = new BufferedImage(ImageX,ImageY,BufferedImage.TYPE_4BYTE_ABGR);Graphics graphics = bfi.getGraphics();graphics.setColor(Color.WHITE);graphics.fillRect(0,0,ImageX,ImageY);AILife.showUpdate(LifeArr);graphics.setColor(Color.BLACK);//绘制更迭图像(1次)for(int i = 0 ; i < LifeArr.length ; i++){for(int j = 0 ; j < LifeArr[i].length ; j ++){if(LifeArr[i][j] ==1 ){graphics.fillRect(  i*9, 20+j*8,9,8);}}}System.out.println("重绘了" + ++n + "次");g.drawImage(bfi,0,0,null);}}public boolean JudgeHave(int [][] LifeArr){for (int i = 0 ; i < LifeArr.length ; i++){for( int j = 0 ; j < LifeArr[0].length ; j ++){if(LifeArr[i][j] == 1){return true;}}}return false;}public int CalAllEle(int [][] LiffeArr){int count = 0;for (int i = 0 ; i < LifeArr.length ; i ++){for ( int j = 0 ; j < LifeArr[0].length ; j ++){if(LifeArr[i][j] == 1){count++;}}}return count;}public static void main(String[] args) {new GameUI().showUI();}
}

删改处:将面板的坐标及大小转换成一个变量
增加处:添加监听器,并在循环中加入**Thread.sleep()**方法,不仅仅是为了减缓重绘速度,更是为了使EDT(事件调度线程)不要过于堵塞,确保其能及时监听到鼠标事件。
(个人提议)
手动初始化数组,很累。因为有10000个空位,填充起来需要点好多次鼠标,并且更迭起来又会淘汰掉一大批零散的空位

http://www.lryc.cn/news/603541.html

相关文章:

  • Unity 编辑器开发 之 Excel导表工具
  • 游戏盾从哪些方面保护网站业务?
  • c语言-数据结构-二叉树OJ之子树与二叉树的构建
  • QT项目 -仿QQ音乐的音乐播放器(第三节)
  • 电脑没有声音了怎么恢复 快速解决音频故障
  • 预装Windows 11系统的新电脑怎么跳过联网验机
  • Wndows Docker Desktop-Unexpected WSL error
  • Docker初学者需要了解的几个知识点(三)
  • docker 重新安裝
  • 小杰数据结构(one day)——心若安,便是晴天;心若乱,便是阴天。
  • 数据结构 排序(2)---选择排序
  • RK3568下的进程间广播通信:用C语言构建简单的中心服务器
  • 【WRF工具】服务器中安装编译GrADS
  • 信创国产Linux操作系统汇总:从桌面到服务器,百花齐放
  • 聚铭安全管家平台2.0实战解码 | 安服篇(三):配置保障 自动核查
  • mapbox进阶,mapbox-gl-draw绘图插件扩展,编辑模式支持点、线、面的捕捉
  • Android系统开发 在Android10版本的Framework中添加系统服务
  • Kafka——Kafka控制器
  • Note3: CNN(卷积神经网络)
  • 八股训练营 40 天心得:一场结束,也是一场新的开始
  • OpenCV 学习探秘之四:从角点检测,SIFT/SURF/ORB特征提取,目标检测与识别,Haar级联分类人脸检测,再到机器学习等接口的全面实战应用与解析
  • 【第四章:大模型(LLM)】01.神经网络中的 NLP-(3)文本情感分类实战
  • 嵌入式中间件-uorb解析
  • 基于深度学习的医学图像分析:使用Capsule Networks实现医学图像分类
  • vscode开发微信小程序
  • 01 基于sklearn的机械学习-机械学习的分类、sklearn的安装、sklearn数据集、数据集的划分、特征工程中特征提取与无量纲化
  • (四十三)深度解析领域特定语言(DSL)第七章——语法分析器组合子(Parser Combinators)
  • 传统数据库连接已OUT!飞算JavaAI开启Java开发智能新潮流
  • 【C++算法】78.BFS解决FloodFill算法_算法简介
  • 两数之和(每天刷力扣hot100系列)