翁恺老师 狐狸和兔子练习

习题描述

狐狸、兔子都有年龄;
到达一定年龄上限会自然死亡;
狐狸随机吃掉周围一只兔子;
狐狸、兔子可以随机生一只小的放在旁边格子;
如果不吃不生,狐狸、兔子可以随机向旁边格子移一步会随机吃掉

Animal抽象类

animal抽象类是fox,rabbit的父类:
属性:ageLimit(生存时间),breedableAge(生育年龄),age(现年龄),isAlive;
方法:
**构造方法:**生存时间、生育年龄;
**简单方法:**获取年龄、年龄百分比、成长(到年龄死亡)、见耶稣、确定没死、确定能生、寿命增长的方法;
**抽象方法:**生育;
移动方法:
传入周围空cell坐标,返回其中一个空cell坐标。
**Animal返回值方法:**进食

package animal;

import java.util.ArrayList;

import field.Location;

public abstract class Animal{
	private int ageLimit;
	private int breedableAge;
	private int age;
	private boolean isAlive = true;
	
	public Animal(int ageLimit, int breedableAge){
		this.ageLimit = ageLimit;
		this.breedableAge = breedableAge;
	}
	
	protected int getAge(){
		return age;
	}
	
	protected double getAgePercent(){
		return (double)age/ageLimit;
	}
	
	public abstract Animal breed();
	
	public void grow(){
		age++;
		if(age > ageLimit){
			die();
		}
	}

	private void die() {
		isAlive = false;
	}
	
	public boolean isAlive(){
		return isAlive;
	}
	
	public boolean isBreedable(){
		return age >breedableAge;
	}
	
	public Location move(Location[] freeAdj){
		Location ret = null;
		if( freeAdj.length > 0 && Math.random() < 0.02 ){
			ret = freeAdj[(int)(Math.random()*freeAdj.length)];
		}
		return ret;
	}
	
	@Override
	public String toString(){
		return " "+age+":"+(isAlive?"live":"dead");
	}
	
	public Animal feed(ArrayList<Animal> neighbour){
		return null;
	}
	
	protected void longerlife( int addage ){
		ageLimit += addage;
	}
}

Fox类:继承animal,cell

构造方法:生存时间20,生育年龄4;
重写抽象方法:animal的 生育、进食;
生育:5%概率生育,返回 Animal;
进食:返回cell(传入附近兔子数组),被吃掉概率0.2,可通过cell是否为null判断给否被吃掉;
重写接口cell方法:draw,传入cell 图,坐标,大小;

package animal;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;

import cell.Cell;

public class Fox extends Animal implements Cell{
	public Fox(){
		super(20,4);     //最大年龄,生育年龄
	}
	
	@Override
	public void draw( Graphics g, int x, int y, int size ){
		int alpha = (int)((1-getAgePercent())*255);
		g.setColor(new Color(0,0,0,alpha));
		g.fillRect(x, y, size, size);
	}
	
	@Override
	public Animal breed() {
		Animal ret = null;
		if( isBreedable() && Math.random() < 0.05 ){   //5%的几率breed
			ret = new Fox();
		}
		return ret;
	}
	
	@Override
	public String toString(){
		return "Fox:"+super.toString();
	}
	
	@Override
	public Animal feed(ArrayList<Animal> neighbour){    //返回被吃的兔子
		Animal ret = null;
		if( Math.random() < 0.2 ){
			ret = neighbour.get((int)(Math.random()*neighbour.size()));
			longerlife(2);
		}
		return ret;
	}
}

Rabbit类:继承animal,cell

构造方法:生存时间10,生育年龄2;
重写抽象方法:animal的 生育、进食;
生育:12%概率生育,返回 Animal;
重写接口cell方法:draw,传入cell 图,坐标,大小;

package animal;

import java.awt.Color;
import java.awt.Graphics;

import cell.Cell;

public class Rabbit extends Animal implements Cell{

	public Rabbit() {
		super(10, 2);
	}

	@Override
	public void draw(Graphics g, int x, int y, int size) {
		int alpha = (int)((1-getAgePercent())*255);
		g.setColor(new Color(255,0,0,alpha));
		g.fillRect(x, y, size, size);
	}

