From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../hjp5/examples/Puzzle.java | 345 +++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/examples/Puzzle.java (limited to 'Master/Reference Architectures and Patterns/hjp5/examples/Puzzle.java') 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 -- cgit v1.2.3