码迷,mamicode.com
首页 > 编程语言 > 详细

80.JAVA编程思想——复杂性理论

时间:2016-05-13 02:18:36      阅读:325      评论:0      收藏:0      [点我收藏+]

标签:

80.JAVA编程思想——复杂性理论

下面要介绍的程序的前身是由Larry O‘Brien 原创的一些代码,并以由Craig Reynolds 于1986 年编制的“Boids”程序为基础,当时是为了演示复杂性理论的一个特殊问题,名为“凸显”(Emergence)。这儿要达到的目标是通过为每种动物都规定少许简单的规则,从而逼真地再现动物的群聚行为。每个动物都能看到看到整个环境以及环境中的其他动物,但它只与一系列附近的“群聚伙伴”打交道。动物的移动基于三个简单的引导行为:

(1) 分隔:避免本地群聚伙伴过于拥挤。

(2) 方向:遵从本地群聚伙伴的普遍方向。

(3) 聚合:朝本地群聚伙伴组的中心移动。

更复杂的模型甚至可以包括障碍物的因素,动物能预知和避免与障碍冲突的能力,所以它们能围绕环境中的固定物体自由活动。除此以外,动物也可能有自己的特殊目标,这也许会造成群体按特定的路径前进。为简化讨论,避免障碍以及目标搜寻的因素并未包括到这里建立的模型中。尽管计算机本身比较简陋,而且采用的规则也相当简单,但结果看起来是真实的。也就是说,相当逼真的行为从这个简单的模型中“凸显”出来了。

程序以合成到一起的应用程序/程序片的形式提供:

1     代码

import java.awt.*;

import java.awt.event.*;

import java.applet.*;

import java.util.*;

class Beast {

    int x, y, // Screen position

            currentSpeed; // Pixels per second

    float currentDirection;// Radians

    Color color; // Fill color

    FieldOBeasts field; // Where theBeast roams

    static finalintGSIZE= 10; // Graphic size

 

    public Beast(FieldOBeasts f, intx, int y, float cD, int cS, Color c) {

        field = f;

        this.x = x;

        this.y = y;

        currentDirection = cD;

        currentSpeed = cS;

        color = c;

    }

 

    public voidstep() {

        // You move based on those within your sight:

        Vector seen = field.beastListInSector(this);

        // If you‘re not out in front

        if (seen.size() > 0) {

            // Gather data on those you see

            int totalSpeed = 0;

            float totalBearing = 0.0f;

            float distanceToNearest = 100000.0f;

            Beast nearestBeast = (Beast) seen.elementAt(0);

            Enumeration e = seen.elements();

            while (e.hasMoreElements()) {

                Beast aBeast = (Beast) e.nextElement();

                totalSpeed += aBeast.currentSpeed;

                float bearing = aBeast.bearingFromPointAlongAxis(x, y, currentDirection);

                totalBearing += bearing;

                float distanceToBeast = aBeast.distanceFromPoint(x, y);

                if (distanceToBeast < distanceToNearest){

                    nearestBeast = aBeast;

                    distanceToNearest = distanceToBeast;

                }

            }

            // Rule 1: Match average speed of those

            // in the list:

            currentSpeed = totalSpeed / seen.size();

            // Rule 2: Move towards the perceived

            // center of gravity of the herd:

            currentDirection = totalBearing / seen.size();

            // Rule 3: Maintain a minimum distance

            // from those around you:

            if (distanceToNearest <= field.minimumDistance){

                currentDirection = nearestBeast.currentDirection;

                currentSpeed = nearestBeast.currentSpeed;

                if (currentSpeed > field.maxSpeed){

                    currentSpeed = field.maxSpeed;

                }

            }

        } else { // You are infront, so slow down

            currentSpeed = (int) (currentSpeed * field.decayRate);

        }

        // Make the beast move:

        x += (int) (Math.cos(currentDirection) * currentSpeed);

        y += (int) (Math.sin(currentDirection) * currentSpeed);

        x %= field.xExtent;

        y %= field.yExtent;

        if (x < 0)

            x += field.xExtent;

        if (y < 0)

            y += field.yExtent;

    }

 

    public floatbearingFromPointAlongAxis(int originX,intoriginY,floataxis){

        // Returns bearing angle of the current Beast

        // in the world coordiante system

        try {

            double bearingInRadians = Math.atan((this.y - originY) / (this.x - originX));

            // Inverse tan has two solutions, so you

            // have to correct for other quarters:

            if (x < originX){

                if (y < originY){

                    bearingInRadians += -(float) Math.PI;

                } else {

                    bearingInRadians = (float) Math.PI - bearingInRadians;

                }

            }

            // Just subtract the axis (in radians):

            return (float) (axis - bearingInRadians);

        } catch (ArithmeticException aE) {

            // Divide by 0 error possible on this

            if (x > originX){

                return 0;

            } else

                return (float) Math.PI;

        }

    }

 

    public floatdistanceFromPoint(int x1,inty1){

        return (float) Math.sqrt(Math.pow(x1 - x, 2) + Math.pow(y1 - y, 2));

    }

 

    public Point position() {

        return new Point(x, y);

    }

 

    // Beasts knowhow to draw themselves:

    public voiddraw(Graphics g) {

        g.setColor(color);

        int directionInDegrees = (int)((currentDirection* 360) / (2 * Math.PI));

        int startAngle = directionInDegrees- FieldOBeasts.halfFieldOfView;

        int endAngle = 90;

        g.fillArc(x, y, GSIZE,GSIZE,startAngle,endAngle);

    }

}

 

