mirror of
https://gitee.com/drinkjava2/frog.git
synced 2024-11-25 16:04:06 +08:00
Cleanup core\bottom_up and fix root frog path bug
This commit is contained in:
parent
278918bc59
commit
efae3b4ca7
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.awt.image.BufferedImage;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import com.gitee.drinkjava2.frog.brain.Cell;
|
||||
import com.gitee.drinkjava2.frog.egg.Egg;
|
||||
import com.gitee.drinkjava2.frog.objects.Material;
|
||||
import com.gitee.drinkjava2.frog.util.RandomUtils;
|
||||
|
||||
/**
|
||||
* Animal = cells <br/>
|
||||
* cells = actions + photons <br/>
|
||||
*
|
||||
* Animal's name is Sam.
|
||||
*
|
||||
* 脑由一个cells三维数组组成,每个cell里可以存在多个行为,行为是由器官决定,同一个细胞可以存在多种行为。光子是信息的载体,永远不停留。
|
||||
*
|
||||
* @author Yong Zhu
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public abstract class Animal {// 这个程序大量用到public变量而不是getter/setter,主要是为了编程方便和简洁,但缺点是编程者需要小心维护各个变量
|
||||
public static BufferedImage FROG_IMAGE;
|
||||
public static BufferedImage snakeImage;
|
||||
|
||||
static {
|
||||
try {
|
||||
FROG_IMAGE = ImageIO.read(new FileInputStream(Application.CLASSPATH + "frog.png"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/** brain cells */
|
||||
public List<Cell> cells = 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 int animalMaterial=Material.FROG_TAG;
|
||||
public Image animalImage= Animal.FROG_IMAGE;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public void initAnimal() { // 初始化animal,通常只是调用每个organ的init方法
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
// 依次调用每个cell的active方法
|
||||
//for (Cell cell : cells)
|
||||
// cell.organ.active(this, cell);
|
||||
return alive;
|
||||
}
|
||||
|
||||
public void show(Graphics g) {// 显示当前动物
|
||||
if (!alive)
|
||||
return;
|
||||
g.drawImage(animalImage, x - 8, y - 8, 16, 16, null);// 减去坐标,保证嘴巴显示在当前x,y处
|
||||
}
|
||||
|
||||
public void kill() {// 杀死当前动物
|
||||
this.alive = false;
|
||||
Env.clearMaterial(x, y, animalMaterial);
|
||||
}
|
||||
|
||||
/** 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.BRAIN_XSIZE || y < 0 || y >= Env.BRAIN_YSIZE || z < 0 || z >= Env.BRAIN_ZSIZE;
|
||||
}
|
||||
|
||||
}
|
@ -29,7 +29,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
@ -38,22 +38,21 @@ public class Application {
|
||||
|
||||
public static JFrame mainFrame = new JFrame();
|
||||
public static Env env = new Env();
|
||||
public static BrainPicture brainPic = new BrainPicture(Env.ENV_WIDTH + 5, 0, Env.FROG_BRAIN_XSIZE,
|
||||
Env.FROG_BRAIN_DISP_WIDTH);
|
||||
public static BrainPicture brainPic = new BrainPicture(Env.ENV_WIDTH + 5, 0, Env.BRAIN_XSIZE, Env.FROG_BRAIN_DISP_WIDTH);
|
||||
public static ActionListener pauseAction;
|
||||
public static boolean selectFrog = true;
|
||||
|
||||
private static void checkIfShowBrainPicture(JButton button) {
|
||||
if (Env.SHOW_FIRST_FROG_BRAIN) {
|
||||
if (Env.SHOW_FIRST_ANIMAL_BRAIN) {
|
||||
button.setText("Hide brain");
|
||||
int y = Env.ENV_HEIGHT + 160;
|
||||
int y = Env.ENV_HEIGHT + 120;
|
||||
if (Env.FROG_BRAIN_DISP_WIDTH + 41 > y)
|
||||
y = Env.FROG_BRAIN_DISP_WIDTH + 41;
|
||||
mainFrame.setSize(Env.ENV_WIDTH + Env.FROG_BRAIN_DISP_WIDTH + 25, y);
|
||||
brainPic.requestFocus();
|
||||
brainPic.requestFocus();
|
||||
} else {
|
||||
button.setText("Show brain");
|
||||
mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 160);
|
||||
mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 120);
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,22 +63,14 @@ public class Application {
|
||||
mainFrame.add(env); // 添加虚拟环境Panel
|
||||
mainFrame.add(brainPic); // 添加脑图Panel
|
||||
|
||||
JButton showBrainbutton = new JButton("Show brain");// 按钮,显示或隐藏脑图
|
||||
JButton button = new JButton("Show brain");// 按钮,显示或隐藏脑图
|
||||
int buttonWidth = 100;
|
||||
int buttonHeight = 22;
|
||||
int buttonXpos = Env.ENV_WIDTH / 2 - buttonWidth / 2;
|
||||
button.setBounds(buttonXpos, Env.ENV_HEIGHT + 8, buttonWidth, buttonHeight);
|
||||
|
||||
showBrainbutton.setBounds(buttonXpos, Env.ENV_HEIGHT + 8, buttonWidth, buttonHeight);
|
||||
ActionListener al = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {//显示或隐藏脑图
|
||||
Env.SHOW_FIRST_FROG_BRAIN = !Env.SHOW_FIRST_FROG_BRAIN;
|
||||
checkIfShowBrainPicture(showBrainbutton);
|
||||
}
|
||||
};
|
||||
checkIfShowBrainPicture(showBrainbutton);
|
||||
showBrainbutton.addActionListener(al);
|
||||
mainFrame.add(showBrainbutton);
|
||||
checkIfShowBrainPicture(button);
|
||||
mainFrame.add(button);
|
||||
|
||||
JButton stopButton = new JButton("Pause");// 暂停或继续按钮
|
||||
stopButton.setBounds(buttonXpos, Env.ENV_HEIGHT + 35, buttonWidth, buttonHeight);
|
||||
@ -113,9 +104,9 @@ public class Application {
|
||||
final JLabel label = new JLabel("Speed:");
|
||||
label.setBounds(buttonXpos - 90, stopButton.getY() + 23, 100, buttonHeight);
|
||||
mainFrame.add(label);
|
||||
|
||||
|
||||
|
||||
mainFrame.setVisible(true);
|
||||
mainFrame.setTitle("这是一个空框架,用随机生成基因的方式来实现细胞3D分裂还没开始做");
|
||||
env.run();
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,9 @@ import java.util.List;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.gitee.drinkjava2.frog.egg.Egg;
|
||||
import com.gitee.drinkjava2.frog.egg.EggTool;
|
||||
import com.gitee.drinkjava2.frog.egg.FrogEggTool;
|
||||
import com.gitee.drinkjava2.frog.objects.EnvObject;
|
||||
import com.gitee.drinkjava2.frog.objects.Food;
|
||||
import com.gitee.drinkjava2.frog.objects.Material;
|
||||
import com.gitee.drinkjava2.frog.util.RandomUtils;
|
||||
|
||||
@ -23,244 +24,307 @@ import com.gitee.drinkjava2.frog.util.RandomUtils;
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class Env extends JPanel {
|
||||
/** Speed of test */
|
||||
public static int SHOW_SPEED = 1; // 测试速度,-1000~1000,可调, 数值越小,速度越慢
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Delete eggs at beginning of each run */
|
||||
public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋
|
||||
/** Speed of test */
|
||||
public static int SHOW_SPEED = 1; // 测试速度,-1000~1000,可调, 数值越小,速度越慢
|
||||
|
||||
public static final int EGG_QTY = 5; // 每轮下n个蛋,可调,只有最优秀的前n个青蛙们才允许下蛋
|
||||
/** Delete eggs at beginning of each run */
|
||||
public static final boolean DELETE_FROG_EGGS = true;// 每次运行是否先删除保存的青蛙蛋
|
||||
|
||||
public static final int FROG_PER_EGG = 5; // 每个蛋可以孵出几个青蛙
|
||||
public static final int FROG_EGG_QTY = 25; // 每轮下n个青蛙蛋,可调,只有最优秀的前n个青蛙们才允许下蛋
|
||||
|
||||
public static final int SCREEN = 1; // 分几屏测完
|
||||
public static final int FROG_PER_EGG = 4; // 每个青蛙蛋可以孵出几个青蛙
|
||||
|
||||
public static final int FROG_PER_SCREEN = EGG_QTY * FROG_PER_EGG / SCREEN; // 每屏上显示几个青蛙,这个数值由上面三个参数计算得来
|
||||
public static final boolean BORN_AT_RANDOM_PLACE = true;// 孵出动物落在地图上随机位置,而不是在蛋所在地
|
||||
|
||||
/** Frog's brain size is a 3D array of Cell */ // 脑空间是个三维Cell数组,为节约内存,仅在用到数组元素时才去初始化这维,按需分配内存
|
||||
public static final int FROG_BRAIN_XSIZE = 20; // frog的脑在X方向长度
|
||||
public static final int FROG_BRAIN_YSIZE = 20; // frog的脑在Y方向长度
|
||||
public static final int FROG_BRAIN_ZSIZE = 20; // frog的脑在Z方向长度
|
||||
public static final int SCREEN = 1; // 分几屏测完
|
||||
|
||||
/** SHOW first frog's brain structure */
|
||||
public static boolean SHOW_FIRST_FROG_BRAIN = true; // 是否显示脑图在Env区的右侧
|
||||
/** Frog's brain size is a 3D array of Cell */ // 脑空间是个三维Cell数组,为节约内存,仅在用到数组元素时才去初始化这维,按需分配内存
|
||||
public static final int BRAIN_XSIZE = 1000; // 脑在X方向长度
|
||||
public static final int BRAIN_YSIZE = 1000; // 脑在Y方向长度
|
||||
public static final int BRAIN_ZSIZE = 1000; // 脑在Z方向长度
|
||||
|
||||
/** Draw first frog's brain after some steps */
|
||||
public static int DRAW_BRAIN_AFTER_STEPS = 1; // 以此值为间隔动态画出脑图,设为0则关闭这个动态脑图功能,只显示一个静态、不闪烁的脑图
|
||||
/** SHOW first animal's brain structure */
|
||||
public static boolean SHOW_FIRST_ANIMAL_BRAIN = true; // 是否显示脑图在Env区的右侧
|
||||
|
||||
/** Environment x width, unit: pixels */
|
||||
public static final int ENV_WIDTH = 400; // 虚拟环境的宽度, 可调
|
||||
/** Draw first frog's brain after some steps */
|
||||
public static int DRAW_BRAIN_AFTER_STEPS = 1; // 以此值为间隔动态画出脑图,设为0则关闭这个动态脑图功能,只显示一个静态、不闪烁的脑图
|
||||
|
||||
/** Environment y height, unit: pixels */
|
||||
public static final int ENV_HEIGHT = ENV_WIDTH; // 虚拟环境高度, 可调,通常取正方形
|
||||
/** Environment x width, unit: pixels */
|
||||
public static final int ENV_WIDTH = 400; // 虚拟环境的宽度, 可调
|
||||
|
||||
/** Frog's brain display width on screen, not important */
|
||||
public static final int FROG_BRAIN_DISP_WIDTH = 600; // Frog的脑图在屏幕上的显示大小,可调
|
||||
/** Environment y height, unit: pixels */
|
||||
public static final int ENV_HEIGHT = ENV_WIDTH; // 虚拟环境高度, 可调,通常取正方形
|
||||
|
||||
/** Steps of one test round */
|
||||
public static final int STEPS_PER_ROUND = 200;// 每轮测试步数,可调
|
||||
public static int step;// 当前测试步数
|
||||
/** Frog's brain display width on screen, not important */
|
||||
public static final int FROG_BRAIN_DISP_WIDTH = 400; // Frog的脑图在屏幕上的显示大小,可调
|
||||
|
||||
public static final int FOOD_QTY = 100; // 食物数量, 可调
|
||||
/** Steps of one test round */
|
||||
public static final int STEPS_PER_ROUND = 2000;// 每轮测试步数,可调
|
||||
public static int step;// 当前测试步数
|
||||
|
||||
// 以下是程序内部变量,不要手工修改它们
|
||||
public static boolean pause = false; // 暂停按钮按下将暂停测试
|
||||
public static final int FOOD_QTY = 1500; // 食物数量, 可调
|
||||
|
||||
public static byte[][] bricks = new byte[ENV_WIDTH][ENV_HEIGHT];// 组成环境的材料,见Material.java
|
||||
// 以下是程序内部变量,不要手工修改它们
|
||||
public static final int TOTAL_FROG_QTY = FROG_EGG_QTY * FROG_PER_EGG; // 蛇的总数
|
||||
|
||||
public static List<Frog> frogs = new ArrayList<>(); // 这里存放所有待测的青蛙,可能分几次测完,由FROG_PER_SCREEN大小来决定
|
||||
public static final int FROG_PER_SCREEN = TOTAL_FROG_QTY / SCREEN; // 每屏显示几个青蛙,这个数值由其它常量计算得来
|
||||
|
||||
public static List<Egg> eggs = new ArrayList<>(); // 这里存放新建或从磁盘载入上轮下的蛋,每个蛋可能生成几个青蛙,
|
||||
public static int current_screen = 0;
|
||||
|
||||
public static EnvObject[] things = new EnvObject[]{};// 所有外界物体,如食物、字母测试工具都放在这个things里面
|
||||
public static int food_ated = 0; // 用来统计总共多少个食物被青蛙吃掉
|
||||
|
||||
static {
|
||||
System.out.println("脑图快捷键: T:顶视 F:前视 L:左视 R:右视 X:斜视 方向键:剖视 空格:暂停 鼠标:缩放旋转平移");
|
||||
if (DELETE_EGGS) {
|
||||
System.out.println("唵缚悉波罗摩尼莎诃!"); // 杀生前先打印往生咒,见码云issue#IW4H8
|
||||
EggTool.deleteEggs();
|
||||
}
|
||||
public static int frog_ated = 0; // 用来统计总共多少个食物被青蛙吃掉
|
||||
|
||||
public static boolean pause = false; // 暂停按钮按下将暂停测试
|
||||
|
||||
public static int[][] bricks = new int[ENV_WIDTH][ENV_HEIGHT];// 组成环境的材料,见Material.java
|
||||
|
||||
public static List<Frog> frogs = new ArrayList<>(); // 这里存放所有待测的青蛙,可能分几次测完,由FROG_PER_SCREEN大小来决定
|
||||
|
||||
public static List<Egg> frog_eggs = new ArrayList<>(); // 这里存放新建或从磁盘载入上轮下的蛋,每个蛋可能生成几个青蛙,
|
||||
|
||||
public static EnvObject[] things = new EnvObject[] { new Food() };// 所有外界物体,如食物、字母测试工具都放在这个things里面
|
||||
|
||||
static {
|
||||
System.out.println("唵缚悉波罗摩尼莎诃!"); // 杀生前先打印往生咒,见码云issue#IW4H8
|
||||
System.out.println("脑图快捷键: T:顶视 F:前视 L:左视 R:右视 X:斜视 方向键:剖视 空格:暂停 鼠标:缩放旋转平移");
|
||||
if (DELETE_FROG_EGGS)
|
||||
FrogEggTool.deleteEggs();
|
||||
}
|
||||
|
||||
public Env() {
|
||||
super();
|
||||
this.setLayout(null);// 空布局
|
||||
this.setBounds(1, 1, ENV_WIDTH, ENV_HEIGHT);
|
||||
}
|
||||
|
||||
public static boolean insideEnv(int x, int y) {// 如果指定点在边界内
|
||||
return !(x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT);
|
||||
}
|
||||
|
||||
public static boolean outsideEnv(int x, int y) {// 如果指定点超出边界
|
||||
return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT;
|
||||
}
|
||||
|
||||
public static boolean closeToEdge(Animal a) {// 靠近边界? 离死不远了
|
||||
return a.x < 20 || a.y < 20 || a.x > (Env.ENV_WIDTH - 20) || a.y > (Env.ENV_HEIGHT - 20);
|
||||
}
|
||||
|
||||
public static boolean foundAnyThingOrOutEdge(int x, int y) {// 如果指定点看到任意东西或超出边界,返回true
|
||||
return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT || Env.bricks[x][y] != 0;
|
||||
}
|
||||
|
||||
public static boolean foundAndAteFood(int x, int y) {// 如果x,y有食物,将其清0,返回true
|
||||
if (insideEnv(x, y) && (Env.bricks[x][y] & Material.FOOD) > 0) {
|
||||
Env.food_ated++;
|
||||
clearMaterial(x, y, Material.FOOD);// 清空任意食物
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean foundFrogOrOutEdge(int x, int y) {// 如果指定点看到青蛙或超出边界,返回true
|
||||
if (x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT)
|
||||
return true;// 如果出界返回true
|
||||
if ((Env.bricks[x][y] & Material.FROG_TAG) > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean foundAndAteFrog(int x, int y) {// 如果x,y有青蛙,将其杀死,返回true
|
||||
if (x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT)
|
||||
return false;// 如果出界返回false;
|
||||
int frogNo = Env.bricks[x][y] & Material.FROG_TAG;
|
||||
if (frogNo > 0) {
|
||||
Frog f = frogs.get(frogNo - 1);
|
||||
if (f.alive) {
|
||||
Env.frog_ated++;
|
||||
f.kill();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void setMaterial(int x, int y, int material) {
|
||||
if (Env.insideEnv(x, y))
|
||||
Env.bricks[x][y] = Env.bricks[x][y] | material;
|
||||
}
|
||||
|
||||
public Env() {
|
||||
super();
|
||||
this.setLayout(null);// 空布局
|
||||
this.setBounds(1, 1, ENV_WIDTH, ENV_HEIGHT);
|
||||
public static boolean hasMaterial(int x, int y, int material) {
|
||||
if (!Env.insideEnv(x, y))
|
||||
return false;
|
||||
return (Env.bricks[x][y] & material) > 0;
|
||||
}
|
||||
|
||||
public static boolean insideEnv(int x, int y) {// 如果指定点在边界内
|
||||
return !(x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT);
|
||||
public static void clearMaterial(int x, int y, int material) {
|
||||
if (Env.insideEnv(x, y))
|
||||
Env.bricks[x][y] = Env.bricks[x][y] & ~material;
|
||||
}
|
||||
|
||||
public static boolean outsideEnv(int x, int y) {// 如果指定点超出边界
|
||||
return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT;
|
||||
}
|
||||
private void rebuildFrogs() {// 根据蛙蛋重新孵化出蛙
|
||||
frogs.clear();
|
||||
for (int i = 0; i < frog_eggs.size(); i++) {// 创建青蛙,每个蛋生成n个蛙,并随机取一个别的蛋作为精子
|
||||
int loop = FROG_PER_EGG;
|
||||
if (frog_eggs.size() > 20) { // 如果数量多,进行一些优化,让排名靠前的Egg多孵出青蛙
|
||||
if (i < FROG_PER_EGG)// 0,1,2,3
|
||||
loop = FROG_PER_EGG + 1;
|
||||
if (i >= (frog_eggs.size() - FROG_PER_EGG))
|
||||
loop = FROG_PER_EGG - 1;
|
||||
}
|
||||
for (int j = 0; j < loop; j++) {
|
||||
Egg zygote = new Egg(frog_eggs.get(i), frog_eggs.get(RandomUtils.nextInt(frog_eggs.size())));
|
||||
Frog f = new Frog(zygote);
|
||||
frogs.add(f);
|
||||
f.no = frogs.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawWorld(Graphics g) {
|
||||
int brick;
|
||||
for (int x = 0; x < ENV_WIDTH; x++)
|
||||
for (int y = 0; y < ENV_HEIGHT; y++) {
|
||||
brick = bricks[x][y];
|
||||
if (brick != 0) {
|
||||
g.setColor(Material.color(brick));
|
||||
if ((brick & Material.FOOD) > 0) {
|
||||
g.fillRoundRect(x, y, 4, 4, 2, 2); //食物只有一个点太小,画大一点
|
||||
} else
|
||||
g.drawLine(x, y, x, y); // only 1 point
|
||||
}
|
||||
}
|
||||
g.setColor(Color.BLACK);
|
||||
}
|
||||
|
||||
public static boolean closeToEdge(Frog f) {// 青蛙靠近边界? 离死不远了
|
||||
return f.x < 20 || f.y < 20 || f.x > (Env.ENV_WIDTH - 20) || f.y > (Env.ENV_HEIGHT - 20);
|
||||
}
|
||||
static final NumberFormat format100 = NumberFormat.getPercentInstance();
|
||||
static {
|
||||
format100.setMaximumFractionDigits(2);
|
||||
}
|
||||
|
||||
public static boolean foundAnyThing(int x, int y) {// 如果指定点看到任意东西或超出边界
|
||||
return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT || Env.bricks[x][y] >= Material.VISIBLE;
|
||||
}
|
||||
private String foodAtedCount() {// 统计吃食总数等
|
||||
int maxFound = 0;
|
||||
for (Frog f : frogs)
|
||||
if (f.ateFood > maxFound)
|
||||
maxFound = f.ateFood;
|
||||
return new StringBuilder("吃食率:").append(format100.format(Env.food_ated * 1.00 / FOOD_QTY)).append(", 平均: ")
|
||||
.append(Env.food_ated * 1.0f / FROG_PER_SCREEN).append(",最多:").append(maxFound).toString();
|
||||
}
|
||||
|
||||
public static boolean foundAndAteFood(int x, int y) {// 如果x,y有食物,将其清0,返回true
|
||||
if (insideEnv(x, y) && Env.bricks[x][y] == Material.FOOD) {
|
||||
bricks[x][y] = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private String frogAtedCount() {// 统计食蛙总数
|
||||
return new StringBuilder("吃蛙率:").append(format100.format(Env.frog_ated * 1.00 / TOTAL_FROG_QTY)).toString();
|
||||
}
|
||||
|
||||
private void rebuildFrogs() {
|
||||
frogs.clear();
|
||||
for (int i = 0; i < eggs.size(); i++) {// 创建青蛙,每个蛋生成n个蛙,并随机取一个别的蛋作为精子
|
||||
int loop = FROG_PER_EGG;
|
||||
if (eggs.size() > 20) { // 如果数量多,进行一些优化,让排名靠前的Egg多孵出青蛙
|
||||
if (i < FROG_PER_EGG)// 0,1,2,3
|
||||
loop = FROG_PER_EGG + 1;
|
||||
if (i >= (eggs.size() - FROG_PER_EGG))
|
||||
loop = FROG_PER_EGG - 1;
|
||||
}
|
||||
for (int j = 0; j < loop; j++) {
|
||||
Egg zygote = new Egg(eggs.get(i), eggs.get(RandomUtils.nextInt(eggs.size())));
|
||||
frogs.add(new Frog(RandomUtils.nextInt(ENV_WIDTH), RandomUtils.nextInt(ENV_HEIGHT), zygote));
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void checkIfPause() {
|
||||
if (pause)
|
||||
do {
|
||||
Application.brainPic.drawBrainPicture();
|
||||
Application.brainPic.requestFocus();
|
||||
sleep(100);
|
||||
} while (pause);
|
||||
}
|
||||
|
||||
private void drawWorld(Graphics g) {
|
||||
byte brick;
|
||||
for (int x = 0; x < ENV_WIDTH; x++)
|
||||
for (int y = 0; y < ENV_HEIGHT; y++) {
|
||||
brick = bricks[x][y];
|
||||
if (brick != 0) {
|
||||
g.setColor(Material.color(brick));
|
||||
if (brick == Material.FOOD)
|
||||
g.fillRoundRect(x, y, 4, 4, 2, 2); // show food bigger
|
||||
else
|
||||
g.drawLine(x, y, x, y); // only 1 point
|
||||
}
|
||||
}
|
||||
g.setColor(Color.BLACK);
|
||||
}
|
||||
public static void sleep(long millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static final NumberFormat format100 = NumberFormat.getPercentInstance();
|
||||
static {
|
||||
format100.setMaximumFractionDigits(2);
|
||||
}
|
||||
public static Animal getShowAnimal() {
|
||||
return frogs.get(current_screen * FROG_PER_SCREEN);
|
||||
}
|
||||
|
||||
private static int foodFoundAmount() {// 统计找食数等
|
||||
int leftfood = 0;
|
||||
for (int x = 0; x < ENV_WIDTH; x++)
|
||||
for (int y = 0; y < ENV_HEIGHT; y++)
|
||||
if (bricks[x][y] == Material.FOOD)
|
||||
leftfood++;
|
||||
return FOOD_QTY - leftfood;
|
||||
}
|
||||
public void run() {
|
||||
FrogEggTool.loadFrogEggs(); // 从磁盘加载蛙egg,或新建一批egg
|
||||
Image buffImg = createImage(this.getWidth(), this.getHeight());
|
||||
Graphics g = buffImg.getGraphics();
|
||||
long time0;// 计时用
|
||||
int round = 1;
|
||||
do {
|
||||
rebuildFrogs();
|
||||
for (current_screen = 0; current_screen < SCREEN; current_screen++) {// 分屏测试,每屏FROG_PER_SCREEN个蛙
|
||||
Env.food_ated = 0; // 先清0吃食物数
|
||||
Env.frog_ated = 0;// 先清0吃蛙数
|
||||
time0 = System.currentTimeMillis();
|
||||
for (EnvObject thing : things) // 创建食物、陷阱等物体
|
||||
thing.build();
|
||||
boolean allDead = false;
|
||||
|
||||
private String foodFoundCountText() {// 统计找食数等
|
||||
int foodFound = foodFoundAmount();
|
||||
int maxFound = 0;
|
||||
for (Frog f : frogs)
|
||||
if (f.ateFood > maxFound)
|
||||
maxFound = f.ateFood;
|
||||
return new StringBuilder("找食率:").append(format100.format(foodFound * 1.00 / FOOD_QTY)).append(", 平均: ").append(foodFound * 1.0f / FROG_PER_SCREEN).append(",最多:").append(maxFound).toString();
|
||||
}
|
||||
for (int j = 0; j < FROG_PER_SCREEN; j++) {
|
||||
Frog f = frogs.get(current_screen * FROG_PER_SCREEN + j);
|
||||
f.initAnimal(); // 初始化器官延迟到这一步,是因为脑细胞太占内存,而且当前屏测完后会清空
|
||||
}
|
||||
|
||||
public static void checkIfPause(Frog f) {
|
||||
if (pause)
|
||||
do {
|
||||
if (f != null) {
|
||||
Application.brainPic.drawBrainPicture(f);
|
||||
Application.brainPic.requestFocus();
|
||||
}
|
||||
sleep(100);
|
||||
} while (pause);
|
||||
}
|
||||
for (step = 0; step < STEPS_PER_ROUND; step++) {
|
||||
for (EnvObject thing : things)// 调用食物、陷阱等物体的动作
|
||||
thing.active();
|
||||
if (allDead)
|
||||
break; // 青蛙全死光了就直接跳到下一轮,以节省时间
|
||||
allDead = true;
|
||||
for (int j = 0; j < FROG_PER_SCREEN; j++) {
|
||||
Frog f = frogs.get(current_screen * FROG_PER_SCREEN + j);
|
||||
if (f.active())// 调用青蛙的Active方法,并返回是否还活着
|
||||
allDead = false;
|
||||
}
|
||||
|
||||
public static void sleep(long millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (SHOW_SPEED > 0 && step % SHOW_SPEED != 0) // 用是否跳帧画图的方式来控制速度
|
||||
continue;
|
||||
|
||||
public void run() {
|
||||
EggTool.loadEggs(); // 从磁盘加载egg,或新建一批egg
|
||||
Image buffImg = createImage(this.getWidth(), this.getHeight());
|
||||
Graphics g = buffImg.getGraphics();
|
||||
long time0;// 计时用
|
||||
int round = 1;
|
||||
do {
|
||||
rebuildFrogs();
|
||||
for (int screen = 0; screen < SCREEN; screen++) {// 分屏测试,每屏FROG_PER_SCREEN个蛙
|
||||
time0 = System.currentTimeMillis();
|
||||
for (EnvObject thing : things) // 创建食物、陷阱等物体
|
||||
thing.build();
|
||||
boolean allDead = false;
|
||||
Frog firstFrog = frogs.get(screen * FROG_PER_SCREEN);
|
||||
checkIfPause(firstFrog);
|
||||
for (int j = 0; j < FROG_PER_SCREEN; j++) {
|
||||
Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
|
||||
f.initFrog(); // 初始化器官延迟到这一步,是因为脑细胞太占内存,而且当前屏测完后会清空
|
||||
}
|
||||
if (SHOW_SPEED < 0) // 如果speed小于0,人为加入延迟
|
||||
sleep(-SHOW_SPEED);
|
||||
|
||||
for (step = 0; step < STEPS_PER_ROUND; step++) {
|
||||
for (EnvObject thing : things)// 调用食物、陷阱等物体的动作
|
||||
thing.active(screen);
|
||||
if (allDead)
|
||||
break; // 青蛙全死光了就直接跳到下一轮,以节省时间
|
||||
allDead = true;
|
||||
for (int j = 0; j < FROG_PER_SCREEN; j++) {
|
||||
Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
|
||||
if (f.active(this))
|
||||
allDead = false;
|
||||
}
|
||||
// 开始画虚拟环境和青蛙和蛇
|
||||
g.setColor(Color.white);
|
||||
g.fillRect(0, 0, this.getWidth(), this.getHeight()); // 先清空虚拟环境
|
||||
g.setColor(Color.BLACK);
|
||||
drawWorld(g);// 画整个虚拟环境
|
||||
for (int j = 0; j < FROG_PER_SCREEN; j++) { // 显示青蛙
|
||||
Frog f = frogs.get(current_screen * FROG_PER_SCREEN + j);
|
||||
f.show(g);
|
||||
}
|
||||
|
||||
if (SHOW_FIRST_ANIMAL_BRAIN) {// 在showAnimal上画一个红圈
|
||||
Animal showAnimal = getShowAnimal();
|
||||
if (showAnimal != null) {
|
||||
g.setColor(Color.red);
|
||||
g.drawArc(showAnimal.x - 15, showAnimal.y - 15, 30, 30, 0, 360);
|
||||
g.setColor(Color.BLACK);
|
||||
}
|
||||
}
|
||||
if (DRAW_BRAIN_AFTER_STEPS > 0 && step % DRAW_BRAIN_AFTER_STEPS == 0)
|
||||
Application.brainPic.drawBrainPicture();
|
||||
Graphics g2 = this.getGraphics();
|
||||
g2.drawImage(buffImg, 0, 0, this);
|
||||
}
|
||||
// System.out.println(showFrog.debugInfo());// 打印输出Frog调试内容
|
||||
if (SHOW_FIRST_ANIMAL_BRAIN)
|
||||
Application.brainPic.drawBrainPicture();
|
||||
checkIfPause();
|
||||
for (int j = 0; j < FROG_PER_SCREEN; j++) {
|
||||
Frog f = frogs.get(current_screen * FROG_PER_SCREEN + j);
|
||||
f.cells = null; // 清空frog脑细胞所占用的内存
|
||||
}
|
||||
StringBuilder sb = new StringBuilder("Round: ");
|
||||
sb.append(round).append(", screen:").append(current_screen).append(", speed:").append(Env.SHOW_SPEED)
|
||||
.append(", ").append(", 用时: ").append(System.currentTimeMillis() - time0).append("ms, ");
|
||||
sb.append(foodAtedCount());
|
||||
|
||||
if (SHOW_SPEED > 0 && step % SHOW_SPEED != 0) // 用画青蛙的方式来拖慢速度
|
||||
continue;
|
||||
|
||||
if (SHOW_SPEED <= 1) // 如果speed小于0,人为加入延迟
|
||||
sleep(5);
|
||||
|
||||
// 开始画青蛙
|
||||
g.setColor(Color.white);
|
||||
g.fillRect(0, 0, this.getWidth(), this.getHeight());
|
||||
g.setColor(Color.BLACK);
|
||||
drawWorld(g);
|
||||
for (int j = 0; j < FROG_PER_SCREEN; j++) {
|
||||
Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
|
||||
f.show(g);
|
||||
}
|
||||
|
||||
if (firstFrog.alive) { // 开始显示第一个Frog的动态脑图
|
||||
if (SHOW_FIRST_FROG_BRAIN) {
|
||||
g.setColor(Color.red);
|
||||
g.drawArc(firstFrog.x - 15, firstFrog.y - 15, 30, 30, 0, 360);
|
||||
g.setColor(Color.BLACK);
|
||||
}
|
||||
if (DRAW_BRAIN_AFTER_STEPS > 0 && step % DRAW_BRAIN_AFTER_STEPS == 0)
|
||||
Application.brainPic.drawBrainPicture(firstFrog);
|
||||
}
|
||||
Graphics g2 = this.getGraphics();
|
||||
g2.drawImage(buffImg, 0, 0, this);
|
||||
}
|
||||
Application.brainPic.drawBrainPicture(firstFrog);
|
||||
for (int j = 0; j < FROG_PER_SCREEN; j++) {
|
||||
Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
|
||||
f.cells = null; // 清空frog脑细胞所占用的内存
|
||||
}
|
||||
Application.mainFrame.setTitle(new StringBuilder("Round: ").append(round).append(", screen:").append(screen).append(", ").append(foodFoundCountText()).append(", 用时: ")
|
||||
.append(System.currentTimeMillis() - time0).append("ms").toString());
|
||||
for (EnvObject thing : things)// 去除食物、陷阱等物体
|
||||
thing.destory();
|
||||
}
|
||||
round++;
|
||||
EggTool.layEggs();
|
||||
} while (true);
|
||||
}
|
||||
Application.mainFrame.setTitle(sb.toString());
|
||||
// for (EnvObject thing : things)// 去除食物、陷阱等物体
|
||||
// thing.destory();
|
||||
for (int i = 0; i < ENV_WIDTH; i++) {// 清除食物
|
||||
for (int j = 0; j < ENV_HEIGHT; j++)
|
||||
bricks[i][j] = 0;
|
||||
}
|
||||
}
|
||||
round++;
|
||||
FrogEggTool.layEggs();
|
||||
} while (true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,115 +10,20 @@
|
||||
*/
|
||||
package com.gitee.drinkjava2.frog;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import com.gitee.drinkjava2.frog.brain.Cell;
|
||||
import com.gitee.drinkjava2.frog.egg.Egg;
|
||||
import com.gitee.drinkjava2.frog.objects.Material;
|
||||
|
||||
/**
|
||||
* Frog's name is Sam, Frog is made up of cells, cells are created by gene tree, gene tree is saved in egg.
|
||||
* Frog is child class of Animal
|
||||
* Frog是Animal的一个子类
|
||||
*
|
||||
* 青蛙由细胞组成,细胞的生成由基因树决定,基因树保存在蛋里,蛋最早为空,第一个基因树由随机数产生
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 1.0
|
||||
*/
|
||||
public class Frog {// 这个项目里大量用到全局public变量而不是私有变量+getter/setter,主要是为了编程方便和简洁,大项目不提倡
|
||||
/** brain cells */
|
||||
public Cell[][][] cells;// 一开始不要初始化,只在调用getOrCreateCell方法时才初始化相关维以节约内存
|
||||
public class Frog extends Animal {
|
||||
|
||||
public int x; // frog在Env中的x坐标
|
||||
public int y; // frog在Env中的y坐标
|
||||
public long energy = 10000000; // 青蛙的能量为0则死掉
|
||||
public boolean alive = true; // 设为false表示青蛙死掉了,将不参与计算和显示,以节省时间
|
||||
public int ateFood = 0;
|
||||
|
||||
static Image frogImg;
|
||||
static {
|
||||
try {
|
||||
frogImg = ImageIO.read(new FileInputStream(Application.CLASSPATH + "frog.png"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
public Frog(Egg egg) {
|
||||
super(egg);
|
||||
animalMaterial = Material.FROG_TAG;
|
||||
animalImage = Animal.FROG_IMAGE;
|
||||
}
|
||||
|
||||
public Frog(int x, int y, Egg egg) {// x, y 是虑拟环境的坐标
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public void initFrog() {// 仅在测试之前调用这个方法初始化frog以节约内存,测试完成后要清空units释放内存
|
||||
try {
|
||||
cells = new Cell[Env.FROG_BRAIN_XSIZE][][]; // 为了节约内存,先只初始化三维数组的x维,另两维用到时再分配
|
||||
} catch (OutOfMemoryError e) {
|
||||
System.out.println("OutOfMemoryError found for frog, force it die.");
|
||||
this.alive = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean active(Env v) {// 这个active方法在每一步循环都会被调用,是脑思考的最小帧
|
||||
// 如果能量小于0、出界、与非食物的点重合则判死
|
||||
if (!alive || energy < 0 || Env.outsideEnv(x, y) || Env.bricks[x][y] >= Material.KILLFROG) {
|
||||
energy -= 100; // 死掉的青蛙也要消耗能量,确保淘汰出局
|
||||
alive = false;
|
||||
return false;
|
||||
}
|
||||
energy -= 20;
|
||||
|
||||
// 这里是最关键的脑细胞主循环,调用每个细胞的act方法
|
||||
for (int i = 0; i < Env.FROG_BRAIN_XSIZE; i++) {
|
||||
Env.checkIfPause(this);
|
||||
if (cells[i] != null)
|
||||
for (int j = 0; j < Env.FROG_BRAIN_YSIZE; j++)
|
||||
if (cells[i][j] != null)
|
||||
for (int k = 0; k < Env.FROG_BRAIN_ZSIZE; k++) {
|
||||
Cell cell = cells[i][j][k];
|
||||
if (cell != null)
|
||||
cell.act();
|
||||
}
|
||||
}
|
||||
return alive;
|
||||
}
|
||||
|
||||
public void show(Graphics g) {// 显示青蛙的图象
|
||||
if (!alive)
|
||||
return;
|
||||
g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);
|
||||
}
|
||||
|
||||
/** Check if cell exist */
|
||||
public Cell getCell(int x, int y, int z) {// 返回指定脑坐标的cell ,如果不存在,返回null
|
||||
if (cells[x] == null || cells[x][y] == null)
|
||||
return null;
|
||||
return cells[x][y][z];
|
||||
}
|
||||
|
||||
/** Get a cell in position (x,y,z), if not exist, create a new one */
|
||||
public Cell getOrCreateCell(int x, int y, int z) {// 获取指定坐标的Cell,如果为空,则在指定位置新建Cell
|
||||
if (outBrainBound(x, y, z))
|
||||
return null;
|
||||
if (cells[x] == null)
|
||||
cells[x] = new Cell[Env.FROG_BRAIN_YSIZE][];
|
||||
if (cells[x][y] == null)
|
||||
cells[x][y] = new Cell[Env.FROG_BRAIN_ZSIZE];
|
||||
Cell cell = cells[x][y][z];
|
||||
if (cell == null) {
|
||||
cell = new Cell(x, y, z);
|
||||
cells[x][y][z] = cell;
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
/** Check if x,y,z out of frog's brain bound */
|
||||
public static boolean outBrainBound(int x, int y, int z) {// 检查指定坐标是否超出frog脑空间界限
|
||||
return x < 0 || x >= Env.FROG_BRAIN_XSIZE || y < 0 || y >= Env.FROG_BRAIN_YSIZE || z < 0 || z >= Env.FROG_BRAIN_ZSIZE;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,12 +3,12 @@ package com.gitee.drinkjava2.frog.brain;
|
||||
import static java.awt.Color.BLACK;
|
||||
import static java.awt.Color.RED;
|
||||
import static java.awt.Color.WHITE;
|
||||
//import static java.awt.BLUE;
|
||||
import static java.lang.Math.cos;
|
||||
import static java.lang.Math.round;
|
||||
import static java.lang.Math.sin;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
@ -16,9 +16,10 @@ import java.awt.image.BufferedImage;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.gitee.drinkjava2.frog.Animal;
|
||||
import com.gitee.drinkjava2.frog.Application;
|
||||
import com.gitee.drinkjava2.frog.Env;
|
||||
import com.gitee.drinkjava2.frog.Frog;
|
||||
import com.gitee.drinkjava2.frog.util.ColorUtils;
|
||||
|
||||
/**
|
||||
* BrainPicture show first frog's brain structure, for debug purpose only
|
||||
@ -32,288 +33,347 @@ import com.gitee.drinkjava2.frog.Frog;
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class BrainPicture extends JPanel {
|
||||
private static final float d90 = (float) (Math.PI / 2);
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
Color picColor = RED;
|
||||
int brainDispWidth; // screen display piexls width
|
||||
float scale; // brain scale
|
||||
int xOffset = 0; // brain display x offset compare to screen
|
||||
int yOffset = 0; // brain display y offset compare to screen
|
||||
float xAngle = d90 * .8f; // brain rotate on x axis
|
||||
float yAngle = d90 / 4; // brain rotate on y axis
|
||||
float zAngle = 0;// brain rotate on z axis
|
||||
int xMask = -1;// x Mask
|
||||
int yMask = -1;// y Mask
|
||||
BufferedImage buffImg;
|
||||
Graphics g;
|
||||
public KeyAdapter keyAdapter;
|
||||
private static final float D90 = (float) (Math.PI / 2);
|
||||
|
||||
public BrainPicture(int x, int y, float brainWidth, int brainDispWidth) {
|
||||
super();
|
||||
this.setLayout(null);// 空布局
|
||||
this.brainDispWidth = brainDispWidth;
|
||||
scale = 0.5f * brainDispWidth / brainWidth;
|
||||
this.setBounds(x, y, brainDispWidth + 1, brainDispWidth + 1);
|
||||
buffImg = new BufferedImage(Env.FROG_BRAIN_DISP_WIDTH, Env.FROG_BRAIN_DISP_WIDTH, BufferedImage.TYPE_INT_RGB);
|
||||
g = buffImg.getGraphics();
|
||||
MouseAction act = new MouseAction(this);
|
||||
this.addMouseListener(act); // 添加鼠标动作监听
|
||||
this.addMouseWheelListener(act);// 添加鼠标滚轮动作监听
|
||||
this.addMouseMotionListener(act);// 添加鼠标移动动作监听
|
||||
Color picColor = RED;
|
||||
int brainDispWidth; // screen display piexls width
|
||||
float scale; // brain scale
|
||||
int xOffset = 0; // brain display x offset compare to screen
|
||||
int yOffset = 0; // brain display y offset compare to screen
|
||||
float xAngle = D90 * .8f; // brain rotate on x axis
|
||||
float yAngle = D90 / 4; // brain rotate on y axis
|
||||
float zAngle = 0;// brain rotate on z axis
|
||||
int xMask = -1;// x Mask
|
||||
int yMask = -1;// y Mask
|
||||
BufferedImage buffImg;
|
||||
Graphics g;
|
||||
String note;
|
||||
public KeyAdapter keyAdapter;
|
||||
|
||||
keyAdapter = new KeyAdapter() {// 处理t,f,l,r,x键盘命令
|
||||
public void keyPressed(KeyEvent e) {
|
||||
switch (e.getKeyCode()){
|
||||
case KeyEvent.VK_UP:// Y切面向上
|
||||
yMask++;
|
||||
if (yMask > Env.FROG_BRAIN_YSIZE)
|
||||
yMask = Env.FROG_BRAIN_YSIZE;
|
||||
break;
|
||||
case KeyEvent.VK_DOWN:// Y切面向下
|
||||
yMask--;
|
||||
if (yMask < 0)
|
||||
yMask = 0;
|
||||
break;
|
||||
case KeyEvent.VK_LEFT:// x切面向左
|
||||
xMask--;
|
||||
if (xMask < 0)
|
||||
xMask = 0;
|
||||
break;
|
||||
case KeyEvent.VK_RIGHT:// x切面向右
|
||||
xMask++;
|
||||
if (xMask > Env.FROG_BRAIN_XSIZE)
|
||||
xMask = Env.FROG_BRAIN_XSIZE;
|
||||
break;
|
||||
case ' ':// 暂停及继续
|
||||
Application.pauseAction.actionPerformed(null);
|
||||
break;
|
||||
case 'T':// 顶视
|
||||
xAngle = 0;
|
||||
yAngle = 0;
|
||||
zAngle = 0;
|
||||
break;
|
||||
case 'F':// 前视
|
||||
xAngle = d90;
|
||||
yAngle = 0;
|
||||
zAngle = 0;
|
||||
break;
|
||||
case 'L':// 左视
|
||||
xAngle = d90;
|
||||
yAngle = d90;
|
||||
zAngle = 0;
|
||||
break;
|
||||
case 'R':// 右视
|
||||
xAngle = d90;
|
||||
yAngle = -d90;
|
||||
zAngle = 0;
|
||||
break;
|
||||
case 'X':// 斜视
|
||||
xAngle = d90 * .8f;
|
||||
yAngle = d90 / 4;
|
||||
zAngle = 0;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
};
|
||||
addKeyListener(keyAdapter);
|
||||
this.setFocusable(true);
|
||||
}
|
||||
public BrainPicture(int x, int y, float brainWidth, int brainDispWidth) {
|
||||
super();
|
||||
this.setLayout(null);// 空布局
|
||||
this.brainDispWidth = brainDispWidth;
|
||||
scale = 0.5f * brainDispWidth / brainWidth;
|
||||
this.setBounds(x, y, brainDispWidth + 1, brainDispWidth + 1);
|
||||
buffImg = new BufferedImage(Env.FROG_BRAIN_DISP_WIDTH, Env.FROG_BRAIN_DISP_WIDTH, BufferedImage.TYPE_INT_RGB);
|
||||
g = buffImg.getGraphics();
|
||||
MouseAction act = new MouseAction(this);
|
||||
this.addMouseListener(act); // 添加鼠标动作监听
|
||||
this.addMouseWheelListener(act);// 添加鼠标滚轮动作监听
|
||||
this.addMouseMotionListener(act);// 添加鼠标移动动作监听
|
||||
|
||||
public void drawCuboid(Cuboid c) {// 在脑图上画一个长立方体框架,视角是TopView
|
||||
float x = c.x;
|
||||
float y = c.y;
|
||||
float z = c.z;
|
||||
float xe = c.xe;
|
||||
float ye = c.ye;
|
||||
float ze = c.ze;
|
||||
keyAdapter = new KeyAdapter() {// 处理t,f,l,r,x键盘命令
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
switch (e.getKeyCode()) {
|
||||
case KeyEvent.VK_UP:// Y切面向上
|
||||
yMask++;
|
||||
if (yMask > Env.BRAIN_YSIZE)
|
||||
yMask = Env.BRAIN_YSIZE;
|
||||
break;
|
||||
case KeyEvent.VK_DOWN:// Y切面向下
|
||||
yMask--;
|
||||
if (yMask < 0)
|
||||
yMask = 0;
|
||||
break;
|
||||
case KeyEvent.VK_LEFT:// x切面向左
|
||||
xMask--;
|
||||
if (xMask < 0)
|
||||
xMask = 0;
|
||||
break;
|
||||
case KeyEvent.VK_RIGHT:// x切面向右
|
||||
xMask++;
|
||||
if (xMask > Env.BRAIN_XSIZE)
|
||||
xMask = Env.BRAIN_XSIZE;
|
||||
break;
|
||||
case ' ':// 暂停及继续
|
||||
Application.pauseAction.actionPerformed(null);
|
||||
break;
|
||||
case 'T':// 顶视
|
||||
xAngle = 0;
|
||||
yAngle = 0;
|
||||
zAngle = 0;
|
||||
break;
|
||||
case 'F':// 前视
|
||||
xAngle = D90;
|
||||
yAngle = 0;
|
||||
zAngle = 0;
|
||||
break;
|
||||
case 'L':// 左视
|
||||
xAngle = D90;
|
||||
yAngle = D90;
|
||||
zAngle = 0;
|
||||
break;
|
||||
case 'R':// 右视
|
||||
xAngle = D90;
|
||||
yAngle = -D90;
|
||||
zAngle = 0;
|
||||
break;
|
||||
case 'X':// 斜视
|
||||
xAngle = D90 * .8f;
|
||||
yAngle = D90 / 4;
|
||||
zAngle = 0;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
};
|
||||
addKeyListener(keyAdapter);
|
||||
this.setFocusable(true);
|
||||
}
|
||||
|
||||
drawLine(x, y, z, x + xe, y, z);// 画立方体的下面边
|
||||
drawLine(x + xe, y, z, x + xe, y + ye, z);
|
||||
drawLine(x + xe, y + ye, z, x, y + ye, z);
|
||||
drawLine(x, y + ye, z, x, y, z);
|
||||
public void drawCuboid(Cuboid c) {// 在脑图上画一个长立方体框架,视角是TopView
|
||||
drawCuboid(c.x, c.y, c.z, c.xe, c.ye, c.ze);
|
||||
}
|
||||
|
||||
drawLine(x, y, z, x, y, z + ze);// 画立方体的中间边
|
||||
drawLine(x + xe, y, z, x + xe, y, z + ze);
|
||||
drawLine(x + xe, y + ye, z, x + xe, y + ye, z + ze);
|
||||
drawLine(x, y + ye, z, x, y + ye, z + ze);
|
||||
public void drawCuboid(float x, float y, float z, float xe, float ye, float ze) {// 在脑图上画一个长立方体框架,视角是TopView
|
||||
drawLine(x, y, z, x + xe, y, z);// 画立方体的下面边
|
||||
drawLine(x + xe, y, z, x + xe, y + ye, z);
|
||||
drawLine(x + xe, y + ye, z, x, y + ye, z);
|
||||
drawLine(x, y + ye, z, x, y, z);
|
||||
|
||||
drawLine(x, y, z + ze, x + xe, y, z + ze);// 画立方体的上面边
|
||||
drawLine(x + xe, y, z + ze, x + xe, y + ye, z + ze);
|
||||
drawLine(x + xe, y + ye, z + ze, x, y + ye, z + ze);
|
||||
drawLine(x, y + ye, z + ze, x, y, z + ze);
|
||||
}
|
||||
drawLine(x, y, z, x, y, z + ze);// 画立方体的中间边
|
||||
drawLine(x + xe, y, z, x + xe, y, z + ze);
|
||||
drawLine(x + xe, y + ye, z, x + xe, y + ye, z + ze);
|
||||
drawLine(x, y + ye, z, x, y + ye, z + ze);
|
||||
|
||||
/*-
|
||||
画线,固定以top视角的角度,所以只需要从x1,y1画一条到x2,y2的直线
|
||||
绕 x 轴旋转 θ
|
||||
x, y.cosθ-zsinθ, y.sinθ+z.cosθ
|
||||
|
||||
绕 y 轴旋转 θ
|
||||
z.sinθ+x.cosθ, y, z.cosθ-x.sinθ
|
||||
|
||||
绕 z 轴旋转 θ
|
||||
x.cosθ-y.sinθ, x.sinθ+y.consθ, z
|
||||
-*/
|
||||
public void drawLine(float px1, float py1, float pz1, float px2, float py2, float pz2) {
|
||||
double x1 = px1 - Env.FROG_BRAIN_XSIZE / 2;
|
||||
double y1 = -py1 + Env.FROG_BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来
|
||||
double z1 = pz1 - Env.FROG_BRAIN_ZSIZE / 2;
|
||||
double x2 = px2 - Env.FROG_BRAIN_XSIZE / 2;
|
||||
double y2 = -py2 + Env.FROG_BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来
|
||||
double z2 = pz2 - Env.FROG_BRAIN_ZSIZE / 2;
|
||||
x1 = x1 * scale;
|
||||
y1 = y1 * scale;
|
||||
z1 = z1 * scale;
|
||||
x2 = x2 * scale;
|
||||
y2 = y2 * scale;
|
||||
z2 = z2 * scale;
|
||||
double x, y, z;
|
||||
y = y1 * cos(xAngle) - z1 * sin(xAngle);// 绕x轴转
|
||||
z = y1 * sin(xAngle) + z1 * cos(xAngle);
|
||||
y1 = y;
|
||||
z1 = z;
|
||||
drawLine(x, y, z + ze, x + xe, y, z + ze);// 画立方体的上面边
|
||||
drawLine(x + xe, y, z + ze, x + xe, y + ye, z + ze);
|
||||
drawLine(x + xe, y + ye, z + ze, x, y + ye, z + ze);
|
||||
drawLine(x, y + ye, z + ze, x, y, z + ze);
|
||||
}
|
||||
|
||||
x = z1 * sin(yAngle) + x1 * cos(yAngle);// 绕y轴转
|
||||
z = z1 * cos(yAngle) - x1 * sin(yAngle);
|
||||
x1 = x;
|
||||
z1 = z;
|
||||
|
||||
x = x1 * cos(zAngle) - y1 * sin(zAngle);// 绕z轴转
|
||||
y = x1 * sin(zAngle) + y1 * cos(zAngle);
|
||||
x1 = x;
|
||||
y1 = y;
|
||||
|
||||
y = y2 * cos(xAngle) - z2 * sin(xAngle);// 绕x轴转
|
||||
z = y2 * sin(xAngle) + z2 * cos(xAngle);
|
||||
y2 = y;
|
||||
z2 = z;
|
||||
|
||||
x = z2 * sin(yAngle) + x2 * cos(yAngle);// 绕y轴转
|
||||
z = z2 * cos(yAngle) - x2 * sin(yAngle);
|
||||
x2 = x;
|
||||
z2 = z;
|
||||
|
||||
x = x2 * cos(zAngle) - y2 * sin(zAngle);// 绕z轴转
|
||||
y = x2 * sin(zAngle) + y2 * cos(zAngle);
|
||||
x2 = x;
|
||||
y2 = y;
|
||||
|
||||
g.setColor(picColor);
|
||||
g.drawLine((int) round(x1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset, (int) round(y1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset, (int) round(x2) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset,
|
||||
(int) round(y2) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset);
|
||||
}
|
||||
|
||||
/** 画出cell的中心点 */
|
||||
public void drawCellCenter(float x, float y, float z, float diameter) {
|
||||
if (x > 0 && (x < xMask || y < yMask))
|
||||
public void drawCell(Cell c) {//画出细胞
|
||||
if (c == null)
|
||||
return;
|
||||
drawPoint(x + 0.5f, y + 0.5f, z + 0.5f, (int) Math.max(2, Math.round(scale * diameter)));
|
||||
drawPoint(c.x, c.y, c.z, scale);
|
||||
}
|
||||
|
||||
/** 画点,固定以top视角的角度,所以只需要在x1,y1位置画一个点 */
|
||||
public void drawPoint(float px1, float py1, float pz1, int diameter) {
|
||||
double x1 = px1 - Env.FROG_BRAIN_XSIZE / 2;
|
||||
double y1 = -py1 + Env.FROG_BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来
|
||||
double z1 = pz1 - Env.FROG_BRAIN_ZSIZE / 2;
|
||||
x1 = x1 * scale;
|
||||
y1 = y1 * scale;
|
||||
z1 = z1 * scale;
|
||||
double x, y, z;
|
||||
y = y1 * cos(xAngle) - z1 * sin(xAngle);// 绕x轴转
|
||||
z = y1 * sin(xAngle) + z1 * cos(xAngle);
|
||||
y1 = y;
|
||||
z1 = z;
|
||||
/*-
|
||||
画线,固定以top视角的角度,所以只需要从x1,y1画一条到x2,y2的直线
|
||||
绕 x 轴旋转 θ
|
||||
x, y.cosθ-zsinθ, y.sinθ+z.cosθ
|
||||
|
||||
绕 y 轴旋转 θ
|
||||
z.sinθ+x.cosθ, y, z.cosθ-x.sinθ
|
||||
|
||||
绕 z 轴旋转 θ
|
||||
x.cosθ-y.sinθ, x.sinθ+y.consθ, z
|
||||
-*/
|
||||
public void drawLine(float px1, float py1, float pz1, float px2, float py2, float pz2) {
|
||||
double x1 = px1 - Env.BRAIN_XSIZE / 2;
|
||||
double y1 = -py1 + Env.BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来
|
||||
double z1 = pz1 - Env.BRAIN_ZSIZE / 2;
|
||||
double x2 = px2 - Env.BRAIN_XSIZE / 2;
|
||||
double y2 = -py2 + Env.BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来
|
||||
double z2 = pz2 - Env.BRAIN_ZSIZE / 2;
|
||||
x1 = x1 * scale;
|
||||
y1 = y1 * scale;
|
||||
z1 = z1 * scale;
|
||||
x2 = x2 * scale;
|
||||
y2 = y2 * scale;
|
||||
z2 = z2 * scale;
|
||||
double x, y, z;
|
||||
y = y1 * cos(xAngle) - z1 * sin(xAngle);// 绕x轴转
|
||||
z = y1 * sin(xAngle) + z1 * cos(xAngle);
|
||||
y1 = y;
|
||||
z1 = z;
|
||||
|
||||
x = z1 * sin(yAngle) + x1 * cos(yAngle);// 绕y轴转
|
||||
z = z1 * cos(yAngle) - x1 * sin(yAngle);
|
||||
x1 = x;
|
||||
z1 = z;
|
||||
x = z1 * sin(yAngle) + x1 * cos(yAngle);// 绕y轴转
|
||||
// z = z1 * cos(yAngle) - x1 * sin(yAngle);
|
||||
x1 = x;
|
||||
// z1 = z;
|
||||
|
||||
x = x1 * cos(zAngle) - y1 * sin(zAngle);// 绕z轴转
|
||||
y = x1 * sin(zAngle) + y1 * cos(zAngle);
|
||||
x1 = x;
|
||||
y1 = y;
|
||||
x = x1 * cos(zAngle) - y1 * sin(zAngle);// 绕z轴转
|
||||
y = x1 * sin(zAngle) + y1 * cos(zAngle);
|
||||
x1 = x;
|
||||
y1 = y;
|
||||
|
||||
g.setColor(picColor);
|
||||
g.fillOval((int) round(x1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset, (int) round(y1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset - diameter / 2, diameter, diameter);
|
||||
}
|
||||
y = y2 * cos(xAngle) - z2 * sin(xAngle);// 绕x轴转
|
||||
z = y2 * sin(xAngle) + z2 * cos(xAngle);
|
||||
y2 = y;
|
||||
z2 = z;
|
||||
|
||||
private static Cuboid brain = new Cuboid(0, 0, 0, Env.FROG_BRAIN_XSIZE, Env.FROG_BRAIN_YSIZE, Env.FROG_BRAIN_ZSIZE);
|
||||
x = z2 * sin(yAngle) + x2 * cos(yAngle);// 绕y轴转
|
||||
// z = z2 * cos(yAngle) - x2 * sin(yAngle);
|
||||
x2 = x;
|
||||
// z2 = z;
|
||||
|
||||
public void drawBrainPicture(Frog f) {// 在这个方法里进行青蛙三维脑结构的绘制
|
||||
if (!f.alive)
|
||||
return;
|
||||
if (!Env.SHOW_FIRST_FROG_BRAIN)
|
||||
return;
|
||||
g.setColor(WHITE);// 先清空旧图
|
||||
g.fillRect(0, 0, brainDispWidth, brainDispWidth);
|
||||
g.setColor(BLACK); // 画边框
|
||||
g.drawRect(0, 0, brainDispWidth, brainDispWidth);
|
||||
setPicColor(BLACK);
|
||||
drawCuboid(brain);// 先把脑的框架画出来
|
||||
x = x2 * cos(zAngle) - y2 * sin(zAngle);// 绕z轴转
|
||||
y = x2 * sin(zAngle) + y2 * cos(zAngle);
|
||||
x2 = x;
|
||||
y2 = y;
|
||||
|
||||
setPicColor(RED);
|
||||
drawLine(0, 0, 0, 1, 0, 0);
|
||||
drawLine(0, 0, 0, 0, 1, 0);
|
||||
drawLine(0, 0, 0, 0, 0, 1);
|
||||
g.setColor(picColor);
|
||||
g.drawLine((int) round(x1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset,
|
||||
(int) round(y1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset,
|
||||
(int) round(x2) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset,
|
||||
(int) round(y2) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset);
|
||||
}
|
||||
|
||||
Graphics g2 = this.getGraphics(); // 这两行是将缓存中的图像写到屏幕上
|
||||
g2.drawImage(buffImg, 0, 0, this);
|
||||
/** 画点,固定以top视角的角度,所以只需要在x1,y1位置画一个点 */
|
||||
public void drawPoint(float px1, float py1, float pz1, float r) {
|
||||
double x1 = px1 - Env.BRAIN_XSIZE / 2;
|
||||
double y1 = -py1 + Env.BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来
|
||||
double z1 = pz1 - Env.BRAIN_ZSIZE / 2;
|
||||
x1 = x1 * scale;
|
||||
y1 = y1 * scale;
|
||||
z1 = z1 * scale;
|
||||
double x, y, z;
|
||||
y = y1 * cos(xAngle) - z1 * sin(xAngle);// 绕x轴转
|
||||
z = y1 * sin(xAngle) + z1 * cos(xAngle);
|
||||
y1 = y;
|
||||
z1 = z;
|
||||
|
||||
}
|
||||
x = z1 * sin(yAngle) + x1 * cos(yAngle);// 绕y轴转
|
||||
// z = z1 * cos(yAngle) - x1 * sin(yAngle);
|
||||
x1 = x;
|
||||
// z1 = z;
|
||||
|
||||
// getters & setters
|
||||
public float getScale() {
|
||||
return scale;
|
||||
}
|
||||
x = x1 * cos(zAngle) - y1 * sin(zAngle);// 绕z轴转
|
||||
y = x1 * sin(zAngle) + y1 * cos(zAngle);
|
||||
x1 = x;
|
||||
y1 = y;
|
||||
|
||||
public void setScale(float scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
g.setColor(picColor);
|
||||
g.fillOval(round((float) x1 + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset - r * scale * .5f),
|
||||
round((float) y1 + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset - r * scale * .5f), round(r * scale),
|
||||
round(r * scale));
|
||||
}
|
||||
|
||||
public float getxAngle() {
|
||||
return xAngle;
|
||||
}
|
||||
public void drawText(float px1, float py1, float pz1, String text) {
|
||||
drawText(px1, py1, pz1, text, 12);
|
||||
}
|
||||
|
||||
public void setxAngle(float xAngle) {
|
||||
this.xAngle = xAngle;
|
||||
}
|
||||
public void drawText(float px1, float py1, float pz1, String text, float textSize) {
|
||||
double x1 = px1 - Env.BRAIN_XSIZE / 2;
|
||||
double y1 = -py1 + Env.BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来
|
||||
double z1 = pz1 - Env.BRAIN_ZSIZE / 2;
|
||||
x1 = x1 * scale;
|
||||
y1 = y1 * scale;
|
||||
z1 = z1 * scale;
|
||||
double x, y, z;
|
||||
y = y1 * cos(xAngle) - z1 * sin(xAngle);// 绕x轴转
|
||||
z = y1 * sin(xAngle) + z1 * cos(xAngle);
|
||||
y1 = y;
|
||||
z1 = z;
|
||||
|
||||
public float getyAngle() {
|
||||
return yAngle;
|
||||
}
|
||||
x = z1 * sin(yAngle) + x1 * cos(yAngle);// 绕y轴转
|
||||
// z = z1 * cos(yAngle) - x1 * sin(yAngle);
|
||||
x1 = x;
|
||||
// z1 = z;
|
||||
|
||||
public void setyAngle(float yAngle) {
|
||||
this.yAngle = yAngle;
|
||||
}
|
||||
x = x1 * cos(zAngle) - y1 * sin(zAngle);// 绕z轴转
|
||||
y = x1 * sin(zAngle) + y1 * cos(zAngle);
|
||||
x1 = x;
|
||||
y1 = y;
|
||||
|
||||
public float getzAngle() {
|
||||
return zAngle;
|
||||
}
|
||||
g.setColor(picColor);
|
||||
g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, (int) round(textSize * scale)));
|
||||
g.drawString(text, (int) round(x1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset,
|
||||
(int) round(y1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset);
|
||||
|
||||
public void setzAngle(float zAngle) {
|
||||
this.zAngle = zAngle;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPicColor(Color color) {
|
||||
this.picColor = color;
|
||||
}
|
||||
private static Cuboid brain = new Cuboid(0, 0, 0, Env.BRAIN_XSIZE, Env.BRAIN_YSIZE, Env.BRAIN_ZSIZE);
|
||||
|
||||
public int getxOffset() {
|
||||
return xOffset;
|
||||
}
|
||||
public void drawBrainPicture() {// 在这个方法里进行动物的三维脑结构的绘制,蛇是青蛙的子类,所以也可以当参数传进来
|
||||
if (!Env.SHOW_FIRST_ANIMAL_BRAIN)
|
||||
return;
|
||||
Animal a = Env.getShowAnimal(); // 显示第一个青蛙或蛇
|
||||
if (a == null || !a.alive)
|
||||
return;
|
||||
g.setColor(WHITE);// 先清空旧图
|
||||
g.fillRect(0, 0, brainDispWidth, brainDispWidth);
|
||||
g.setColor(BLACK); // 画边框
|
||||
g.drawRect(0, 0, brainDispWidth, brainDispWidth);
|
||||
setPicColor(BLACK);
|
||||
drawCuboid(brain);// 先把脑的框架画出来
|
||||
drawText(100, 0, 0, "x");
|
||||
drawText(0, 100, 0, "y");
|
||||
drawText(0, 0, 100, "z");
|
||||
|
||||
public void setxOffset(int xOffset) {
|
||||
this.xOffset = xOffset;
|
||||
}
|
||||
setPicColor(RED);
|
||||
drawLine(0, 0, 0, 1, 0, 0);
|
||||
drawLine(0, 0, 0, 0, 1, 0);
|
||||
drawLine(0, 0, 0, 0, 0, 1);
|
||||
|
||||
public int getyOffset() {
|
||||
return yOffset;
|
||||
}
|
||||
for (Cell cell : a.cells) {
|
||||
if (cell != null && cell.energy > 20) {
|
||||
setPicColor(ColorUtils.grayColor(cell.energy));// 用灰度表示活跃度
|
||||
drawCell(cell);
|
||||
}
|
||||
}
|
||||
|
||||
public void setyOffset(int yOffset) {
|
||||
this.yOffset = yOffset;
|
||||
}
|
||||
g.setColor(Color.black);
|
||||
if (note != null) // 全局注释
|
||||
g.drawString(note, 30, 55);
|
||||
Graphics g2 = this.getGraphics();
|
||||
g2.drawImage(buffImg, 0, 0, this);// 利用缓存避免画面闪烁,这里输出缓存图片
|
||||
}
|
||||
|
||||
public static void setNote(String note) {
|
||||
Application.brainPic.note = note;
|
||||
}
|
||||
|
||||
// getters & setters
|
||||
public float getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public void setScale(float scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public float getxAngle() {
|
||||
return xAngle;
|
||||
}
|
||||
|
||||
public void setxAngle(float xAngle) {
|
||||
this.xAngle = xAngle;
|
||||
}
|
||||
|
||||
public float getyAngle() {
|
||||
return yAngle;
|
||||
}
|
||||
|
||||
public void setyAngle(float yAngle) {
|
||||
this.yAngle = yAngle;
|
||||
}
|
||||
|
||||
public float getzAngle() {
|
||||
return zAngle;
|
||||
}
|
||||
|
||||
public void setzAngle(float zAngle) {
|
||||
this.zAngle = zAngle;
|
||||
}
|
||||
|
||||
public void setPicColor(Color color) {
|
||||
this.picColor = color;
|
||||
}
|
||||
|
||||
public Color getPicColor() {
|
||||
return picColor;
|
||||
}
|
||||
|
||||
public int getxOffset() {
|
||||
return xOffset;
|
||||
}
|
||||
|
||||
public void setxOffset(int xOffset) {
|
||||
this.xOffset = xOffset;
|
||||
}
|
||||
|
||||
public int getyOffset() {
|
||||
return yOffset;
|
||||
}
|
||||
|
||||
public void setyOffset(int yOffset) {
|
||||
this.yOffset = yOffset;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,7 +28,10 @@ public class Cell {
|
||||
public int x;
|
||||
public int y;
|
||||
public int z;
|
||||
|
||||
|
||||
// energy of cell
|
||||
public float energy=0; // 每个细胞当前的能量值
|
||||
|
||||
public Cell(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
@ -10,52 +10,50 @@
|
||||
*/
|
||||
package com.gitee.drinkjava2.frog.brain;
|
||||
|
||||
import com.gitee.drinkjava2.frog.Frog;
|
||||
|
||||
/**
|
||||
* Cuboid represents a rectangular prism 3d zone in brain
|
||||
*
|
||||
* Cuboid是一个长方体,通常用来表示脑内器官的形状
|
||||
* Cuboid是一个长方体,通常用来表示脑内器官的形状。另一个功能类似的形装是Cone锥形体。
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 2.0.2
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class Cuboid implements Shape {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public int x;// x,y,z是长方体的左下角坐标
|
||||
public int y;
|
||||
public int z;
|
||||
public int xe;// xe,ye,ze分别是长方体三边长
|
||||
public int ye;
|
||||
public int ze;
|
||||
public float x;// x,y,z是长方体的左下角坐标
|
||||
public float y;
|
||||
public float z;
|
||||
public float xe;// xe,ye,ze分别是长方体三边长
|
||||
public float ye;
|
||||
public float ze;
|
||||
|
||||
public Cuboid() {
|
||||
// 空构造器不能省
|
||||
}
|
||||
public Cuboid() {
|
||||
// 空构造器不能省
|
||||
}
|
||||
|
||||
public Cuboid(int x, int y, int z, int xe, int ye, int ze) {// 用x,y,z,r来构造
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.xe = xe;
|
||||
this.ye = ye;
|
||||
this.ze = ze;
|
||||
}
|
||||
public Cuboid(float x, float y, float z, float xe, float ye, float ze) {// 用x,y,z,r来构造
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.xe = xe;
|
||||
this.ye = ye;
|
||||
this.ze = ze;
|
||||
}
|
||||
|
||||
public Cuboid(Cuboid c) {// 用另一个Cuboid来构造
|
||||
this.x = c.x;
|
||||
this.y = c.y;
|
||||
this.z = c.z;
|
||||
this.xe = c.xe;
|
||||
this.ye = c.ye;
|
||||
this.ze = c.ze;
|
||||
}
|
||||
public Cuboid(Cuboid c) {// 用另一个Cuboid来构造
|
||||
this.x = c.x;
|
||||
this.y = c.y;
|
||||
this.z = c.z;
|
||||
this.xe = c.xe;
|
||||
this.ye = c.ye;
|
||||
this.ze = c.ze;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOnBrainPicture(BrainPicture pic) {
|
||||
pic.drawCuboid(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOnBrainPicture(BrainPicture pic) {
|
||||
pic.drawCuboid(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ public class MouseAction implements MouseListener, MouseWheelListener, MouseMoti
|
||||
buttonPressed = 0;
|
||||
x = e.getPoint().x;
|
||||
y = e.getPoint().y;
|
||||
brainPic.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,12 +15,13 @@ import java.io.Serializable;
|
||||
/**
|
||||
* Shape represents a 3d zone in brain
|
||||
*
|
||||
* Shape用来表示脑内器官的形状,一个器官只能有一个shape
|
||||
* Shape用来表示脑内器官的形状,一个器官只能有一个shape,但是多个器官可以在脑内重合,也就是说一个Cell可以属于多个器官
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public interface Shape extends Serializable {
|
||||
/* Draw self on brain picture */
|
||||
public void drawOnBrainPicture(BrainPicture pic); // 把自己在脑图上画出来
|
||||
public void drawOnBrainPicture(BrainPicture pic); // 把自己在脑图上画出来
|
||||
|
||||
}
|
||||
|
@ -12,32 +12,42 @@ package com.gitee.drinkjava2.frog.egg;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.gitee.drinkjava2.frog.Frog;
|
||||
import com.gitee.drinkjava2.frog.Animal;
|
||||
import com.gitee.drinkjava2.frog.Env;
|
||||
import com.gitee.drinkjava2.frog.util.RandomUtils;
|
||||
|
||||
/**
|
||||
* Egg is the static structure description of frog, can save as file, to build a
|
||||
* frog, first need build a egg.<br/>
|
||||
*
|
||||
* 蛋存在的目的是为了以最小的字节数串行化存储Frog的基因树,它是Frog的生成算法描述,而不是Frog本身,这样一来Frog就不能"永生"了,因为每一个egg都不等同于
|
||||
* 它的母体, 而且每一次测试,除了少量固有反射外,大部分条件反射的建立都必须从头开始训练,类似于人类,无论人类社会有多聪明, 婴儿始终是一张白纸,除了需要花大量的时间从头学习。
|
||||
* 蛋存在的目的是为了以最小的字节数串行化存储Frog,它是Frog的生成算法描述,而不是Frog本身,这样一来Frog就不能"永生"了,因为每一个egg都不等同于
|
||||
* 它的母体, 而且每一次测试,大部分条件反射的建立都必须从头开始训练,类似于人类,无论人类社会有多聪明, 婴儿始终是一张白纸,需要花大量的时间从头学习。
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 1.0
|
||||
*/
|
||||
public class Egg implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final long serialVersionUID = 1L;
|
||||
public int x; // 蛋的x位置
|
||||
public int y; // 蛋的y位置
|
||||
|
||||
public Egg() {// 无中生有,创建一个蛋,先有蛋,后有蛙
|
||||
x = RandomUtils.nextInt(Env.ENV_WIDTH);
|
||||
y = RandomUtils.nextInt(Env.ENV_HEIGHT);
|
||||
}
|
||||
|
||||
public Egg() {// 无中生有,创建一个蛋,先有蛋,后有蛙
|
||||
/** Create egg from frog */
|
||||
public Egg(Animal a) { // 下蛋,每个器官会创建自已的副本或变异,可以是0或多个
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Create egg from frog */
|
||||
public Egg(Frog frog) { // 青蛙下蛋,每个青蛙的器官会创建自已的副本或变异,可以是0或多个
|
||||
|
||||
}
|
||||
|
||||
/** Create a egg by join 2 eggs */
|
||||
public Egg(Egg x, Egg y) { //模拟X、Y 染色体合并,两个蛋生成一个新的蛋
|
||||
}
|
||||
/**
|
||||
* Create a egg by join 2 eggs, x+y=zygote 模拟X、Y 染色体合并,两个蛋生成一个新的蛋
|
||||
*/
|
||||
public Egg(Egg a, Egg b) {
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,50 +19,52 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import com.gitee.drinkjava2.frog.Animal;
|
||||
import com.gitee.drinkjava2.frog.Application;
|
||||
import com.gitee.drinkjava2.frog.Env;
|
||||
import com.gitee.drinkjava2.frog.Frog;
|
||||
import com.gitee.drinkjava2.frog.util.FrogFileUtils;
|
||||
import com.gitee.drinkjava2.frog.util.LocalFileUtils;
|
||||
|
||||
/**
|
||||
* EggTool save eggs to disk
|
||||
* FrogEggTool save/load frog eggs to file
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 1.0
|
||||
*/
|
||||
public class EggTool {
|
||||
@SuppressWarnings("all")
|
||||
public class FrogEggTool {
|
||||
|
||||
/**
|
||||
* Frogs which have higher energy lay eggs
|
||||
*
|
||||
* 利用Java串行机制存盘。 能量多(也就是吃的更多)的Frog下蛋并存盘, 以进行下一轮测试,能量少的Frog被淘汰,没有下蛋的资格。
|
||||
* 用能量的多少来简化生存竟争模拟,也就是说生存是唯一的奖惩机制,每次下蛋数量固定为EGG_QTY个
|
||||
* 用能量的多少来简化生存竟争模拟,每次下蛋数量固定为EGG_QTY个
|
||||
*/
|
||||
public static void layEggs() {
|
||||
sortFrogsOrderByEnergyDesc();
|
||||
|
||||
sortFrogsOrderByEnergyDesc();
|
||||
Frog first = Env.frogs.get(0);
|
||||
Frog last = Env.frogs.get(Env.frogs.size() - 1);
|
||||
|
||||
try {
|
||||
Env.eggs.clear();
|
||||
for (int i = 0; i < Env.EGG_QTY; i++)
|
||||
Env.eggs.add(new Egg(Env.frogs.get(i)));
|
||||
FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser");
|
||||
Env.frog_eggs.clear();
|
||||
for (int i = 0; i < Env.FROG_EGG_QTY; i++)
|
||||
Env.frog_eggs.add(new Egg(Env.frogs.get(i)));
|
||||
FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "frog_eggs.ser");
|
||||
ObjectOutputStream so = new ObjectOutputStream(fo);
|
||||
so.writeObject(Env.eggs);
|
||||
so.writeObject(Env.frog_eggs);
|
||||
so.close();
|
||||
System.out.print("Fist frog energy=" + first.energy);
|
||||
System.out.println(", Last frog energy=" + last.energy);
|
||||
System.out.println("Saved " + Env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.ser'");
|
||||
System.out.println(
|
||||
"Saved " + Env.frog_eggs.size() + " eggs to file '" + Application.CLASSPATH + "frog_eggs.ser'");
|
||||
} catch (IOException e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void sortFrogsOrderByEnergyDesc() {// 按能量多少给青蛙排序
|
||||
Collections.sort(Env.frogs, new Comparator<Frog>() {
|
||||
public int compare(Frog a, Frog b) {
|
||||
Collections.sort(Env.frogs, new Comparator<Animal>() {
|
||||
public int compare(Animal a, Animal b) {
|
||||
if (a.energy > b.energy)
|
||||
return -1;
|
||||
else if (a.energy == b.energy)
|
||||
@ -73,33 +75,36 @@ public class EggTool {
|
||||
});
|
||||
}
|
||||
|
||||
public static void deleteEggs() {//是否每次测试要删除蛋是在Env.DELETE_EGGS设置
|
||||
System.out.println("Delete exist egg file: '" + Application.CLASSPATH + "eggs.ser'");
|
||||
FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.ser");
|
||||
public static void deleteEggs() {
|
||||
System.out.println("Delete exist egg file: '" + Application.CLASSPATH + "frog_eggs.ser'");
|
||||
LocalFileUtils.deleteFile(Application.CLASSPATH + "frog_eggs.ser");
|
||||
}
|
||||
|
||||
/**
|
||||
* 从磁盘读入一批Egg
|
||||
* 从磁盘读入一批frog Egg
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void loadEggs() {
|
||||
public static void loadFrogEggs() {
|
||||
boolean errorfound = false;
|
||||
try {
|
||||
FileInputStream eggsFile = new FileInputStream(Application.CLASSPATH + "eggs.ser");
|
||||
FileInputStream eggsFile = new FileInputStream(Application.CLASSPATH + "frog_eggs.ser");
|
||||
ObjectInputStream eggsInputStream = new ObjectInputStream(eggsFile);
|
||||
Env.eggs = (List<Egg>) eggsInputStream.readObject();
|
||||
System.out.println(
|
||||
"Loaded " + Env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.ser" + "'.\n");
|
||||
Env.frog_eggs = (List<Egg>) eggsInputStream.readObject();
|
||||
System.out.println("Loaded " + Env.frog_eggs.size() + " eggs from file '" + Application.CLASSPATH
|
||||
+ "frog_eggs.ser" + "'.\n");
|
||||
eggsInputStream.close();
|
||||
} catch (Exception e) {
|
||||
errorfound = true;
|
||||
}
|
||||
if (errorfound) {
|
||||
Env.eggs.clear();
|
||||
for (int j = 0; j < Env.EGG_QTY; j++)
|
||||
Env.eggs.add(new Egg());
|
||||
System.out.println("Fail to load egg file at path '" + Application.CLASSPATH + "', created "
|
||||
+ Env.eggs.size() + " eggs to do test.\n");
|
||||
Env.frog_eggs.clear();
|
||||
for (int j = 0; j < Env.FROG_EGG_QTY; j++) {
|
||||
Egg egg = new Egg();
|
||||
//TODO
|
||||
Env.frog_eggs.add(egg);
|
||||
}
|
||||
System.out.println("Fail to load frog egg file '" + Application.CLASSPATH + "frog_eggs.ser" + "', created "
|
||||
+ Env.frog_eggs.size() + " eggs to do test.");
|
||||
}
|
||||
|
||||
}
|
@ -22,5 +22,5 @@ public interface EnvObject {
|
||||
|
||||
public void destory();// 从Env中清除本身物体,只在每屏测试完成后调用一次
|
||||
|
||||
public void active(int screen); // 每个步长都会调用一次这个方法
|
||||
public void active(); // 每个步长都会调用一次这个方法
|
||||
}
|
||||
|
@ -13,36 +13,35 @@ package com.gitee.drinkjava2.frog.objects;
|
||||
import static com.gitee.drinkjava2.frog.Env.ENV_HEIGHT;
|
||||
import static com.gitee.drinkjava2.frog.Env.ENV_WIDTH;
|
||||
import static com.gitee.drinkjava2.frog.Env.FOOD_QTY;
|
||||
import static com.gitee.drinkjava2.frog.Env.bricks;
|
||||
|
||||
import com.gitee.drinkjava2.frog.Env;
|
||||
import com.gitee.drinkjava2.frog.util.RandomUtils;
|
||||
|
||||
/**
|
||||
* Food randomly scatter on Env
|
||||
* 生成食物(静态食物或苍蝇,苍蝇如果Env中FOOD_CAN_MOVE=true,会向四个方向移动)
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 1.0
|
||||
*/
|
||||
public class Food implements EnvObject {
|
||||
|
||||
@Override
|
||||
public void build() {
|
||||
for (int i = 0; i < FOOD_QTY; i++) // 生成食物
|
||||
bricks[RandomUtils.nextInt(ENV_WIDTH)][RandomUtils.nextInt(ENV_HEIGHT)] = Material.FOOD;
|
||||
}
|
||||
@Override
|
||||
public void build() {
|
||||
for (int i = 0; i < FOOD_QTY; i++) // 生成食物
|
||||
Env.setMaterial(RandomUtils.nextInt(ENV_WIDTH), RandomUtils.nextInt(ENV_HEIGHT), Material.FOOD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destory() {
|
||||
for (int i = 0; i < ENV_WIDTH; i++) {// 清除食物
|
||||
for (int j = 0; j < ENV_HEIGHT; j++)
|
||||
if (bricks[i][j] == Material.FOOD)
|
||||
bricks[i][j] = 0;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void destory() {
|
||||
for (int i = 0; i < ENV_WIDTH; i++) {// 清除食物
|
||||
for (int j = 0; j < ENV_HEIGHT; j++)
|
||||
Env.clearMaterial(i, j, Material.FOOD);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void active(int screen) {
|
||||
// Food do not have any active
|
||||
}
|
||||
@Override
|
||||
public void active() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,29 +13,38 @@ package com.gitee.drinkjava2.frog.objects;
|
||||
import java.awt.Color;
|
||||
|
||||
/**
|
||||
* Object means some thing in Env
|
||||
* Material store material types
|
||||
*
|
||||
* 用不同的数字常量代表虚拟环境中不同的组成材料,0为空,小于10的不可见,大于20的将杀死在同一位置出现的青蛙,例如砖头和青蛙不可以重叠出现在同一位置
|
||||
* 虚拟环境中每个点由一个int代表,多个材料可以同时出现在同一个点,每种材料用int中的一个bit位来表示,
|
||||
* 小于等于16384的位数用来标记青蛙序号,可利用Env.frogs.get(no-1)获取青蛙对象,其它各种材料用整数中其它位来表示
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 1.0
|
||||
*/
|
||||
public class Material {
|
||||
public static final byte NO = 0; // nothing
|
||||
public static final byte SEESAW_BASE = 1; // 1~9 is invisible to frog
|
||||
public class Material {// NOSONAR
|
||||
|
||||
public static final byte VISIBLE = 10; // if>=10 will visible to frog
|
||||
public static final byte FOOD = VISIBLE + 1;
|
||||
public static final byte SEESAW = VISIBLE + 2;
|
||||
public static final int FROG_TAG = 0b11111111111111; // 16383 小于等于16384的位数用来标记青蛙序号,可利用Env.frogs.get(no-1)快速定位青蛙
|
||||
|
||||
public static final byte KILLFROG = 20; // if>=20 will kill frog
|
||||
public static final byte BRICK = KILLFROG + 1;// brick will kill frog
|
||||
public static final byte TRAP = KILLFROG + 2; // trap will kill frog
|
||||
private static int material = FROG_TAG + 1; // 大于16384用来作为各种材料的标记
|
||||
|
||||
public static final int FOOD = nextMaterial();
|
||||
public static final int SNAKE = nextMaterial(); // 蛇的图形
|
||||
public static final int KILL_ANIMAL = nextMaterial(); // if>=KILLFROG will kill animal
|
||||
public static final int BRICK = nextMaterial();// brick will kill frog
|
||||
public static final int TRAP = nextMaterial(); // trap will kill frog
|
||||
|
||||
private static int nextMaterial() {// 每次将material左移1位
|
||||
material = material << 1;
|
||||
if (material < 0)
|
||||
throw new IllegalArgumentException("Material out of maximum range");
|
||||
return material;
|
||||
}
|
||||
|
||||
public static Color color(int material) {
|
||||
if ((material & TRAP) > 0)
|
||||
return Color.LIGHT_GRAY;
|
||||
else
|
||||
return Color.BLACK;
|
||||
}
|
||||
|
||||
public static Color color(byte material) {
|
||||
if (material == TRAP)
|
||||
return Color.LIGHT_GRAY;
|
||||
else
|
||||
return Color.BLACK;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public class ColorUtils {
|
||||
public static final int GRAY = 7;
|
||||
|
||||
private static final Color[] rainbow = new Color[] { Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.CYAN,
|
||||
Color.BLUE, Color.MAGENTA,Color.GRAY };
|
||||
Color.BLUE, Color.MAGENTA, Color.GRAY };
|
||||
|
||||
private static int nextColor = 0;
|
||||
|
||||
@ -51,20 +51,21 @@ public class ColorUtils {
|
||||
}
|
||||
|
||||
public static Color rainbowColor(float i) { // 根据数值大小范围,在8种彩虹色中取值
|
||||
if (i == 0)
|
||||
return Color.BLACK;
|
||||
if (i == 1)
|
||||
return Color.RED;
|
||||
if (i <= 3)
|
||||
return Color.ORANGE;
|
||||
if (i <= 10)
|
||||
return Color.YELLOW;
|
||||
if (i <= 20)
|
||||
return Color.GREEN;
|
||||
return Color.GRAY;
|
||||
if (i <= 30)
|
||||
return Color.BLACK;
|
||||
if (i <= 50)
|
||||
return Color.CYAN;
|
||||
if (i <= 100)
|
||||
return Color.BLUE;
|
||||
return Color.RED;
|
||||
return Color.MAGENTA;
|
||||
}
|
||||
|
||||
public static Color grayColor(float f) { // 根据数值大小范围0~1000,返回一个灰度色,越大越黑
|
||||
if (f > 1000)
|
||||
f = 1000;
|
||||
int i1 = 255 - (int) Math.round(f * .255);
|
||||
int i2 = 200 - (int) Math.round(f * .200);
|
||||
int i3 = 150 - (int) Math.round(f * .150);
|
||||
return new Color(i1, i2, i3);
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,14 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* File Utilities used in this project
|
||||
* Local File Utilities used in this project
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 1.0
|
||||
*/
|
||||
public class FrogFileUtils {
|
||||
public class LocalFileUtils {
|
||||
|
||||
private FrogFileUtils() {
|
||||
private LocalFileUtils() {
|
||||
// default constructor
|
||||
}
|
||||
|
@ -10,71 +10,83 @@
|
||||
*/
|
||||
package com.gitee.drinkjava2.frog.util;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Random Utilities used in this project
|
||||
*
|
||||
* 随机数工具,最理想情况下,随机算法和遗传算法是Frog项目中仅有的两个算法。
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 1.0
|
||||
*/
|
||||
public class RandomUtils {
|
||||
|
||||
private RandomUtils() {
|
||||
}
|
||||
private RandomUtils() {
|
||||
}
|
||||
|
||||
private static final Random rand = new Random();
|
||||
private static final Random rand = new Random();
|
||||
|
||||
public static int nextInt(int i) {//生成一个整数
|
||||
return rand.nextInt(i);
|
||||
}
|
||||
public static int nextInt(int i) {
|
||||
return rand.nextInt(i);
|
||||
}
|
||||
|
||||
public static float nextFloat() {//生成一个实数
|
||||
return rand.nextFloat();
|
||||
}
|
||||
public static float nextFloat() {
|
||||
return rand.nextFloat();
|
||||
}
|
||||
|
||||
public static boolean percent(float percent) {// 有百分之percent的机率为true
|
||||
return rand.nextInt(100) < percent;
|
||||
}
|
||||
public static boolean percent(float percent) {// 有百分这percent的机率为true
|
||||
return rand.nextFloat() * 100 < percent;
|
||||
}
|
||||
|
||||
|
||||
public static int vary(int v, int percet) {//给定一个整数,有百分之percent的机率变异,变异范围由vary方法决定
|
||||
if (percent(percet))
|
||||
return vary(v);
|
||||
return v;
|
||||
}
|
||||
public static int vary(int v, int percet) {
|
||||
if (percent(percet))
|
||||
return vary(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
public static int vary(int v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异
|
||||
if (percent(40))
|
||||
v *= .98 + .04 * nextFloat(); // 0.98~1.02
|
||||
if (percent(10))
|
||||
v *= .95 + .103 * nextFloat(); // 0.95~1.053
|
||||
else if (percent(5))
|
||||
v *= .08 + 0.45 * nextFloat(); // 0.8~1.25
|
||||
else if (percent(1))
|
||||
v *= .05 + 1.5 * nextFloat(); // 0.5~2
|
||||
return v;
|
||||
}
|
||||
public static int vary(int v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异
|
||||
if (percent(40))
|
||||
v += v * .04 * (nextFloat() - 0.5); // v=v+-.04
|
||||
if (percent(10))
|
||||
v += v * .103 * (nextFloat() - 0.5); // v=v+-0.1
|
||||
else if (percent(5))
|
||||
v += v * 1 * (nextFloat() - 0.5); // v=v+-0.4
|
||||
else if (percent(2))
|
||||
v += v * 4 * (nextFloat() - 0.5); // v=v+-2
|
||||
else if (percent(1f))
|
||||
v += v * 8 * (nextFloat() - 0.5); // v=v+-6
|
||||
return v;
|
||||
}
|
||||
|
||||
public static float vary(float v, int percet) {//给定一个实数,有百分之percent的机率变异,变异范围由vary方法决定
|
||||
if (percent(percet))
|
||||
return vary(v);
|
||||
return v;
|
||||
}
|
||||
public static float vary(float v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异
|
||||
if (percent(40))
|
||||
v += v * .04 * (nextFloat() - 0.5); // v=v+-.04
|
||||
if (percent(10))
|
||||
v += v * .103 * (nextFloat() - 0.5); // v=v+-0.1
|
||||
else if (percent(5))
|
||||
v += v * 1 * (nextFloat() - 0.5); // v=v+-0.4
|
||||
else if (percent(2))
|
||||
v += v * 4 * (nextFloat() - 0.5); // v=v+-2
|
||||
else if (percent(1f))
|
||||
v += v * 8 * (nextFloat() - 0.5); // v=v+-6
|
||||
return v;
|
||||
}
|
||||
|
||||
public static float vary(float v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异
|
||||
if (percent(40))
|
||||
v *= .98 + .04 * nextFloat(); // 0.98~1.02
|
||||
if (percent(10))
|
||||
v *= .95 + .103 * nextFloat(); // 0.95~1.053
|
||||
else if (percent(5))
|
||||
v *= .08 + 0.45 * nextFloat(); // 0.8~1.25
|
||||
else if (percent(1))
|
||||
v *= .05 + 1.5 * nextFloat(); // 0.5~2
|
||||
return v;
|
||||
}
|
||||
|
||||
public static int varyInLimit(int v, int from, int to) {// 让返回值在from和to之间随机变异
|
||||
int i = vary(v);
|
||||
if (i < from)
|
||||
i = from;
|
||||
if (i > to)
|
||||
i = to;
|
||||
return i;
|
||||
}
|
||||
|
||||
public static float varyInLimit(float v, float from, float to) {// 让返回值在from和to之间随机变异
|
||||
float i = vary(v);
|
||||
if (i < from)
|
||||
i = from;
|
||||
if (i > to)
|
||||
i = to;
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ public class Application {
|
||||
public static final String CLASSPATH;
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -20,7 +20,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -22,7 +22,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -22,7 +22,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -26,7 +26,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -22,7 +22,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -21,7 +21,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -29,7 +29,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -29,7 +29,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -29,7 +29,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -29,7 +29,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
@ -29,7 +29,7 @@ public class Application {
|
||||
|
||||
static {
|
||||
String classpath = new File("").getAbsolutePath();
|
||||
int i = classpath.indexOf("\\frog\\");
|
||||
int i = classpath.lastIndexOf("\\frog\\");
|
||||
if (i > 0)
|
||||
CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user