⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hanoitower.java

📁 创建一个Applet小程序实现有名的汉诺塔小游戏
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
import java.applet.* ;
import java.awt.* ;
import java.net.* ;
import java.util.* ;
import javax.swing.*;
import java.awt.event.*;

public class HanoiTower extends JApplet implements Runnable   //$主类用于初始化applet panel,开始游戏,
{                                                          //$运行自动演示线程和处理用鼠标移动事件
   static final Font titleFont=new Font("Helvetica", Font.BOLD, 20),//$定义一些字体常量
                     textFont=new Font("Helvetica", Font.PLAIN, 20),
                     monoFont=new Font("Courier", Font.BOLD, 20) ;
   static final int CANVAS_WIDTH=450, CANVAS_HEIGHT=250,  //$定义画布大小及盘子的最大最小值
                     TABLE_TOP=225,MIN_DISCS=3, MAX_DISCS=12 ;
   public int PEG1=0, PEG2=1, PEG3=2;             //$定义三个值代表三个柱子

   private boolean gameOver,suspendFlag,stepFlag ;//$游戏结束、线程挂起、单步运行
   private int sourceDisc, sourcePeg, targetPeg;  //$源盘、源柱、目标柱
   private String gameStatus ;                    //$游戏状态
   private JPanel cp1Back,cp2Back, titlePanel ;   //$控制面板1、2和标题面板
   private JLabel titleLabel ;                    //$标题标签
   private Board bd ;                             //$自定义类描述盘子存储结构
   private BoardCanvas bc ;                       //$自定义类描述盘子外观
   private StatusPanel sp ;                       //$自定义类描述状态面板
   private ControlPanelOne cp1 ;                  //$自定义类描述控制面板1、2
   private ControlPanelTwo cp2 ;
   private Image boardImage ;
   private String boardImageFile = "board.gif" ;  //$背景图片
   public Thread solveThread, timer ;             //$自动线程和时间线程

   public void init()
   {

      // load board image
      MediaTracker tracker = new MediaTracker(this) ;//$装载并跟踪图片
      URL url = getCodeBase() ;
      boardImage = getImage(url,boardImageFile) ;
      tracker.addImage(boardImage,0) ;
      try { tracker.waitForID(0); }
      catch (InterruptedException e) {}

      // initialize applet layout
      setBackground(Color.gray) ;                     //$主面板初始化
      JPanel mainPanel = new JPanel() ;
      mainPanel.setLayout(new BorderLayout(0,0)) ;    //$BorderLayout布局
      // BoardCanvas
      bc = new BoardCanvas(this) ;
      bc.resize(CANVAS_WIDTH,CANVAS_HEIGHT) ;
      // Title panel
      titlePanel = new JPanel() ;
      titlePanel.setLayout(new GridLayout(1,1)) ;
      titlePanel.setBackground(Color.gray) ;
      titlePanel.setFont(titleFont) ;
      titlePanel.add(titleLabel=new JLabel("   Tower of Hanoi made by Wangyue.",JLabel.CENTER)) ;
      titleLabel.setForeground(Color.white) ;
      // Control Panel one

      cp1Back = new JPanel() ;
      cp1Back.setBackground(Color.gray) ;
      cp1 = new ControlPanelOne(this) ;
      cp1Back.add(cp1) ;
      //Control Panel two
      cp2Back = new JPanel() ;
      cp2Back.setBackground(Color.gray) ;
      cp2 = new ControlPanelTwo(this) ;
      cp2Back.add(cp2) ;



      // Status panel
      sp = new StatusPanel(this) ;
      sp.setBackground(Color.gray) ;
      // construct applet panel
      mainPanel.add("Center",bc) ;
      mainPanel.add("North",titlePanel) ;
      mainPanel.add("West",cp1Back) ;
      mainPanel.add("East",cp2Back) ;
      mainPanel.add("South",sp) ;
      add(mainPanel) ;
      validate() ;               //$使布局生效

      newGame() ;                //$开始游戏
   }
   // startup
   void newGame() //$开始游戏
   {
      int discs = cp1.getDiscs() ;//$得到盘子数

      System.gc() ;               //$内存回收
      gameOver = false ;
      suspendFlag=false;
      stepFlag=true;

      bd = new Board(discs,this) ;
      bc.drawBoard(bd,boardImage,0,0,0) ;
      sp.setMoveCount(0) ;
      if (cp2.isTimerOn) timer = new Timer(cp2) ; //$计时
      else cp2.setTimer(" ") ;
      if (solveThread == null)                    //$状态条
         sp.setStatus("Move all " + discs + " discs to the rightmost peg.") ;
      bc.requestFocus() ;                         //$得到焦点
   }
   // handle Reset event
   void restartGame()        //$重新开始游戏
   {
      stop() ;
      cp1.setAutoSolveEnable(true) ;
      newGame() ;
   }
   // kill all threads
   public void stop()        //$停止游戏
   {
      if (solveThread!=null) {
         solveThread.stop() ;
         solveThread = null ;
      }
      if (timer!=null) {
         timer.stop() ;
         timer = null ;
      }
   }
   // spawn Autosolve thread
   public void startSolveThread() //$自动运行
   {
      stop() ;
      solveThread = new Thread(this) ;
      solveThread.start() ;
   }
   // run Autosolve thread
   public void run()          //$start()调用
   {
      newGame() ;
      sp.setStatus("Autosolving ...") ;
      solve(cp1.getDiscs(),PEG1,PEG2,PEG3) ; //$递归
      sp.setStatus("Finished!") ;
      gameOver = true ;
      solveThread = null ;
      cp1.setAutoSolveEnable(true) ;
   }
   //when Autosolve to show status bar
   public void showstatusbar(int source,int target) //$演示过程
   {
   	  sp.setStatus("Now move from peg"+(source+1) + " to peg" + (target+1)+ ".") ;
   }
   public void mysuspend()  //$线程的挂起
   {
   	  suspendFlag=true;
   }
   synchronized void myresume() //$线程的返回
   {
   	  suspendFlag=false;
   	  notify();
   }
   public void step()        //$单步运行
   {
   	  //myresume();
   	  suspendFlag=!suspendFlag;
   	  notify();
   	  //stepFlag=!stepFlag;
   }

