/* Listing3409.java */

import java.awt.*;
import java.awt.event.*;
import java.util.*;

class ColorRectangle
extends Rectangle
{
  public Color color;
}

public class Listing3409
extends Frame
implements Runnable
{
  //Konstanten
  private static final int   SIZERECT    = 7;
  private static final int   SLEEP       = 40;
  private static final int   NUMELEMENTS = 20;
  private static final Color BGCOLOR     = Color.lightGray;

  //Instanzvariablen
  private Thread th;
  private Vector snake;
  private int dx;
  private int dy;

  public static void main(String[] args)
  {
    Listing3409 frame = new Listing3409();
    frame.setSize(200,150);
    frame.setVisible(true);
    frame.startAnimation();
  }

  public Listing3409()
  {
    super("Animierte Schlange");
    setBackground(BGCOLOR);
    addWindowListener(new WindowClosingAdapter(true));
    snake = new Vector();
  }

  public void startAnimation()
  {
    th = new Thread(this);
    th.start();
  }

  public void run()
  {
    //Schlange konstruieren
    ColorRectangle cr;
    int x = 100;
    int y = 100;
    for (int i=0; i < NUMELEMENTS; ++i) {
      cr = new ColorRectangle();
      cr.x = x;
      cr.y = y;
      cr.width = SIZERECT;
      cr.height = SIZERECT;
      x += SIZERECT;
      cr.color = new Color(
        i*(256/NUMELEMENTS),
        0,
        240-i*(256/NUMELEMENTS)
      );
      snake.addElement(cr);
    }

    //Vorzugsrichtung festlegen
    dx = -1;
    dy = -1;

    //Schlange laufen lassen
    while (true) {
      repaint();
      try {
        Thread.sleep(SLEEP);
      } catch (InterruptedException e){
        //nichts
      }
      moveSnake();
    }
  }

  public void moveSnake()
  {
    Dimension size = getSize();
    int sizex = size.width-getInsets().left-getInsets().right;
    int sizey = size.height-getInsets().top-getInsets().bottom;
    ColorRectangle cr = (ColorRectangle)snake.firstElement();
    boolean lBorder = false;
    int xalt, yalt;
    int xtmp, ytmp;

    //Kopf der Schlange neu berechnen
    if (cr.x <= 1) {
      dx = 1;
      lBorder = true;
    }
    if (cr.x + cr.width >= sizex) {
      dx = -1;
      lBorder = true;
    }
    if (cr.y <= 1) {
      dy = 1;
      lBorder = true;
    }
    if (cr.y + cr.height >= sizey) {
      dy = -1;
      lBorder = true;
    }
    if (! lBorder) {
      if (rand(10) == 0) {
        if (rand(2) == 0) {
          switch (rand(5)) {
          case 0: case 1:
            dx = -1;
            break;
          case 2:
            dx = 0;
            break;
          case 3: case 4:
            dx = 1;
            break;
          }
        } else {
          switch (rand(5)) {
          case 0: case 1:
            dy = -1;
            break;
          case 2:
            dy = 0;
            break;
          case 3: case 4:
            dy = 1;
            break;
          }
        }
      }
    }
    xalt = cr.x + SIZERECT * dx;
    yalt = cr.y + SIZERECT * dy;
    //Rest der Schlange hinterherziehen
    Enumeration e = snake.elements();
    while (e.hasMoreElements()) {
      cr = (ColorRectangle)e.nextElement();
      xtmp = cr.x;
      ytmp = cr.y;
      cr.x = xalt;
      cr.y = yalt;
      xalt = xtmp;
      yalt = ytmp;
    }
  }

  public void paint(Graphics g)
  {
    ColorRectangle cr;
    Enumeration e = snake.elements();
    int inleft    = getInsets().left;
    int intop     = getInsets().top;
    while (e.hasMoreElements()) {
      cr = (ColorRectangle)e.nextElement();
      g.setColor(cr.color);
      g.fillRect(cr.x+inleft,cr.y+intop,cr.width,cr.height);
    }
  }

  private int rand(int limit)
  {
    return (int)(Math.random() * limit);
  }
}