	@Override
	public Animal breed() {
		Animal ret = null;
		if( isBreedable() && Math.random() < 0.12 ){   //12%的几率breed
			ret = new Rabbit();
		}
		return ret;
	}
	
	@Override
	public String toString(){
		return "Rabbit:"+super.toString();
	}
}

Cell接口:

package cell;

import java.awt.Graphics;

public interface Cell {
	void draw ( Graphics g, int x, int y, int size );
}

Location类:

用于定位,返回所要cell位置

package field;

public class Location{
	private int row;
	private int col;
	
	public Location( int row, int col ){
		this.col = col;
		this.row = row;
	}
	
	public int getRow(){
		return row;
	}
	public int getCol() {
		return col;
	}
}

Field类:

属性:长、宽、cell二维数组;
构造方法:生成指定大小cell二维数组;
简单方法:获取长、宽、指定cell;
获取周围细胞方法:输入现在细胞坐标,返回周围细胞数组;
获取周围空cell数组:输入现在细胞坐标,返回空cell坐标数组;
在周围空cell里放置一个cell:
输入现在细胞坐标 和 放入的cell;返回是否成功放入cell进field;
根据坐标删除cell:输入坐标,删除cell(置field数组指空),返回删除;
根据细胞删除cell:输入细胞,细胞删除(此处可以优化);
clear方法:删除所有细胞;
move方法:细胞移动;

package field;

import java.util.ArrayList;

import cell.Cell;

public class Field {
//  这段代码没用到过
//	private static final Location[] adjacent = {
//			new Location(-1,-1),new Location(-1,0),new Location(-1,1),
//			new Location(0,-1) ,new Location(0,0) ,new Location(0,-1), 
//			new Location(1,-1) ,new Location(1,-1),new Location(1,-1),
//	};
	private int width;
	private int height;
	private Cell[][] field;
	
	public Field(int width, int height){
		this.height = height;
		this.width = width;
		field = new Cell[height][width];
	}
	
	public int getWidth(){ return width; }
	public int getHeight(){ return height; }
	
	public Cell get(int row, int col){
		return field[row][col];
	}
	
	public Cell[] getNeighbour(int row, int col) {
		ArrayList<Cell> list = new ArrayList<Cell>();
		for( int i = -1; i<2; i++ ) {
			for( int j = -1; j<2; j++ ) {
				int r = row+i;
				int c = col+j;
				if( r>-1 && r<height && c>-1 && c<width && !(r == row && c == col)) {
					list.add(field[r][c]);
				}
			}
		}
		return list.toArray(new Cell[list.size()]);
	}
	 //列出周围空cell的数组
	public Location[] getFreeNeighbour(int row, int col) {   
		ArrayList<Location> list = new ArrayList<Location>();
		for( int i = -1; i<2; i++ ) {
			for( int j = -1; j<2; j++ ) {
				int r = row+i;
				int c = col+j;
				if( r>-1 && r<height && c>-1 && c<width && field[r][c] == null ) {
					list.add(new Location(r, c));
				}
			}
		}
		return list.toArray(new Location[list.size()]);
	}
	
	public boolean placeRandomAdj( int row, int col, Cell cell ){   
		boolean ret = false;
		Location[] FreeAdj = getFreeNeighbour(row, col);
		if( FreeAdj.length > 0 ){
			int idx = (int)(Math.random()*FreeAdj.length);
			field[FreeAdj[idx].getRow()][FreeAdj[idx].getCol()] = cell;
			ret = true;
		}
		return ret;
	}
	
	public Cell remove( int row, int col ){
		Cell ret = field[row][col];
		field[row][col] = null;
		return ret;
	}
	
	public void remove( Cell cell ){
		for( int row = 0; row < height; row++ ){
			for( int col = 0; col <width; col++ ){
				if( field[row][col] == cell ){
					field[row][col] = null;
					break;
				}
			}
		}
	}
	
	public void clear(){
		for( int i = 0; i < height; i++){
			for( int j = 0; j < width; j++){
				field[i][j] = null;
			}
		}
	}
	
	public void move(int row, int col, Location loc){
		field[loc.getRow()][loc.getCol()] = field[row][col];
		remove(row,col);
	}