public class FieldOBeasts extends Applet implements Runnable {

    private Vector beasts;

    static floatfieldOfView= (float)(Math.PI/ 4), // In radians

            // Deceleration % per second:

            decayRate = 1.0f, minimumDistance= 10f; // In pixels

    static inthalfFieldOfView = (int)((fieldOfView* 360) / (2 * Math.PI)), xExtent= 0, yExtent= 0, numBeasts= 50,

            maxSpeed = 20; // Pixels/second

    boolean uniqueColors= true;

    Thread thisThread;

    int delay= 25;

 

    public voidinit() {

        if (xExtent == 0 && yExtent == 0) {

            xExtent = Integer.parseInt(getParameter("xExtent"));

            yExtent = Integer.parseInt(getParameter("yExtent"));

        }

        beasts = makeBeastVector(numBeasts, uniqueColors);

        // Now start the beasts a-rovin‘:

        thisThread = new Thread(this);

        thisThread.start();

    }

 

    public voidrun() {

        while (true) {

            for (int i = 0; i < beasts.size(); i++) {

                Beast b = (Beast) beasts.elementAt(i);

                b.step();

            }

            try {

                thisThread.sleep(delay);

            } catch (InterruptedException ex) {

            }

            repaint(); // Otherwise it won‘t update

        }

    }

 

    Vector makeBeastVector(int quantity, boolean uniqueColors) {

        Vector newBeasts = new Vector();

        Random generator = new Random();

        // Used only if uniqueColors is on:

        double cubeRootOfBeastNumber = Math.pow((double) numBeasts, 1.0 / 3.0);

        float colorCubeStepSize = (float) (1.0 / cubeRootOfBeastNumber);

        float r = 0.0f;

        float g = 0.0f;

        float b = 0.0f;

        for (int i = 0; i < quantity; i++) {

            int x = (int)(generator.nextFloat()* xExtent);

            if (x > xExtent - Beast.GSIZE)

                x -= Beast.GSIZE;

            int y = (int)(generator.nextFloat()* yExtent);

            if (y > yExtent - Beast.GSIZE)

                y -= Beast.GSIZE;

            float direction = (float) (generator.nextFloat() * 2 * Math.PI);

            int speed = (int)(generator.nextFloat()* (float)maxSpeed);

            if (uniqueColors) {

                r += colorCubeStepSize;

                if (r > 1.0) {

                    r -= 1.0f;

                    g += colorCubeStepSize;

                    if (g > 1.0) {

                        g -= 1.0f;

                        b += colorCubeStepSize;

                        if (b > 1.0)

                            b -= 1.0f;

                    }

                }

            }

            newBeasts.addElement(new Beast(this, x, y, direction,speed,newColor(r,g,b)));

        }

        return newBeasts;

    }

 

    public Vector beastListInSector(Beast viewer) {

        Vector output = new Vector();

        Enumeration e = beasts.elements();

        Beast aBeast = (Beast) beasts.elementAt(0);

        int counter = 0;

        while (e.hasMoreElements()) {

            aBeast = (Beast) e.nextElement();

            if (aBeast != viewer){

                Point p = aBeast.position();

                Point v = viewer.position();

                float bearing = aBeast.bearingFromPointAlongAxis(v.x, v.y, viewer.currentDirection);

                if (Math.abs(bearing) < fieldOfView / 2)

                    output.addElement(aBeast);

            }

        }

        return output;

    }

 

    public voidpaint(Graphics g){

        Enumeration e = beasts.elements();

        while (e.hasMoreElements()) {

            ((Beast) e.nextElement()).draw(g);

        }

    }

 

    public staticvoidmain(String[] args){

        FieldOBeasts field = new FieldOBeasts();

        field.xExtent = 640;

        field.yExtent = 480;

        Frame frame = new Frame("Field ‘O Beasts");

        // Optionally use a command-line argument

        // for the sleep time:

        if (args.length>= 1)

            field.delay = Integer.parseInt(args[0]);

        frame.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {

                System.exit(0);

            }

        });

        frame.add(field, BorderLayout.CENTER);

        frame.setSize(640, 480);

        field.init();

        field.start();

        frame.setVisible(true);

    }

} /// :~

尽管这并非对Craig Reynold 的“Boids”例子中的行为完美重现,但它却展现出了自己独有的迷人之外。通过对数字进行调整,即可进行全面的修改。

2     总结

通过学习,大家知道运用Java 可做到一些较复杂的事情。通过这些例子亦可看出,尽管Java 必定有自己的局限,但受那些局限影响的主要是性能(比如写好文字处理程序后,会发现C++的版本要快得多——这部分是由于IO 库做得不完善造成的;而在你读到本书的时候,情况也许已发生了变化。但Java 的局限也仅此而已,它在语言表达方面的能力是无以伦比的。利用Java,几乎可以表达出我们想得到的任何事情。而与此同时,Java 在表达的方便性和易读性上,也做足了功夫。所以在使用Java 时,一般不会陷入其他语言常见的那种复杂境地。使用那些语言时,会感觉它们象一个爱唠叨的老太婆,哪有Java 那样清纯、简练!而且通过Java 1.2 的JFC/Swing 库,AWT 的表达能力和易用性甚至又得到了进一步的增强。

80.JAVA编程思想——复杂性理论

标签:

原文地址:http://blog.csdn.net/notbaron/article/details/51347900

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!