Cleanup core\bottom_up and fix root frog path bug

This commit is contained in:
yong 2021-09-09 23:54:46 -06:00
parent 278918bc59
commit efae3b4ca7
29 changed files with 949 additions and 769 deletions

View File

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

View File

@ -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();
}

View File

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

View File

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

View File

@ -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,rx键盘命令
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,rx键盘命令
@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;
}
}

View File

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

View File

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

View File

@ -34,6 +34,7 @@ public class MouseAction implements MouseListener, MouseWheelListener, MouseMoti
buttonPressed = 0;
x = e.getPoint().x;
y = e.getPoint().y;
brainPic.requestFocus();
}
@Override

View File

@ -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); // 把自己在脑图上画出来
}

View File

@ -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) { //模拟XY 染色体合并两个蛋生成一个新的蛋
}
/**
* Create a egg by join 2 eggs, x+y=zygote 模拟XY 染色体合并两个蛋生成一个新的蛋
*/
public Egg(Egg a, Egg b) {
x = a.x;
y = a.y;
}
}

View File

@ -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.");
}
}

View File

@ -22,5 +22,5 @@ public interface EnvObject {
public void destory();// 从Env中清除本身物体只在每屏测试完成后调用一次
public void active(int screen); // 每个步长都会调用一次这个方法
public void active(); // 每个步长都会调用一次这个方法
}

View File

@ -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() {
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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