/* * (C) 2004 - Geotechnical Software Services * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ import java.awt.*; import javax.swing.*; import no.geosoft.cc.graphics.*; /** * G demo program. Demonstrates: * * <ul> * <li>A sample game application * <li>Graphics animation * <li>GObject reparenting * </ul> * * @author <a href="mailto:info@geosoft.no">GeoSoft</a> */ public class Demo14 extends JFrame { private TowersOfHanoi towersOfHanoi_; private GWindow window_; private Peg[] pegs_; private int nDiscs_; private JButton startButton_; public Demo14 (int nDiscs) { super ("G Graphics Library - Demo 14"); setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); nDiscs_ = nDiscs; // Create the graphic canvas window_ = new GWindow (new Color (200, 230, 200)); getContentPane().add (window_.getCanvas()); // Create scene GScene scene = new GScene (window_); double w0[] = {0.0, 0.0, 0.0}; double w1[] = {4.0, 0.0, 0.0}; double w2[] = {0.0, nDiscs_ * 2, 0.0}; scene.setWorldExtent (w0, w1, w2); // Add title object and add to scene scene.add (new Title()); // Create the 3 pegs and add to the scene int nPegs = 3; pegs_ = new Peg[nPegs]; for (int i = 0; i < nPegs; i++) { pegs_[i] = new Peg (i + 1.0); scene.add (pegs_[i]); } // Create the discs and add to the first peg for (int i = 0; i < nDiscs; i++) { Disc disc = new Disc ((double) (nDiscs - i) / nDiscs); disc.setPosition (1.0, i); pegs_[0].add (disc); } pack(); setSize (new Dimension (500, 500)); setVisible (true); // Create the puzzle and execute the solution towersOfHanoi_ = new TowersOfHanoi(); towersOfHanoi_.solve(); } public void discMoved (int source, int destination) { // This is the disc to move Disc disc = (Disc) pegs_[source].getChild (pegs_[source].getNChildren()-1); double y0 = disc.getY(); double y1 = nDiscs_ + 4.0; double x0 = pegs_[source].getX(); double x1 = pegs_[destination].getX(); // Animate vertical up movement double step = 0.2; double y = y0; while (y < y1) { disc.setPosition (x0, y); disc.redraw(); window_.refresh(); y += step; } // Reparent peg pegs_[source].remove (disc); pegs_[destination].add (disc); // Animate horizontal movement step = 0.05; double x = x0; while (x != x1) { disc.setPosition (x, y); disc.redraw(); window_.refresh(); x += (x1 > x0 ? step : -step); if (Math.abs (x - x1) < 0.01) x = x1; } // Animate vertical down movement step = 0.2; y = y1; y1 = pegs_[destination].getNChildren() - 1; while (y > y1) { if (Math.abs (y - y1) < 0.01) y = y1; disc.setPosition (x, y); disc.redraw(); window_.refresh(); y -= step; } } /** * Graphics object for canvas title. */ class Title extends GObject { private GSegment anchor_; public Title() { GStyle style = new GStyle(); style.setLineStyle (GStyle.LINESTYLE_INVISIBLE); style.setForegroundColor (new Color (100, 100, 200)); style.setFont (new Font ("serif", Font.PLAIN, 36)); setStyle (style); anchor_ = new GSegment(); addSegment (anchor_); GText text = new GText ("Towers of Hanoi", GPosition.SOUTHEAST); anchor_.setText (text); } public void draw() { anchor_.setGeometry (20, 20); } } /** * Graphics representation of a peg. */ class Peg extends GObject { private double x_; private GSegment peg_; private double[] xy_; public Peg (double x) { x_ = x; GStyle style = new GStyle(); style.setBackgroundColor (new Color (100, 100, 100)); setStyle (style); peg_ = new GSegment(); addSegment (peg_); xy_ = new double[] {x_ - 0.05, 0.0, x_ - 0.05, nDiscs_ + 2, x_ + 0.05, nDiscs_ + 2, x_ + 0.05, 0.0, x_ - 0.05, 0.0}; } public double getX() { return x_; } public void draw() { peg_.setGeometryXy (xy_); } } /** * Graphics representation of a disc. */ class Disc extends GObject { private double size_; private GSegment disc_; private double x_, y_; public Disc (double size) { size_ = size; GStyle style = new GStyle(); style.setForegroundColor (new Color (255, 0, 0)); style.setBackgroundColor (new Color (255, 150, 150)); setStyle (style); disc_ = new GSegment(); addSegment (disc_); } public void setPosition (double x, double y) { x_ = x; y_ = y; } public double getY() { return y_; } public void draw() { double[] xy = new double[] {x_ - size_ / 2.0, y_, x_ - size_ / 2.0, y_ + 1.0, x_ + size_ / 2.0, y_ + 1.0, x_ + size_ / 2.0, y_, x_ - size_ / 2.0, y_}; disc_.setGeometryXy (xy); } } /** * Class for solving the "Towers of Hanoi" puzzle. */ class TowersOfHanoi { public void solve() { solve (nDiscs_, 0, 2, 1); } private void solve (int nDiscs, int source, int destination, int auxiliary) { if (nDiscs == 1) discMoved (source, destination); else if (nDiscs > 1) { solve (nDiscs - 1, source, auxiliary, destination); discMoved (source, destination); solve (nDiscs - 1, auxiliary, destination, source); } } } public static void main (String[] args) { int nDiscs = 8; Demo14 demo = new Demo14 (nDiscs); } }