FileDocCategorySizeDatePackage
HanoiCanvas.javaAPI DocJ2ME MIDP 2.06341Thu Nov 07 12:02:20 GMT 2002example.hanoi

HanoiCanvas.java

/*
 * @(#)HanoiCanvas.java	1.3 02/08/15 @(#)
 *
 * Copyright (c) 2002 Sun Microsystems, Inc.  All rights reserved.
 * PROPRIETARY/CONFIDENTIAL
 * Use is subject to license terms.
 */

package example.hanoi;

import java.util.Stack;
import java.util.Enumeration;

import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;

class HanoiCanvas extends Canvas {

    public static final int BACKGROUND_COLOUR    = 0x00000000;
    public static final int TEXT_COLOUR          = 0x00FFFFFF;
    public static final int TOWER_BASE_COLOUR    = 0x000066FF;
    public static final int TOWER_OUTLINE_COLOUR = 0x000066FF;

    public HanoiCanvas(Hanoi hanoi) {
        m_Margin = 2;
        m_N      = 12;
        m_Src    = 0;
        m_Aux    = 1;
        m_Dst    = 2;

	// Create towers
        m_Tower    = new Stack[3];
        m_Tower[0] = new Stack();
        m_Tower[1] = new Stack();
        m_Tower[2] = new Stack();

	// Create move stack
        m_Moves    = new Stack();

        m_xC       = new int[3];
	resetTowers();
    }

    public void resetTowers() {
        graphicsDone = 0;

        for(; !m_Tower[m_Src].isEmpty(); m_Tower[m_Src].pop());
        for(; !m_Tower[m_Aux].isEmpty(); m_Tower[m_Aux].pop());
        for(; !m_Tower[m_Dst].isEmpty(); m_Tower[m_Dst].pop());
        for(; !m_Moves.isEmpty(); m_Moves.pop());
	
        m_XUnit = (getWidth() - 4 * m_Margin) / 3 / m_N;
        m_YUnit = Math.min((getHeight() - 4 * m_Margin) / m_N, m_XUnit * 2);

	for(int i = 0; i < 3; i++) {
	    m_xC[i] = ((i+1)*m_Margin) + (i*m_XUnit*m_N) + ((m_XUnit*m_N)/2);
	}

        m_YBase = getHeight() - m_YUnit;

        for(int j = 0; j < m_N; j++) {
            HanoiRing ring = new HanoiRing(m_N - j, j);
            int k          = (ring.getId() * m_XUnit) / 2;

            ring.setRect(m_xC[0]-k, m_YBase - (j+1) * m_YUnit, k * 2, m_YUnit);
            m_Tower[m_Src].push(ring);
        }

        m_Solving = false;
        repaint();
    }

    public void paint(Graphics g) {
        update(g);
    }

    public void update(Graphics g) {
        g.setColor(HanoiCanvas.BACKGROUND_COLOUR);
        g.fillRect(0, 0, getWidth(), getHeight());
        for(int i = 0; i < 3; i++) {
            drawTower(g, i);
	}

        if (m_Tower[m_Src].isEmpty() && m_Tower[m_Aux].isEmpty()) {
            graphicsDone = ++graphicsDone;
            if (graphicsDone == 1) {
                lapsedTime = System.currentTimeMillis() - startTime;
		if((lapsedTime < bestTime) || (bestTime == 0)) {
		    bestTime = lapsedTime;
		}
            }
        }

	int stringX = getWidth() 
	              - Font.getDefaultFont().stringWidth("ms") - m_XUnit;
	int stringY = Font.getDefaultFont().getHeight() + m_YUnit;

        g.setColor(HanoiCanvas.TEXT_COLOUR);
	g.drawString("ms", stringX, m_YUnit, Graphics.TOP|Graphics.LEFT);
	g.drawString("" + lapsedTime, stringX, 
		     m_YUnit, Graphics.TOP|Graphics.RIGHT);
	g.drawString("Last:", 
		     stringX - Font.getDefaultFont().stringWidth(" 0000"), 
		     m_YUnit, Graphics.TOP|Graphics.RIGHT);

	g.drawString("ms", stringX, 
		     stringY, Graphics.TOP|Graphics.LEFT);
	g.drawString("" + bestTime, stringX, 
		     stringY, Graphics.TOP|Graphics.RIGHT);
	g.drawString("Best:", 
		     stringX - Font.getDefaultFont().stringWidth(" 0000"), 
		     stringY, Graphics.TOP|Graphics.RIGHT);
    }