   // here's the famous algorithm
   void solve(int discs,int source,int aux,int target) //$递归
   {
   	  synchronized (this)
   	  {
   	  	while(suspendFlag)
   	  	{
   	  		try
   	  		{
   	  		  wait();
   	  		}
   	  		catch(InterruptedException e){}
   	  	}
   	  }
      if (discs==0) return ;                      // base to end recursion
      solve(discs-1,source,target,aux) ;          // recursive call #1

      bd.moveDisc(source,target) ;                // move disc
      sp.setMoveCount(bd.getMoveCount()) ;        // update display
      showstatusbar(source,target);
      bc.drawBoard(bd,boardImage,0,0,0) ;
      try { solveThread.sleep(cp1.getDelay()) ; }  // Autosolve delay
      catch (InterruptedException e) {}
      /*while(!stepFlag)
      {
      try { solveThread.sleep(cp1.getDelay()) ; }  // Autosolve delay
      catch (InterruptedException e) {}
      }*/
      solve(discs-1,aux,source,target) ;          // recursive call #2
   }
   // handle mouse drag event
   void dragDisc(int x,int y) {
      if (!gameOver&&(sourceDisc!=0))  //$如果源盘子存在
         bc.drawBoard(bd,boardImage,sourceDisc,x,y) ;
   }
   // handle mouse down event
   void selectDisc(int x,int y) {
      if (!gameOver&&(solveThread==null)) {
         if ((timer!=null)&&(!timer.isAlive())) timer.start() ;
         sourcePeg = pixelToPeg(x,y) ;
         if (bd.isStartPeg(sourcePeg)) //$如果此柱上有盘子
         {
            sourceDisc = bd.getTopDisc(sourcePeg) ;
            bc.drawBoard(bd,boardImage,sourceDisc,x,y) ;
         }
      }
   }
   // handle mouse up event
   void dropDisc(int x,int y)
   {
      if (!gameOver&&(sourceDisc!=0))  //$如果取到盘子
      {
         targetPeg = pixelToPeg(x,y) ;
         if (bd.moveDisc(sourceDisc,sourcePeg,targetPeg))
         {
            gameStatus = bd.getBoardStatus() ;
            sp.setMoveCount(bd.getMoveCount()) ;
            if (gameStatus==null)
               sp.setStatus("The minimum number of moves required is " +
                             bd.getMinMoves() + ".") ;
            else
            {
               gameOver = true ;
               stop() ;
               sp.setStatus(gameStatus) ;
            }
         }
         bc.drawBoard(bd,boardImage,0,0,0) ;
         sourceDisc = 0 ;
      }
   }
   // conversion for mouse down/up events
   int pixelToPeg(int x,int y)  //$是否在有效范围内
   {
      int peg = -1 ;
      if ((y>40)&&(y<TABLE_TOP))
      {
         if ((x>50)&&(x<100)) peg = PEG1 ;
         else if ((x>200)&&(x<250)) peg = PEG2 ;
         else if ((x>350)&&(x<400)) peg = PEG3 ;
      }
      return peg ;
   }
}