	public Cell place(int row, int col, Cell c) {
		Cell ret = field[row][col];
		field[row][col] = c;
		return ret;
	}
}

view类:

继承自JPanel面板
重写的方法:paint,设置刚好的尺寸;

package field;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;

import cell.Cell;

public class View extends JPanel{
	private static final long serialVersionUID = -2417015700213488315L;
	private static final int GRID_SIZE = 16;
	private Field thefield;
	
	public View (Field field){
		thefield = field;
	}
	
	@Override
	public void paint( Graphics g ){
		super.paint(g);
		g.setColor(Color.gray);
		for( int row = 0; row < thefield.getHeight(); row++ ){
			g.drawLine(0, row*GRID_SIZE, thefield.getWidth()*GRID_SIZE, row*GRID_SIZE);
		}
		for( int col = 0; col < thefield.getHeight(); col++ ){
			g.drawLine(col*GRID_SIZE, 0, col*GRID_SIZE, thefield.getHeight()*GRID_SIZE);
		}
		for( int row = 0; row < thefield.getHeight(); row++){
			for( int col = 0; col < thefield.getWidth(); col++){
				Cell cell = thefield.get(row, col);
				if( cell != null ){
					cell.draw( g, col*GRID_SIZE, row*GRID_SIZE, GRID_SIZE);
				}
			}
		}
	}
	
	@Override
	public Dimension getPreferredSize(){
		return new Dimension(thefield.getWidth()*GRID_SIZE+1, thefield.getHeight()*GRID_SIZE+1);
	}
}

FoxAndRabbit程序执行入口:

主要思想:两层for循环,挨个cell执行移动、进食、生育;每次循环结束后repaint view;

package FoxAndRabbit;

import field.Field;
import field.View;
import field.Location;

import java.util.ArrayList;

import javax.swing.JFrame;

import animal.Fox;
import animal.Rabbit;
import animal.Animal;
import cell.Cell;

public class FoxAndRabbit{
	private Field thefield;
	private View theview;
	
	public FoxAndRabbit( int size ){
		thefield = new Field(size, size);
		for( int row = 0; row <thefield.getHeight(); row++ ){
			for( int col = 0; col < thefield.getWidth(); col++ ){
				double probability = Math.random();
				if( probability <0.05 ){
					thefield.place( row, col, new Fox());
				}else if( probability < 0.15 ){
					thefield.place( row, col, new Rabbit());
				}
			}
		}
		theview = new View(thefield);
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);
		frame.setTitle("FoxAndRabbit");
		frame.add(theview);
		frame.pack();
		frame.setVisible(true);
	}
	
	public void step(){
		for( int row = 0; row < thefield.getHeight(); row++ ){
			for( int col = 0; col < thefield.getWidth(); col++ ){
				Cell cell = thefield.get(row, col);
				if( cell != null ){
					Animal animal = (Animal)cell;
					animal.grow();
					if( animal.isAlive()){
						//move
						Location loc = animal.move(thefield.getFreeNeighbour(row, col));
						if( loc != null ){
							thefield.move(row, col, loc);
						}
						//eat   animal.eat(thefield);
						if( animal instanceof Fox){
							Cell[] neighbour = thefield.getNeighbour(row, col);
							ArrayList<Animal> listRabbit = new ArrayList<Animal>();
							for( Cell an : neighbour ){
								if( an instanceof Rabbit ){
									listRabbit.add( (Rabbit)an );
								}
							}
							if( !listRabbit.isEmpty() ){
								Animal fed = animal.feed(listRabbit);
								if( fed != null ){
									thefield.remove((Cell)fed);
								}
							}
						}
						//breed
						Animal baby = animal.breed();
						if( baby != null ){
							thefield.placeRandomAdj(row, col, (Cell)baby);
						}
					}else{
						thefield.remove(row, col);
					}
				}
			}
		}	
	}
	
	public void start( int steps ){
		for( int i = 0; i < steps; i++){
			step();
			theview.repaint();
			try{
				Thread.sleep(200);
			}catch (InterruptedException e){
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		FoxAndRabbit fnr = new FoxAndRabbit(30);
		fnr.start(10);
	}
}
  • 16
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值