From 01e779d8658c1dfbd121e133fe42c4e7e9627ce7 Mon Sep 17 00:00:00 2001 From: 13766800364 <13766800364@qq.com> Date: Thu, 9 Oct 2025 16:10:13 +0800 Subject: [PATCH] Add File --- .../com/gitee/drinkjava2/frog/Animal.java | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 history/006_snake/src/main/java/com/gitee/drinkjava2/frog/Animal.java diff --git a/history/006_snake/src/main/java/com/gitee/drinkjava2/frog/Animal.java b/history/006_snake/src/main/java/com/gitee/drinkjava2/frog/Animal.java new file mode 100644 index 0000000..2814267 --- /dev/null +++ b/history/006_snake/src/main/java/com/gitee/drinkjava2/frog/Animal.java @@ -0,0 +1,144 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.gitee.drinkjava2.frog; + +import java.awt.Graphics; +import java.awt.Image; +import java.util.ArrayList; +import java.util.List; + +import com.gitee.drinkjava2.frog.brain.Cell; +import com.gitee.drinkjava2.frog.brain.Organ; +import com.gitee.drinkjava2.frog.egg.Egg; +import com.gitee.drinkjava2.frog.objects.Material; +import com.gitee.drinkjava2.frog.organ.Line; +import com.gitee.drinkjava2.frog.util.RandomUtils; + +/** + * Animal = cells
+ * cells = actions + photons
+ * + * Animal's name is Sam. + * + * 脑由一个cells三维数组组成,每个cell里可以存在多个行为,行为是由器官决定,同一个细胞可以存在多种行为。光子是信息的载体,永远不停留。 + * + * @author Yong Zhu + * + * @since 1.0 + */ +public abstract class Animal {// 这个程序大量用到public变量而不是getter/setter,主要是为了编程方便和简洁,但缺点是编程者需要小心维护各个变量 + /** brain cells */ + public List cells = new ArrayList<>(); + + /** organs */ + public List organs = new ArrayList<>(); + + public int x; // animal在Env中的x坐标 + public int y; // animal在Env中的y坐标 + public long energy = 100000; // 青蛙的能量为0则死掉 + public boolean alive = true; // 设为false表示青蛙死掉了,将不参与计算和显示,以节省时间 + public int ateFood = 0; // 青蛙曾吃过的食物总数,下蛋时如果两个青蛙能量相等,可以比数量 + public int no; // 青蛙在Env.animals中的序号,从1开始, 会在运行期写到当前brick的最低位,可利用Env.animals.get(no-1)快速定位青蛙 + + public Image animalImage; + + public Animal(Egg egg) {// x, y 是虑拟环境的坐标 + if (Env.BORN_AT_RANDOM_PLACE) { + x = RandomUtils.nextInt(Env.ENV_WIDTH); + y = RandomUtils.nextInt(Env.ENV_HEIGHT); + } else { + this.x = egg.x + RandomUtils.nextInt(80) - 40; + this.y = egg.y + RandomUtils.nextInt(80) - 40; + if (this.x < 0) + this.x = 0; + if (this.y < 0) + this.y = 0; + if (this.x >= (Env.ENV_WIDTH - 1)) + this.x = Env.ENV_WIDTH - 1; + if (this.y >= (Env.ENV_HEIGHT - 1)) + this.y = Env.ENV_HEIGHT - 1; + } + for (Organ org : egg.organs) + organs.add(org); + } + + public void initAnimal() { // 初始化animal,通常只是调用每个organ的init方法 + for (Organ org : organs) + org.initOrgan(this);// 每个新器官初始化,如果是Group类,它们会生成许多脑细胞 + } + + public void addRandomLines() {// 有一定机率在器官间生成随机的神经连线 + if (alive && RandomUtils.percent(0.2f)) {// 有很小的机率在青蛙活着时就创建新的器官 + Line line = new Line(); + line.initilized = false; + line.initOrgan(this); + organs.add(line); + } + } + + public boolean active() {// 这个active方法在每一步循环都会被调用,是脑思考的最小帧 + // 如果能量小于0、出界、与非食物的点重合则判死 + if (!alive) { + energy -= 1000; // 死掉的青蛙也要消耗能量,确保淘汰出局 + return false; + } + if (energy < 0 || Env.outsideEnv(x, y) || Env.bricks[x][y] >= Material.KILL_ANIMAL) { + energy -= 1000; + kill(); + return false; + } + energy -= 20; + // 依次调用每个organ的active方法 + for (Organ organ : organs) + organ.active(this); + // 依次调用每个cell的active方法,这是写在organ类里的方法,因为同一个器官的cell具有相同的行为 + for (Cell cell : cells) + cell.organ.active(this, cell); + addRandomLines(); // 随机添加神经连线, 这是一个硬编码, 目前一个连线对应一个器官,待改进 + return alive; + } + + public abstract void show(Graphics g);// 显示青蛙或蛇,子类要重写这个方法 + + public abstract void kill();// 杀死青蛙或蛇,子类要重写这个方法 + + @SuppressWarnings("unchecked") + public T findOrganByClass(Class claz) {// 根据器官名寻找器官,但不是每个器官都有名字 + for (Organ o : organs) + if (o != null && o.getClass() == claz) + return (T) o; + return null; + } + + /** Check if x,y,z out of animal's brain range */ + public static boolean outBrainRange(int x, int y, int z) {// 检查指定坐标是否超出animal脑空间界限 + return x < 0 || x >= Env.FROG_BRAIN_XSIZE || y < 0 || y >= Env.FROG_BRAIN_YSIZE || z < 0 + || z >= Env.FROG_BRAIN_ZSIZE; + } + + /** Print debug info */ + public String debugInfo() {// 输出Animal调试内容 + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < organs.size(); i++) { + Organ o = organs.get(i); + if (o != null) { + sb.append("organ(" + i + ")=" + o.getClass()).append("\r"); + if (Line.class.equals(o.getClass())) { + Line l = (Line) o; + sb.append(l.inputZone.debugInfo()).append("\r"); + sb.append(l.outputZone.debugInfo()).append("\r"); + } + } + } + return sb.toString(); + } + +}