zurück zur Übersicht

Springer.java

 
/** 
 * Springer.java
 *
 * @author Martin Klöckner, Daniel Höpfl
 */

package SpringerPack;

import javax.swing.JProgressBar;
import javax.swing.JList;
import java.util.Vector;
import java.awt.Canvas;

/**
 * This class implements the backtracing to solve the Springerproblem
 *
 * @see IOutput
 * @see SpringerMain
 */
public class Springer extends Thread
{
      /**
       * Flag to indicate an interruption
       */
   private boolean mKeepRunning = true;

      /**
       * Member for callback-function-calls
       */
   SpringerMain mMain = null;

      /**
       * size of board
       */
   int mSize = 2;

      /**
       * Starting field
       */
   int mStartX = 0;
   int mStartY = 0;

      /**
       * IOutput for showing the board
       */
   IOutput mOutput = null;

      /**
       * element to show the deepth the backtracking is in
       */
   JProgressBar mDeepth = null;

      /**
       * global progress
       */
   int mProgressInt = 0;
   JProgressBar mProgress = null;

      /**
       * board to use
       */
   private Board mBoard = null;

      /**
       * lists of results
       */
   JList mResultList = null;
   Vector mResultVector = null;

      /**
       * initialisize Springer
       *
       * @param inMain   MainFrame of the applet (used for callback in case of "natural" end)
       * @param inSize   size of Board
       * @param inProgressBar   global Progressbar
       * @param inProgressDeepthBar element to display calculation deepth
       * @param inOutput   Object to show the board
       * @param inResultList   List to show the result
       * @param inBoard   board to store the data in
       *
       * @see IOutput
       * @see Board
       */
   Springer(SpringerMain inMain,
            int inSize,
            JProgressBar inProgressBar,
            JProgressBar inProgressDeepthBar,
            IOutput inOutput,
            JList inResultList,
            Board inBoard)
   {
      mKeepRunning = true;

      mMain = inMain;
      mSize = inSize;

      mProgress = inProgressBar;
      mDeepth = inProgressDeepthBar;

      mDeepth.setMinimum(0);
      mDeepth.setMaximum(mSize * mSize);
      mDeepth.setValue(0);

      mProgress.setMinimum(0);
      mProgress.setMaximum(100000);
      mProgress.setValue(0);
      mProgressInt = 0;

      mResultVector = new Vector();

      mResultList = inResultList;
      mResultList.setListData(mResultVector);

      mBoard = inBoard;

      setIOutput(inOutput);
   }

      /**
       * set the starting field
       *
       * @param inX   x-coordinate of the starting field
       * @param inY   y-coordinate of the starting field
       */
   public void setStart(int inX, int inY)
   {
      if(inX < mSize)
         mStartX = inX;
      if(inY < mSize)
         mStartY = inY;
   }

      /**
       * set the IOutput Object
       *
       * @param inOutput   Object to set
       */
   public synchronized void setIOutput(IOutput inOutput)
   {
      mOutput = inOutput;
      mOutput.setBoardSize(mSize);
      mOutput.setBoard(mBoard);
   }

      /**
       * get one step deeper in the backtracking algorithmus
       *
       * @param inSourceX   x-coordinate of the source field
       * @param inSourceY   y-coordinate of the source field
       * @param inDestX   x-coordinate of the target field
       * @param inDestY   y-coordinate of the target field
       *
       * @see IOutput#deeper
       */
   private synchronized void deeper(int inSourceX, int inSourceY, int inDestX, int inDestY) throws InterruptedException
   {
      mOutput.deeper(inSourceX, inSourceY, inDestX, inDestY);
      mDeepth.setValue(mDeepth.getValue() + 1);
   }

      /**
       * get one step higher in the backtracking algorithmus
       * @param inSourceX   x-coordinate of the source field
       * @param inSourceY   y-coordinate of the source field
       * @param inDestX   x-coordinate of the target field
       * @param inDestY   y-coordinate of the target field
       *
       * @see IOutput#higher
       */
   private synchronized void higher(int inSourceX, int inSourceY, int inDestX, int inDestY) throws InterruptedException
   {
      mOutput.higher(inSourceX, inSourceY, inDestX, inDestY);
      mDeepth.setValue(mDeepth.getValue() - 1);
   }