final class Timer extends Thread //$时间线程
{
   static final int ONE_SECOND=1000 ; //$单位时间一秒
   private long startTime, rem ;
   private int hours, min, sec ;
   private String sMin, sSec, sTime ;
   private ControlPanelTwo cp2 ;

   // constructor
   Timer(ControlPanelTwo cp2)     //$构造函数
   {
      this.cp2 = cp2 ;
      cp2.setTimer(setTime(0)) ;  //$设置时间
   }
   // run thread
   public void run()
   {
      startTime = System.currentTimeMillis() ;
      while (true) {
         try { Thread.sleep(ONE_SECOND) ; }  //$等待一秒
         catch (InterruptedException e) {}
         cp2.setTimer(setTime(System.currentTimeMillis() - startTime)) ;
      }
   }
   // return h:mm:ss string from milliseconds
   String setTime(long millisec)     //$将毫秒数转化为对应小时、分、秒
   {
      hours = (int)(millisec/3600000) ;
      rem = millisec - (hours*3600000) ;
      min = (int)(rem/60000) ;
      rem = rem - (min*60000) ;
      sec = (int)(rem/1000) ;

      sMin = Integer.toString(min) ;
      if (sMin.length()==1) sMin = "0" + sMin ;
      sSec = Integer.toString(sec) ;
      if (sSec.length()==1) sSec = "0" + sSec ;
      sTime = "  " + Integer.toString(hours) + ":" + sMin + ":" + sSec ;
      return sTime ;
   }
}

final class Board   //$自定义类描述盘子存储结构和移动规则
{
   static final int PEGS=3,
                    DISC_SIZES[][]={ {68,18},{76,16},{84,14},{92,13},{100,12},
                                     {108,12},{112,11},{116,10},{120,9},{124,9} } ;
   private int peg[][], pegTop[]=new int[PEGS], discWidth[] ;
   private int discs, moveCount, minMoves ;
   private HanoiTower main ; //$主面板类

   // constructor
   Board(int discs,HanoiTower main) //$构造函数
   {
      this.discs = discs ;
      this.main = main ;
      peg = new int[discs][PEGS] ;
      // put all the disks on the first peg
      for (int i=0; i<discs; i++)  //$存储结构初始化
        peg[i][main.PEG1] = discs-i ;
      pegTop[main.PEG1] = discs-1 ;//$记录每个柱子盘子
      for (int i=1; i<PEGS; i++) pegTop[i] = -1 ;
      // calculate disc widths
      discWidth = new int[discs] ; //$计算盘子宽度
      for (int i=discs-1; i>=0; i--)
         discWidth[i] = DISC_SIZES[discs-main.MIN_DISCS][0] -
                        (DISC_SIZES[discs-main.MIN_DISCS][1] *
                        (discs-1-i)) ;
      moveCount = 0 ;
      // minimum moves is (2**discs)-1
      minMoves = ((int)Math.pow(2.0,discs)) - 1 ; //$算出最少移动次数
   }
   void setDisc(int d,int p) { peg[++pegTop[p]][p] = d ; }
   int getDisc(int d,int p) { return peg[d][p] ; }
   int getTopDisc(int p) { return peg[pegTop[p]--][p] ; }
   int getPegTop(int p) { return pegTop[p] ; }
   int getMoveCount() {return moveCount ; }
   int getMinMoves() {return minMoves ; }
   int getDiscWidth(int d) { return discWidth[d-1] ; }
   boolean isStartPeg(int i)    //$是否有盘子
   {
      if ((i >= 0)&&(pegTop[i]>=0)) return true ;
      else return false ;
   }
   String getBoardStatus()      //$游戏结束返回状态信息
   {
      String status = null ;
      if (pegTop[PEGS-1]==(discs - 1))
      {
         if (moveCount==minMoves)
            status = "Congratulations!" ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -