summaryrefslogtreecommitdiffstats
path: root/Master/Reference Architectures and Patterns/hjp5/examples/Puzzle.java
diff options
context:
space:
mode:
Diffstat (limited to 'Master/Reference Architectures and Patterns/hjp5/examples/Puzzle.java')
-rw-r--r--Master/Reference Architectures and Patterns/hjp5/examples/Puzzle.java345
1 files changed, 345 insertions, 0 deletions
diff --git a/Master/Reference Architectures and Patterns/hjp5/examples/Puzzle.java b/Master/Reference Architectures and Patterns/hjp5/examples/Puzzle.java
new file mode 100644
index 0000000..68ccfd0
--- /dev/null
+++ b/Master/Reference Architectures and Patterns/hjp5/examples/Puzzle.java
@@ -0,0 +1,345 @@
+/**
+ * @(#)Puzzle.java 1.000 97/07/23
+ *
+ * Copyright (c) 1997 Guido Krueger. All Rights Reserved.
+ *
+ * Dieses Applet ist die Implementierung eines Schiebepuzzles
+ * mit 4 x 4 Feldern. Auf den zunächst unsortierten Spielsteinen
+ * werden die Bestandteile eines Images angezeigt, die dann per
+ * Drag & Drop sortiert werden können. Der einzig erlaubte Zug
+ * besteht darin, einen Stein in die benachbarte Lücke zu
+ * verschieben. Durch Klicken auf den Rahmen kann die Sortierung
+ * umgekehrt werden.
+ *
+ * Das applet-Tag erwartet folgende Parameter:
+ *
+ * bordersize = Breite des Spielfeldrandes
+ * src = Name der Bilddatei (gif oder jpeg)
+ *
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.applet.*;
+import java.util.*;
+
+public class Puzzle
+extends Applet
+{
+ int aFields[][]; //Brett mit allen Feldern
+ Image image; //Bildspeicher
+ int bordersize; //Randbreite
+ Dimension fieldsize; //Größe eines Feldes
+ Dimension imagesize; //Größe des Bildes
+ Point sourcefield; //Bei Mausklick ausgewähltes Feld
+ Point lastpoint; //Ursprung des letzten Rechtecks
+ Point drawoffset; //Offset zur Mausdragposition
+
+ public void init()
+ {
+ aFields = new int[4][4];
+ sourcefield = new Point(-1, -1);
+ lastpoint = new Point(-1, -1);
+ drawoffset = new Point(0,0);
+ bordersize = Integer.parseInt(getParameter("bordersize"));
+ if (bordersize < 1 || bordersize > 50) {
+ bordersize = 5;
+ }
+ setBackground(Color.lightGray);
+ addMouseListener(new MyMouseListener());
+ addMouseMotionListener(new MyMouseMotionListener());
+ prepareImage();
+ randomizeField(true);
+ }
+
+ public void update(Graphics g)
+ {
+ Image dbImage;
+ Graphics dbGraphics;
+
+ //Double-Buffer initialisieren
+ dbImage = createImage(getSize().width,getSize().height);
+ dbGraphics = dbImage.getGraphics();
+ //Hintergrund löschen
+ dbGraphics.setColor(getBackground());
+ dbGraphics.fillRect(0,0,getSize().width,getSize().height);
+ //Vordergrund zeichnen
+ dbGraphics.setColor(getForeground());
+ paint(dbGraphics);
+ //Offscreen-Image anzeigen
+ g.drawImage(dbImage,0,0,this);
+ dbGraphics.dispose();
+ }
+
+ public void paint(Graphics g)
+ {
+ paintBorder(g);
+ paintField(g);
+ }
+
+ /**
+ * Zeichnet den Rahmen des Spielbretts.
+ */
+ private void paintBorder(Graphics g)
+ {
+ Insets insets = getInsets();
+ Dimension size = getSize();
+ size.height -= insets.top + insets.bottom;
+ size.width -= insets.left + insets.right;
+ fieldsize = new Dimension();
+ fieldsize.width = (size.width - (2 * bordersize)) / 4;
+ fieldsize.height = (size.height - (2 * bordersize)) / 4;
+ g.setColor(Color.black);
+ g.drawRect(
+ insets.left,
+ insets.top,
+ size.width - 1,
+ size.height - 2
+ );
+ g.drawRect(
+ insets.left + bordersize,
+ insets.top + bordersize,
+ 4 * fieldsize.width,
+ 4 * fieldsize.height
+ );
+ }
+
+ /**
+ * Zeichnet die Spielsteine auf dem Brett.
+ */
+ private void paintField(Graphics g)
+ {
+ int imagenumber, image_i, image_j;
+ Insets insets = getInsets();
+ Point topleft = new Point();
+ topleft.x = insets.left + bordersize;
+ topleft.y = insets.top + bordersize;
+ g.setColor(Color.black);
+ for (int i = 0; i <= 3; ++i) {
+ for (int j = 0; j <= 3; ++j) {
+ imagenumber = aFields[i][j];
+ if (imagenumber == 15) {
+ //Lücke zeichnen
+ g.fillRect(
+ topleft.x + j * fieldsize.width,
+ topleft.y + i * fieldsize.height,
+ fieldsize.width,
+ fieldsize.height
+ );
+ } else {
+ //Image darstellen
+ image_i = imagenumber / 4;
+ image_j = imagenumber % 4;
+ g.drawImage(
+ image,
+ topleft.x + j * fieldsize.width,
+ topleft.y + i * fieldsize.height,
+ topleft.x + j * fieldsize.width + fieldsize.width,
+ topleft.y + i * fieldsize.height + fieldsize.height,
+ image_j * (imagesize.width / 4),
+ image_i * (imagesize.height / 4),
+ image_j * (imagesize.width / 4) + imagesize.width / 4,
+ image_i * (imagesize.height / 4) + imagesize.height / 4,
+ this
+ );
+ //Rahmen
+ g.drawRect(
+ topleft.x + j * fieldsize.width,
+ topleft.y + i * fieldsize.height,
+ fieldsize.width,
+ fieldsize.height
+ );
+ //Beschriftung
+ g.drawString(
+ "" + imagenumber,
+ topleft.x + j * fieldsize.width + 2,
+ topleft.y + i * fieldsize.height + 12
+ );
+ }
+ }
+ }
+ }
+
+ /**
+ * Lädt das Bild.
+ */
+ private void prepareImage()
+ {
+ //Bild laden
+ image = getImage(getDocumentBase(),getParameter("src"));
+ MediaTracker mt = new MediaTracker(this);
+ mt.addImage(image, 0);
+ try {
+ //Warten, bis das Image vollständig geladen ist,
+ mt.waitForAll();
+ } catch (InterruptedException e) {
+ //nothing
+ }
+ imagesize = new Dimension();
+ imagesize.height = image.getHeight(this);
+ imagesize.width = image.getWidth(this);
+ }
+
+ /**
+ * Mischt die Steine auf dem Spielfeld.
+ */
+ private void randomizeField(boolean unordered)
+ {
+ int i, j, k, tmp;
+
+ //Zuerst sortieren...
+ for (i = 0; i <= 15; ++i) {
+ aFields[i / 4][i % 4] = i;
+ }
+ //Dann mischen...
+ if (unordered) {
+ Random rand = new Random(System.currentTimeMillis());
+ for (i = 0; i < 20; ++i) {
+ j = Math.abs(rand.nextInt()) % 16;
+ k = Math.abs(rand.nextInt()) % 16;
+ tmp = aFields[j / 4][j % 4];
+ aFields[j / 4][j % 4] = aFields[k / 4][k % 4];
+ aFields[k / 4][k % 4] = tmp;
+ }
+ }
+ }
+
+ class MyMouseListener
+ extends MouseAdapter
+ {
+ /**
+ * Maustaste gedrückt.
+ */
+ public void mousePressed(MouseEvent event)
+ {
+ sourcefield = getFieldFromCursor(event.getX(), event.getY());
+ if (sourcefield.x == -1 || sourcefield.y == -1) {
+ swapRandomization();
+ repaint();
+ }
+ lastpoint.x = -1;
+ lastpoint.y = -1;
+ }
+
+ /**
+ * Maustaste losgelassen.
+ */
+ public void mouseReleased(MouseEvent event)
+ {
+ if (sourcefield.x != -1 && sourcefield.y != -1) {
+ Point destfield;
+ destfield = getFieldFromCursor(event.getX(), event.getY());
+ if (destfield.x != -1 && destfield.y != -1) {
+ if (aFields[destfield.y][destfield.x] == 15) {
+ if (areNeighbours(sourcefield, destfield)) {
+ aFields[destfield.y][destfield.x] =
+ aFields[sourcefield.y][sourcefield.x];
+ aFields[sourcefield.y][sourcefield.x] = 15;
+ }
+ }
+ }
+ repaint();
+ }
+ sourcefield.x = -1;
+ sourcefield.y = -1;
+ }
+
+ /**
+ * Liefert den zur Mausposition passenden horizontalen und
+ * vertikalen Index des darunterliegenden Steins. Liegt der
+ * Punkt auf dem Rahmen, wird (-1,-1) zurückgegeben.
+ */
+ private Point getFieldFromCursor(int x, int y)
+ {
+ Insets insets = getInsets();
+ Point topleft = new Point();
+ topleft.x = insets.left + bordersize;
+ topleft.y = insets.top + bordersize;
+ Point ret = new Point(-1, -1);
+ if (x >= topleft.x) {
+ if (x < topleft.x + 4 * fieldsize.width) {
+ if (y >= topleft.y) {
+ if (y < topleft.y + 4 * fieldsize.height) {
+ ret.x = (x - topleft.x) / fieldsize.width;
+ ret.y = (y - topleft.y) / fieldsize.height;
+ drawoffset.x = x - topleft.x -
+ ret.x * fieldsize.width;
+ drawoffset.y = y - topleft.y -
+ ret.y * fieldsize.height;
+ }
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Testet, ob die durch p1 und p2 bezeichneten Spielsteine
+ * Nachbarn sind.
+ */
+ private boolean areNeighbours(Point p1, Point p2)
+ {
+ int aNeighbours[][] = {{-1,0},{0,-1},{0,1},{1,0}};
+ for (int i = 0; i < aNeighbours.length; ++i) {
+ if (p1.x + aNeighbours[i][0] == p2.x) {
+ if (p1.y + aNeighbours[i][1] == p2.y) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Kehrt die Steineordnung um: falls sie sortiert sind,
+ * werden sie gemischt und umgekehrt.
+ */
+ private void swapRandomization()
+ {
+ //Sind die Felder sortiert?
+ boolean sorted = true;
+ for (int i = 0; i <= 15; ++i) {
+ if (aFields[i / 4][i % 4] != i) {
+ sorted = false;
+ break;
+ }
+ }
+ //Neu mischen bzw. sortieren
+ randomizeField(sorted);
+ }
+ }
+
+ class MyMouseMotionListener
+ extends MouseMotionAdapter
+ {
+ /**
+ * Maus wurde bei gedrückter Taste bewegt.
+ */
+ public void mouseDragged(MouseEvent event)
+ {
+ if (sourcefield.x != -1 && sourcefield.y != -1) {
+ Graphics g = getGraphics();
+ g.setXORMode(getBackground());
+ g.setColor(Color.black);
+ //Das zuletzt gezeichnete Rechteck entfernen
+ if (lastpoint.x != -1) {
+ g.drawRect(
+ lastpoint.x - drawoffset.x,
+ lastpoint.y - drawoffset.y,
+ fieldsize.width,
+ fieldsize.height
+ );
+ }
+ //Neues Rechteck zeichnen
+ g.drawRect(
+ event.getX() - drawoffset.x,
+ event.getY() - drawoffset.y,
+ fieldsize.width,
+ fieldsize.height
+ );
+ lastpoint.x = event.getX();
+ lastpoint.y = event.getY();
+ g.dispose();
+ }
+ }
+ }
+} \ No newline at end of file