KT.java
上传用户:xdk604
上传日期:2021-10-27
资源大小:4k
文件大小:11k
源码类别:

Applet

开发平台:

Java

  1. import java.applet.Applet;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. import java.net.URL;
  5. import java.util.ArrayList;
  6. public class KT extends Applet
  7. {
  8.    // 线程延迟以毫秒为单位
  9.    public final static int DELAY = 500;
  10.    // 开始骑士巡游线程
  11.    private Thread thd;
  12.    // 初始化小程序
  13.    public void init ()
  14.    {
  15.       // 创建一个标签对象来标明小程序的标题
  16.       Label lblTitle = new Label ("Knight's Tour", Label.CENTER);
  17.       lblTitle.setFont (new Font ("Arial", Font.BOLD, 18));
  18.       // 把标签对象加到小程序的面板容器
  19.       add (lblTitle);
  20.       // 创建一个ChessBoard对象,它具有显示一个棋盘、移动骑士到
  21. // 任何方格并留下骑士巡游轨迹的能力.
  22.       final ChessBoard cb = new ChessBoard (this);
  23.       //把ChessBoard对象加入到小程序的面板容器
  24.       add (cb);
  25.       // 创建一个Panel对象来保存Label,Choice和按钮对象.
  26.       Panel pnl = new Panel ();
  27.       //创建一个标签来标明Choice对象并把它添加到Panel中
  28.       pnl.add (new Label ("Choose starting position:"));
  29.       //创建一个Choice对象,用来选择骑士的开始位置(棋盘的四个角落)
  30. //并把它添加到Panel中.
  31.       final Choice c = new Choice ();
  32.       c.add ("Upperleft corner");
  33.       c.add ("Upperright corner");
  34.       //创建Choice的item listener,这个监听器按选择结果来重设骑士的开始位置.
  35.       c.addItemListener (new ItemListener ()
  36.                          {
  37.                              public void itemStateChanged (ItemEvent e)
  38.                              {
  39.                                 Choice c = (Choice) e.getSource ();
  40.                                 if (c.getSelectedIndex () == 0)
  41.                                     cb.moveKnight (1);
  42.                                 else
  43.                                     cb.moveKnight (8);
  44.                                 cb.reset ();
  45.                              }
  46.                          });
  47.       pnl.add (c);
  48.       //把Panel加入到小程序的面板容器
  49.       add (pnl);
  50.       //创建一个按钮对象用来开始骑士巡游.
  51.       final Button btn = new Button ("Take the Tour");
  52.       //创建按钮的Action listener(动作监听器),用来确定骑士巡游的位置.
  53. //按照规则将骑士从一个位置移动到另一个位置.
  54.       ActionListener al;
  55.       al = new ActionListener ()
  56.            {
  57.                public void actionPerformed (ActionEvent e)
  58.                {
  59.                   Runnable r;
  60.                   r = new Runnable ()
  61.                       {
  62.                           int [] boardPositions1 =
  63.                           {
  64.                               1, 18, 33, 50, 60, 54, 64, 47,
  65.                              32, 15,  5, 11, 17, 34, 49, 59,
  66.                              53, 63, 48, 31, 16,  6, 12,  2,
  67.                              19, 25, 42, 57, 51, 61, 55, 40,
  68.                              23,  8, 14,  4, 10, 27, 44, 38,
  69.                              21, 36, 46, 29, 35, 41, 58, 52,
  70.                              62, 56, 39, 24,  7, 13,  3,  9,
  71.                              26, 43, 37, 22, 28, 45, 30, 20
  72.                           };
  73.                           int [] boardPositions2 =
  74.                           {
  75.                               8, 23, 40, 55, 61, 51, 57, 42,
  76.                              25, 10,  4, 14, 24, 39, 56, 62,
  77.                              52, 58, 41, 26,  9,  3, 13,  7,
  78.                              22, 32, 47, 64, 54, 60, 50, 33,
  79.                              18,  1, 11,  5, 15, 30, 45, 35,
  80.                              20, 37, 43, 28, 38, 48, 63, 53,
  81.                              59, 49, 34, 17,  2, 12,  6, 16,
  82.                              31, 46, 36, 19, 29, 44, 27, 21
  83.                           };
  84.                           public void run ()
  85.                           {
  86.                              cb.reset ();
  87.                              // thd用来检查用户离开小程序网页
  88.                  // 以便停止小程序的运行.
  89.                              for (int i = 0; i < boardPositions1.length &&
  90.                                   thd != null; i++)
  91.                              {
  92.                                   if (c.getSelectedIndex () == 0)
  93.                                       cb.moveKnight (boardPositions1 [i]);
  94.                                   else
  95.                                       cb.moveKnight (boardPositions2 [i]);
  96.                                   try
  97.                                   {
  98.                                       Thread.sleep (DELAY);
  99.                                   }
  100.                                   catch (InterruptedException e2)
  101.                                   {
  102.                                   }
  103.                              }
  104.                              c.setEnabled (true);
  105.                              btn.setEnabled (true);
  106.                           }
  107.                       };
  108.                   c.setEnabled (false);
  109.                   btn.setEnabled (false);
  110.                   thd = new Thread (r);
  111.                   thd.start ();
  112.                }
  113.            };
  114.       btn.addActionListener (al);
  115.       //添加按钮到小程序面板容器
  116.       add (btn);
  117.    }
  118.    //停止小程序
  119.    public void stop ()
  120.    {
  121.       //用户离开网页时必须停止”骑士巡游”线程
  122.       thd = null;
  123.    }
  124. }
  125. final class ChessBoard extends Canvas
  126. {
  127.    //非白色方格的颜色
  128.    private final static Color SQUARECOLOR = new Color (195, 214, 242);
  129.    //棋盘方格的尺寸
  130.    private final static int SQUAREDIM = 40;
  131.    //棋盘方格的尺寸(包括黑边框)
  132.    private final static int BOARDDIM = 8 * SQUAREDIM + 2;
  133.    //棋盘左上角的左坐标(X坐标)
  134.    private int boardx;
  135.    //棋盘左上角的顶坐标(Y坐标)
  136.    private int boardy;
  137.    //棋盘长度
  138.    private int width;
  139.    // 棋盘宽度
  140.    private int height;
  141.    // 图像缓冲
  142.    private Image imBuffer;
  143.    // Graphics context associated with image buffer.
  144.    private Graphics imG;
  145.    // 骑士图像
  146.    private Image imKnight;
  147.    // 骑士图像的长度
  148.    private int knightWidth;
  149.    // 骑士图像的宽度
  150.    private int knightHeight;
  151.    //骑士轨迹的坐标
  152.    private ArrayList trail;
  153.    // Left coordinate of knight rectangle origin (upper-left corner).
  154.    private int ox;
  155.    // Top coordinate of knight rectangle origin (upper-left corner).
  156.    private int oy;
  157.    // 创建ChessBoard的Applet--调用它的getImage()和getDocumentBase()方法, 
  158. // 并且我们将使用它作为drawImage()方法的image observer
  159.    Applet a;
  160.    // 构造棋盘
  161.    ChessBoard (Applet a)
  162.    {
  163.       // 确定部件的大小
  164.       width = BOARDDIM+1;
  165.       height = BOARDDIM+1;
  166.       // 初始化棋盘, 使它处于中央
  167.       boardx = (width - BOARDDIM) / 2 + 1;
  168.       boardy = (height - BOARDDIM) / 2 + 1;
  169.       //使用MediaTracker来确保骑士图像在我们获取它的长和宽之前被完全导入
  170.       MediaTracker mt = new MediaTracker (this);
  171.       // 导入骑士图像
  172.       imKnight = a.getImage (a.getDocumentBase (), "knight.gif");
  173.       mt.addImage (imKnight, 0);
  174.       try
  175.       {
  176.          mt.waitForID (0);
  177.       }
  178.       catch (InterruptedException e) {}
  179.       //获得骑士的长度和宽度, 帮助骑士定位于方格中央
  180.       knightWidth = imKnight.getWidth (a);
  181.       knightHeight = imKnight.getHeight (a);
  182.       //初始化骑士图像, 使骑士定位于左上角方格的中央
  183.       ox = boardx + (SQUAREDIM - knightWidth) / 2 + 1;
  184.       oy = boardy + (SQUAREDIM - knightHeight) / 2 + 1;
  185.       //创建一个数据结构, 用来保存骑士巡游时的轨迹
  186.       trail = new ArrayList ();
  187.       //保存applet引用以便后面调用drawImage()时使用.
  188.       this.a = a;
  189.    }
  190.    // This method is called when the ChessBoard component's peer is created.
  191.    // The code in this method cannot be called in the ChessBoard constructor
  192.    // because the createImage() method returns null at that point. It doesn't
  193.    // return a meaningful value until the ChessBoard component has been added
  194.    // to its container. The addNotify() method is not called until the first
  195.    // time ChessBoard is added to a container.
  196.    public void addNotify ()
  197.    {
  198.       // Given this object's Canvas "layer" a chance to create a Canvas peer.
  199.       super.addNotify ();
  200.       //创建图像缓冲
  201.       imBuffer = createImage (width, height);
  202.       //得到图像缓冲的内容。
  203.       imG = imBuffer.getGraphics ();
  204.    }
  205.    //当小程序的布局管理器布置它的组件时,会调用这个方法。
  206. //如果可能,组件会显示为首选大小。
  207.    public Dimension getPreferredSize ()
  208.    {
  209.       return new Dimension (width, height);
  210.    }
  211.    //移动骑士到指定的棋盘位置。如果位置小于1或大于64则抛出一个异常
  212.    public void moveKnight (int boardPosition)
  213.    {
  214.       if (boardPosition < 1 || boardPosition > 64)
  215.           throw new IllegalArgumentException ("invalid board position: " +
  216.                                               boardPosition);
  217.       int rebasedBoardPosition = boardPosition-1;
  218.       int col = rebasedBoardPosition % 8;
  219.       int row = rebasedBoardPosition / 8;
  220.       ox = boardx + col * SQUAREDIM + (SQUAREDIM - knightWidth) / 2 + 1;
  221.       oy = boardy + row * SQUAREDIM + (SQUAREDIM - knightHeight) / 2 + 1;
  222.       trail.add (new Point (ox + knightWidth / 2, oy + knightHeight / 2));
  223.       repaint ();
  224.    }
  225.    //画出所有部件——先棋盘然后是骑士
  226.    public void paint (Graphics g)
  227.    {
  228.       //画出棋盘
  229.       paintChessBoard (imG, boardx, boardy);
  230.       //画出骑士
  231.       paintKnight (imG, ox, oy);
  232.       //画出骑士的轨迹
  233.       paintTrail (imG);
  234.       //画出图像缓冲的内容
  235.       g.drawImage (imBuffer, 0, 0, this);
  236.    }
  237.    //画出棋盘——(x, y)是左上角坐标
  238.    void paintChessBoard (Graphics g, int x, int y)
  239.    {
  240.       // 画出棋盘的边框
  241.       g.setColor (Color.black);
  242.       g.drawRect (x, y, 8 * SQUAREDIM + 1, 8 * SQUAREDIM + 1);
  243.       //画出棋盘
  244.       for (int row = 0; row < 8; row++)
  245.       {
  246.            g.setColor (((row & 1) != 0) ? SQUARECOLOR : Color.white);
  247.            for (int col = 0; col < 8; col++)
  248.            {
  249.                 g.fillRect (x + 1 + col * SQUAREDIM, y + 1 + row * SQUAREDIM,
  250.                             SQUAREDIM, SQUAREDIM);
  251.                 g.setColor ((g.getColor () == SQUARECOLOR) ? Color.white :
  252.                             SQUARECOLOR);
  253.            }
  254.       }
  255.    }
  256.    //画出骑士——(x, y)是图片左上角坐标
  257.    void paintKnight (Graphics g, int x, int y)
  258.    {
  259.       g.drawImage (imKnight, x, y, a);
  260.    }
  261.    //画出骑士的轨迹
  262.    void paintTrail (Graphics g)
  263.    {
  264.       g.setColor (Color.black);
  265.       int len = trail.size ();
  266.       if (len == 0)
  267.           return;
  268.       Point pt = (Point) trail.get (0);
  269.       int ox = pt.x;
  270.       int oy = pt.y;
  271.       for (int i = 1; i < len; i++)
  272.       {
  273.            pt = (Point) trail.get (i);
  274.            g.drawLine (ox, oy, pt.x, pt.y);
  275.            ox = pt.x;
  276.            oy = pt.y;
  277.       }
  278.    }
  279.    //清空ArrayList来重设棋盘
  280.    public void reset ()
  281.    {
  282.       trail.clear ();
  283.    }
  284.    // The AWT invokes the update() method in response to the repaint() method
  285.    // call that is made as a knight is moved. The default implementation of 
  286.    // this method, which is inherited from the Container class, clears the
  287.    // applet's drawing area to the background color prior to calling paint().
  288.    // This clearing followed by drawing causes flicker. KT overrides
  289.    // update() to prevent the background from being cleared, which eliminates
  290.    // the flicker.
  291.    public void update (Graphics g)
  292.    {
  293.       paint (g);
  294.    }
  295. }