      /**
       * insert a Result into the Result-List
       */
   private synchronized void foundResult() throws InterruptedException
   {
      int xPos[] = new int[mSize*mSize];
      int yPos[] = new int[mSize*mSize];

         // get sequence of moves
      for(int x = 0;x < mSize; x++)
      {
         for(int y = 0;y < mSize; y++)
         {
            xPos[mBoard.getXY(x,y) - 1] = x;
            yPos[mBoard.getXY(x,y) - 1] = y;
         }
      }

         // create string in chess-notation
      String theResult = new String();

      for(int i = 0;i < mSize * mSize; i++)
      {
         theResult += ("ABCDEFGHIJKLMNOP".charAt(xPos[i])) +
                     new Integer(mSize - yPos[i]).toString() +
                     " ";
      }

         // add result
      mResultVector.addElement(theResult);
      mResultList.setListData(mResultVector);
   }

      /**
       * main recursive backtracking procedure
       *
       * @param xPos   x-coordinate of the field to test
       * @param yPos   y-coordinate of the field to test
       * @param Nr   number of step
       */
   private void DoIt(int xPos, int yPos, int Nr) throws InterruptedException
   {
         // have we been stopped?
      if(!mKeepRunning)
      {
         interrupt();
         return;
      }

         // array for all possible moves
      int xDir[] = new int[8];
      int yDir[] = new int[8];

      xDir[0] =  2; yDir[0] = -1;
      xDir[1] =  2; yDir[1] =  1;
      xDir[2] =  1; yDir[2] =  2;
      xDir[3] = -1; yDir[3] =  2;
      xDir[4] = -2; yDir[4] =  1;
      xDir[5] = -2; yDir[5] = -1;
      xDir[6] = -1; yDir[6] = -2;
      xDir[7] =  1; yDir[7] = -2;

         // lock board to prevent the other thread from drawing
         // half-changed fields, then set our move in and unlock
      mBoard.lockBoard();
      mBoard.setXY(xPos, yPos, Nr);
      mBoard.unlockBoard();

         // found a result?
      if(Nr == (mSize * mSize))
      {
         foundResult();
      }
      else
      {
            // test all 8 possible moves
         for(int testNr = 0;testNr < 8; testNr++)
         {
               // can we get there
            if(mBoard.getXY(xPos + xDir[testNr], yPos + yDir[testNr]) == 0)
            {
                  // update progress-bar
               mProgressInt++;
               mProgress.setValue((int) ((((float) mProgressInt)/134217728) * 10000));

                  // next step in backtracking
               deeper(xPos, yPos, xPos + xDir[testNr], yPos + yDir[testNr]);
               DoIt(xPos + xDir[testNr], yPos + yDir[testNr], Nr+1);
               higher(xPos + xDir[testNr], yPos + yDir[testNr], xPos, yPos);
            }
            else if(Nr < 9)
            {
                  // can't get deeper, progress faster
               int reste[] = new int[9];

               reste[0] = 16777216;
               reste[1] = 2097152;
               reste[2] = 262144;
               reste[3] = 32768;
               reste[4] = 4096;
               reste[5] = 512;
               reste[6] = 64;
               reste[7] = 8;
               reste[8] = 1;

               mProgressInt += reste[Nr - 1];
               mProgress.setValue((int) ((((float) mProgressInt)/134217728) * 10000));
            }
         }
      }

         // take back the move
      mBoard.lockBoard();
      mBoard.setXY(xPos, yPos, 0);
      mBoard.unlockBoard();
   }

      // start thread
   public void run() {
      mDeepth.setValue(1);

      try {
         DoIt(mStartX,mStartY,1);
      } catch (InterruptedException e){
      }

      mDeepth.setValue(0);
      mProgress.setValue(0);
      mProgressInt = 0;

      mMain.ChildFinished();
   }   

      // interrupt it.
   public void Stop() {
      mKeepRunning = false;
   }
}

zurück zur Übersicht