友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
富士康小说网 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

Java编程思想第4版[中文版](PDF格式)-第110部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!



    applet。start();  

    aFrame。setVisible(true);  

  }  

}  

  

class StripQualifiers {  

  private StreamTokenizer st;  

  public StripQualifiers(String qualified) {  

      st = new StreamTokenizer(  

        new StringReader(qualified));  

      st。ordinaryChar(' ');  

  }  

  public String getNext() {  

    String s = null;  

    try {  

      if(st。nextToken() !=  

            StreamTokenizer。TT_EOF) {  

        switch(st。ttype) {  

          case StreamTokenizer。TT_EOL:  

            s = null;  

            break;  

          case StreamTokenizer。TT_NUMBER:  

            s = Double。toString(st。nval);  

            break;  

          case StreamTokenizer。TT_WORD:  

            s = new String(st。sval);  

            break;  

          default: // single character in ttype  

            s = String。valueOf((char)st。ttype);  

        }  

      }  

    } catch(IOException e) {  

      System。out。println(e);  

    }  

    return s;  

  }  

  public static String strip(String qualified) {  

    StripQualifiers sq =   

      new StripQualifiers(qualified);  

    String s = 〃〃; si;  

    while((si = sq。getNext()) != null) {  

      int lastDot = si。lastIndexOf('。');  

      if(lastDot != …1)  

        si =  si。substring(lastDot + 1);  

      s += si;  

    }  

    return s;  

  }  

} ///:~  

  



                                                                                             642 


…………………………………………………………Page 644……………………………………………………………

程序中的有些东西已在以前见识过了。和本书的许多GUI 程序一样,这既可作为一个独立的应用程序使用, 

亦可作为一个程序片(Applet)使用。此外,StripQualifiers 类与它在第 11 章的表现是完全一样的。  

GUI 包含了一个名为name 的“文本字段”(TextField),或在其中输入想查找的类名;还包含了另一个文 

本字段,名为 searchFor,可选择性地在其中输入一定的文字,希望在方法列表中查找那些文字。Checkbox 

 (复选框)允许我们指出最终希望在输出中使用完整的名字,还是将前面的各种限定信息删去。最后,结果 

显示于一个“文本区域”(TextArea )中。  

大家会注意到这个程序未使用任何按钮或其他组件,不能用它们开始一次搜索。这是由于无论文本字段还是 

复选框都会受到它们的“侦听者(Listener )对象的监视。只要作出一项改变,结果列表便会立即更新。若 

改变了name 字段中的文字,新的文字就会在 NameL 类中捕获。若文字不为空,则在Class。forName()中用于 

尝试查找类。当然,在文字键入期间,名字可能会变得不完整,而Class。forName()会失败,这意味着它会 

 “掷”出一个违例。该违例会被捕获,TextArea 会随之设为“Nomatch”(没有相符)。但只要键入了一个 

正确的名字(大小写也算在内),Class。forName()就会成功,而 getMethods()和 getConstructors()会分别 

返回由Method 和 Constructor 对象构成的一个数组。这些数组中的每个对象都会通过toString()转变成一 

个字串(这样便产生了完整的方法或构建器签名),而且两个列表都会合并到 n 中——一个独立的字串数 

组。数组n 属于DisplayMethods 类的一名成员,并在调用reDisplay()时用于显示的更新。  

若改变了Checkbox 或 searchFor 组件,它们的“侦听者”会简单地调用reDisplay()。reDisplay()会创建 

一个临时数组,其中包含了名为rs 的字串(rs 代表“结果集”——Result Set)。结果集要么直接从n 复 

制(没有find 关键字),要么选择性地从包含了 find 关键字的n 中的字串复制。最后会检查strip  

Checkbox,看看用户是不是希望将名字中多余的部分删除(默认为“是”)。若答案是肯定的,则用 

StripQualifiers。strip()做这件事情;反之,就将列表简单地显示出来。  

在 init()中,大家也许认为在设置布局时需要进行大量繁重的工作。事实上,组件的布置完全可能只需要极 

少的工作。但象这样使用BorderLayout 的好处是它允许用户改变窗口的大小,并特别能使 TextArea (文本 

区域)更大一些,这意味着我们可以改变大小,以便毋需滚动即可看到更长的名字。  

编程时,大家会发现特别有必要让这个工具处于运行状态,因为在试图判断要调用什么方法的时候,它提供 

了最好的方法之一。  



17。3 复杂性理论  



下面要介绍的程序的前身是由Larry O'Brien 原创的一些代码,并以由 Craig Reynolds 于 1986 年编制的 

 “Boids”程序为基础,当时是为了演示复杂性理论的一个特殊问题,名为“凸显”(Emergence)。  

这儿要达到的目标是通过为每种动物都规定少许简单的规则,从而逼真地再现动物的群聚行为。每个动物都 

能看到看到整个环境以及环境中的其他动物,但它只与一系列附近的“群聚伙伴”打交道。动物的移动基于 

三个简单的引导行为:  

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

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

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

更复杂的模型甚至可以包括障碍物的因素,动物能预知和避免与障碍冲突的能力,所以它们能围绕环境中的 

固定物体自由活动。除此以外,动物也可能有自己的特殊目标,这也许会造成群体按特定的路径前进。为简 

化讨论,避免障碍以及目标搜寻的因素并未包括到这里建立的模型中。  

尽管计算机本身比较简陋,而且采用的规则也相当简单,但结果看起来是真实的。也就是说,相当逼真的行 

为从这个简单的模型中“凸显”出来了。  

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

  

//: FieldOBeasts。java  

// Demonstration of plexity theory; simulates   

// herding behavior in animals。 Adapted from  

// a program by Larry O'Brien lobrien@msn。  

import java。awt。*;  

import java。awt。event。*;  

import java。applet。*;  

import java。util。*;  

  

class Beast {  



                                                                        643 


…………………………………………………………Page 645……………………………………………………………

  int  

    x; y;            // Screen position  

    currentSpeed;    // Pixels per second  

  float currentDirection;  // Radians  

  Color color;      // Fill color  

  FieldOBeasts field; // Where the Beast roams  

  static final int GSIZE = 10; // Graphic size  

  

  public Beast(FieldOBeasts f; int x; int y;   

      float cD; int cS; Color c) {  

    field = f;  

    this。x = x;  

    this。y = y;  

    currentDirection = cD;  

    currentSpeed = cS;  

    color = c;  

  }  

  public void step()  {  

    // 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:  



                                                                                          644 


…………………………………………………………Page 646……………………………………………………………

      if(distanceToNearest  field。maxSpeed) {  

          currentSpeed = field。maxSpeed;  

        }  

      }  

    }   

    else {  // You are in front; 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 float bearingFromPointAlongAxis (  

      int originX; int originY; float axis) {  

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



                                                                                        645 


…………………………………………………………Page 647……………………………………………………………

      }   

      else  

        return (float) Math。PI;  

    }  

  }  

  public float distanceFromPoint(int x1; int y1){  

    return (float) Math。sqrt(  

      Math。pow(x1 x; 2) +   

      Math。pow(y1 y; 2));  

  }  

  public Point position() {   

    return new Point(x; y);  

  }  

  // Beasts know how to draw themselves:  

  public void draw(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 float   

    fieldOfView =   

      (float) (Math。PI / 4); // In radians  

    // Deceleration % per second:  

    decayRate = 1。0f;   

    minimumDistance = 10f; // In pixels  

  static int  

    halfFieldOfView = (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 void init() {  

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

      xExtent = Integer。parseInt(  

        getParameter(〃xExtent〃));  

      yExtent = Integer。parseInt(  

        getParameter(〃yExtent〃));  

    }  



                                                                                             646 


…………………………………………………………Page 648……………………………………………………………

    beasts =   

      makeBeastVector(numBeasts; uniqueColors);  

    // Now start the beasts a…rovin':  

    thisThread = new Thread(this);  

    thisThread。start();  

  }  

  public void run() {  

    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)   



                                                                                        647 


…………………………………………………………Page 649……………………………………………………………

              b …= 1。0f;  

          }  

        }  

      }  

      newBeasts。addElement(  

        new Beast(this; x; y; direction; speed;   

          new Color(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 void paint(Graphics g)  {  

    Enumeration e = beasts。elements();  

    while(e。hasMoreElements()) {  

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

    }  

  }  

  public static void main(String'' args)   {  

    FieldOBeasts field = new FieldOBeasts();  

    field。xExtent = 640;  

    field。yExtent = 480;  

    Frame frame = new Frame(〃Field 'O Beasts〃);  

    // Optionally use a mand…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);  



                                                                                        648 


…………………………………………………………Page 650……………………………………………………………

    field。init();  

    field。start();  

    frame。setVisible(true);  

  }  

} ///:~  

  

尽管这并非对Craig Reynold 的“Boids”例子中的行为完美重现,但它却展现出了自己独有的迷人之外。通 

过对数字进行调整,即可进行全面的修改。至于与这种群聚行为有关的更多的情况,大家可以访问Craig  

返回目录 上一页 下一页 回到顶部 10 9
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!