    private void drawTower(Graphics g, int tower) {

	// Draw tower
	g.setColor(HanoiCanvas.TOWER_BASE_COLOUR);
        g.fillRect(m_xC[tower] - m_Margin / 2, m_YBase - m_YUnit * (m_N+1), 
		   m_Margin, m_YBase - m_YUnit);

	// Outline tower
        g.setColor(HanoiCanvas.TOWER_OUTLINE_COLOUR);
        g.drawRect(m_xC[tower] - m_Margin / 2, m_YBase - m_YUnit * (m_N+1), 
		   m_Margin, m_YBase - m_YUnit);

        try {
	    Enumeration enum;
            for(enum = m_Tower[tower].elements(); enum.hasMoreElements();) {
                HanoiRing ring = (HanoiRing)enum.nextElement();
                ring.drawRing(g);
            }
        }
        catch (java.util.NoSuchElementException e) {
        }
    }

    public void updateInfo() {
        if(m_Solving) {
            makeMove();
	}
        repaint();
    }

    public void stop() {
        m_Solving    = false;
	graphicsDone = 1;
    }

    public void exit() {
	stop();
	m_Exiting = true;
    }

    public void solve() {
	if (graphicsDone != 0) {
	    resetTowers();
	}
        startTime = System.currentTimeMillis();
        Solution(m_N, m_Src, m_Aux, m_Dst);
        Stack stack = new Stack();
        for(; !m_Moves.isEmpty(); stack.push(m_Moves.pop()));
        m_Moves   = stack;
        m_Solving = true;

	// Kick off the thread to drive screen updates
	synchronized(this) {
	    this.notifyAll();
	}
    }

    public boolean isSolving() {
        return m_Solving;
    }

    public boolean isExiting() {
        return m_Exiting;
    }

    private void Solution(int i, int j, int k, int l) {
        if(i == 0) {
            return;
        } else {
            Solution(i - 1, j, l, k);
            m_Moves.push(new Integer(j));
            m_Moves.push(new Integer(l));
            Solution(i - 1, k, j, l);
        }
    }

    private void makeMove() {
        if(m_Moves.isEmpty()) {
            m_Solving = false;
            return;
        }

	int x = ((Integer)m_Moves.pop()).intValue();       // Tower moving from
	int y = ((Integer)m_Moves.pop()).intValue();         // Tower moving to

        if(!m_Tower[x].isEmpty()) {
            HanoiRing ring = (HanoiRing)m_Tower[x].pop();
            int i          = m_Tower[y].size();

            ring.setRect(m_xC[y] - (ring.getId() * m_XUnit) / 2, 
			 m_YBase - (i + 1) * m_YUnit, 
			 ring.getId() * m_XUnit, m_YUnit);
            m_Tower[y].push(ring);
        }
    }

    private boolean m_Solving; // = false
    private boolean m_Exiting; // = false
    private int     m_Margin;
    private int     m_N;
    private int     m_Src;
    private int     m_Aux;
    private int     m_Dst;
    private int     m_XUnit;
    private int     m_YUnit;
    private int     m_YBase;
    private int     m_xC[];
    private Stack   m_Tower[];
    private Stack   m_Moves;
    private int     graphicsDone = 0;
    private long    startTime;
    private long    lapsedTime;
    private long    bestTime;

}