Spielkarte beschriften

D

David Nienhaus

Gast
Hallo liebe Leute,

ich habe für ein sehr einfaches textbasiertes Spiel eine Spielkarte erstellt indem ich Quadrate so angeordnet habe, dass sie zusammen aussehen wie Räume mit Ausgängen. Wahrscheinlich geht das alles viel einfacher/eleganter, ich hatte aber leider kaum Zeit mich da genauer reinzufuchsen und habe deshalb ein bestehendes Programm, mit welchem man einfachste Formen(Quadrate, Kreise, Dreieck) zeichnen kann, übernommen und angepasst. Jetzt möchte ich die Räume gerne beschriften, damit man auch weiß, wo man sich gerade befindet. Die einzige Lösung die mir dazu eingefallen ist, ist es das ganze in die Klasse "Leinwand" reinzuschreiben (Diese Klasse erstellt die Zeichenfläche, auf der
Das kann aber ja nicht Sinn der Sache sein, da diese Klasse nur für die Leinwand zuständig sein sollte. Vielleicht kann mir jemand einen alternativen Weg erklären.
Hier der Code der Klasse Leinwand:

Code:
import java.awt.Color;
import java.awt.Font;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Leinwand
{

  private static Leinwand leinwandSingleton;

  /**
   * Fabrikmethode, die eine Referenz auf das einzige Exemplar
   * dieser Klasse zurückliefert. Wenn es von einer Klasse nur
   * genau ein Exemplar gibt, wird dieses als 'Singleton'
   * bezeichnet.
   */
  public static Leinwand gibLeinwand()
  {
    if (leinwandSingleton == null)
    {
      leinwandSingleton = new Leinwand("BlueJ Figuren Demo", 1400, 700, Color.white);
    }
    leinwandSingleton.setzeSichtbarkeit(true);
    return leinwandSingleton;
  }

  //  ----- Exemplarvariablen -----

  private JFrame fenster;
  private Zeichenflaeche zeichenflaeche;
  private Graphics2D graphic;
  private Color hintergrundfarbe;
  private Image leinwandImage;
  private List figuren;
  private Map figurZuShape; // Abbildung von Figuren zu Shapes

  /**
   * Erzeuge eine Leinwand.
   * @param titel  Titel, der im Rahmen der Leinwand angezeigt wird
   * @param breite  die gewünschte Breite der Leinwand
   * @param hoehe  die gewünschte Höhe der Leinwand
   * @param grundfarbe die Hintergrundfarbe der Leinwand
   */
  private Leinwand(String titel, int breite, int hoehe, Color grundfarbe)
  {
    titel = "Einkaufszentrum";
    fenster = new JFrame();
    zeichenflaeche = new Zeichenflaeche();
    fenster.setContentPane(zeichenflaeche);
    fenster.setTitle(titel);
    zeichenflaeche.setPreferredSize(new Dimension(breite, hoehe));
    hintergrundfarbe = grundfarbe;
    fenster.pack();
    figuren = new ArrayList();
    figurZuShape = new HashMap();
  }

  /**
   * Setze, ob diese Leinwand sichtbar sein soll oder nicht. Wenn die
   * Leinwand sichtbar gemacht wird, wird ihr Fenster in den
   * Vordergrund geholt. Diese Operation kann auch benutzt werden, um
   * ein bereits sichtbares Leinwandfenster in den Vordergrund (vor
   * andere Fenster) zu holen.
   * @param sichtbar boolean für die gewünschte Sichtbarkeit:
   * true für sichtbar, false für nicht sichtbar.
   */
  public void setzeSichtbarkeit(boolean sichtbar)
  {
    if (graphic == null)
    {
      // erstmaliger Aufruf: erzeuge das Bildschirm-Image und fülle
      // es mit der Hintergrundfarbe
      Dimension size = zeichenflaeche.getSize();
      leinwandImage = zeichenflaeche.createImage(size.width, size.height);
      graphic = (Graphics2D) leinwandImage.getGraphics();
      graphic.setColor(hintergrundfarbe);
      graphic.fillRect(0, 0, size.width, size.height);
      graphic.setColor(Color.black);
    }
    fenster.setVisible(sichtbar);
  }

  /**
   * Zeichne für das gegebene Figur-Objekt eine Java-Figur (einen Shape)
   * auf die Leinwand.
   * @param  figur  das Figur-Objekt, für das ein Shape gezeichnet
   *                 werden soll
   * @param  farbe  die Farbe der Figur
   * @param  shape  ein Objekt der Klasse Shape, das tatsächlich
   *                 gezeichnet wird
   */
  public void zeichne(Object figur, String farbe, Shape shape)
  {
    figuren.remove(figur); // entfernen, falls schon eingetragen
    figuren.add(figur); // am Ende hinzufügen
    figurZuShape.put(figur, new ShapeMitFarbe(shape, farbe));
    erneutZeichnen();
  }
 
  /**
   * Entferne die gegebene Figur von der Leinwand.
   * @param  figur  die Figur, deren Shape entfernt werden soll
   */
  public void entferne(Object figur)
  {
    figuren.remove(figur); // entfernen,falls schon eingetragen
    figurZuShape.remove(figur);
    erneutZeichnen();
  }

  /**
   * Setze die Zeichenfarbe der Leinwand.
   * @param  farbname der Name der neuen Zeichenfarbe.
   */
  public void setzeZeichenfarbe(String farbname)
  {
    if (farbname.equals("rot"))
      graphic.setColor(Color.red);
    else if (farbname.equals("schwarz"))
      graphic.setColor(Color.black);
    else if (farbname.equals("blau"))
      graphic.setColor(Color.blue);
    else if (farbname.equals("gelb"))
      graphic.setColor(Color.yellow);
    else if (farbname.equals("gruen"))
      graphic.setColor(Color.green);
    else if (farbname.equals("lila"))
      graphic.setColor(Color.magenta);
    else if (farbname.equals("weiss"))
      graphic.setColor(Color.white);
    else
      graphic.setColor(Color.black);
  }

  /**
   * Warte für die angegebenen Millisekunden.
   * Mit dieser Operation wird eine Verzögerung definiert, die
   * für animierte Zeichnungen benutzt werden kann.
   * @param  millisekunden die zu wartenden Millisekunden
   */
  public void warte(int millisekunden)
  {
    try
    {
      Thread.sleep(millisekunden);
    }
    catch (Exception e)
    {
      // Exception ignorieren
    }
  }

  /**
   * Zeichne erneut alle Figuren auf der Leinwand.
   */
  private void erneutZeichnen()
  {
    loeschen();
    for (Iterator i = figuren.iterator(); i.hasNext();)
    {
      ((ShapeMitFarbe) figurZuShape.get(i.next())).draw(graphic);
    }
    zeichenflaeche.repaint();
  }

  /**
   * Lösche die gesamte Leinwand.
   */
  private void loeschen()
  {
    Color original = graphic.getColor();
    graphic.setColor(hintergrundfarbe);
    Dimension size = zeichenflaeche.getSize();
    graphic.fill(new Rectangle(0, 0, size.width, size.height));
    graphic.setColor(original);
  }

  /************************************************************************
   * Interne Klasse Zeichenflaeche - die Klasse für die GUI-Komponente,
   * die tatsächlich im Leinwand-Fenster angezeigt wird. Diese Klasse
   * definiert ein JPanel mit der zusätzlichen Möglichkeit, das auf ihm
   * gezeichnet Image aufzufrischen (erneut zu zeichnen).
   */
  private class Zeichenflaeche extends JPanel
  {
    public void paint(Graphics g)
    {
      g.drawImage(leinwandImage, 0, 0, null);
      //Beschriftungen
      g.setFont(g.getFont().deriveFont(20f));
      g.drawString("Erdgeschoss", 280, 20);
      g.drawString("1. Stock", 1000, 20);
      g.drawString("Ein-/Ausgangsbereich", 30, 75);
      g.drawString("Koridor10" , 230 , 75);
      g.drawString("Bäcker" , 430 , 75);
      g.drawString("REWE" , 30 , 275);
      g.drawString("Koridor9" , 230 , 275);
      g.drawString("Koridor8" , 430 , 275);
      g.drawString("Koridor7" , 30 , 475);
      g.drawString("Toiletten" , 230 , 475);
      g.drawString("Koridor6" , 430 , 475);
      g.drawString("Lagerraum" , 730 , 75);
      g.drawString("Koridor0" , 930 , 75);
      g.drawString("Getränkemarkt" , 1130 , 75);
      g.drawString("Elektronikladen" , 730 , 275);
      g.drawString("Koridor1" , 930 , 275);
      g.drawString("Koridor2" , 1130 , 275);
      g.drawString("Koridor5" , 730 , 475);
      g.drawString("Koridor4" , 930 , 475);
      g.drawString("Koridor3" , 1130 , 475);
      g.dispose();
    }
  }

  /************************************************************************
   * Interne Klasse ShapeMitFarbe - Da die Klasse Shape des JDK nicht auch
   * eine Farbe mitverwalten kann, muss mit dieser Klasse die Verknüpfung
   * modelliert werden.
   */
  private class ShapeMitFarbe
  {
    private Shape shape;
    private String farbe;

    public ShapeMitFarbe(Shape shape, String farbe)
    {
      this.shape = shape;
      this.farbe = farbe;
    }

    public void draw(Graphics2D graphic)
    {
      setzeZeichenfarbe(farbe);
      graphic.fill(shape);
    }
  }

}

Relativ am Ende des Codes ist meine Auflistung mit den ganzen Raumbeschreibungen
 

MoxxiManagarm

Top Contributor
Ehrlich gesagt blicke ich bei deinem Code so wie er formatiert ist gar nicht durch.
Benutze bitte [code=java][/code]

Dass du die Strings alle einzeln zeichnest ist für mich der größte gedankliche Schrecken.
die elegantere Lösung wäre es die Räume alle in ein Model zu verpacken. Das Model besitzt auch die Namen. Jedes Model wird dann von einer Komponente (View) dargestellt. Die View holt sich den Namen aus dem Model. Im Model wäre auch die Logik zum Wechseln des Raumes und ihm sind die Figuren im Raum bekannt.

Die Einzelnen Komponenten werden mit einem LayoutManager passend angeordnet.
 
D

David Nienhaus

Gast
Oh, ich wusste nicht, dass das geht. Hier nochmal der Code:

Java:
import java.awt.Color;
import java.awt.Font;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Leinwand
{

  private static Leinwand leinwandSingleton;

  /**
   * Fabrikmethode, die eine Referenz auf das einzige Exemplar
   * dieser Klasse zurückliefert. Wenn es von einer Klasse nur
   * genau ein Exemplar gibt, wird dieses als 'Singleton'
   * bezeichnet.
   */
  public static Leinwand gibLeinwand()
  {
    if (leinwandSingleton == null)
    {
      leinwandSingleton = new Leinwand("BlueJ Figuren Demo", 1400, 700, Color.white);
    }
    leinwandSingleton.setzeSichtbarkeit(true);
    return leinwandSingleton;
  }

  //  ----- Exemplarvariablen -----

  private JFrame fenster;
  private Zeichenflaeche zeichenflaeche;
  private Graphics2D graphic;
  private Color hintergrundfarbe;
  private Image leinwandImage;
  private List figuren;
  private Map figurZuShape; // Abbildung von Figuren zu Shapes

  /**
   * Erzeuge eine Leinwand.
   * @param titel  Titel, der im Rahmen der Leinwand angezeigt wird
   * @param breite  die gewünschte Breite der Leinwand
   * @param hoehe  die gewünschte Höhe der Leinwand
   * @param grundfarbe die Hintergrundfarbe der Leinwand
   */
  private Leinwand(String titel, int breite, int hoehe, Color grundfarbe)
  {
    titel = "Einkaufszentrum";
    fenster = new JFrame();
    zeichenflaeche = new Zeichenflaeche();
    fenster.setContentPane(zeichenflaeche);
    fenster.setTitle(titel);
    zeichenflaeche.setPreferredSize(new Dimension(breite, hoehe));
    hintergrundfarbe = grundfarbe;
    fenster.pack();
    figuren = new ArrayList();
    figurZuShape = new HashMap();
  }

  /**
   * Setze, ob diese Leinwand sichtbar sein soll oder nicht. Wenn die
   * Leinwand sichtbar gemacht wird, wird ihr Fenster in den
   * Vordergrund geholt. Diese Operation kann auch benutzt werden, um
   * ein bereits sichtbares Leinwandfenster in den Vordergrund (vor
   * andere Fenster) zu holen.
   * @param sichtbar boolean für die gewünschte Sichtbarkeit:
   * true für sichtbar, false für nicht sichtbar.
   */
  public void setzeSichtbarkeit(boolean sichtbar)
  {
    if (graphic == null)
    {
      // erstmaliger Aufruf: erzeuge das Bildschirm-Image und fülle
      // es mit der Hintergrundfarbe
      Dimension size = zeichenflaeche.getSize();
      leinwandImage = zeichenflaeche.createImage(size.width, size.height);
      graphic = (Graphics2D) leinwandImage.getGraphics();
      graphic.setColor(hintergrundfarbe);
      graphic.fillRect(0, 0, size.width, size.height);
      graphic.setColor(Color.black);
    }
    fenster.setVisible(sichtbar);
  }

  /**
   * Zeichne für das gegebene Figur-Objekt eine Java-Figur (einen Shape)
   * auf die Leinwand.
   * @param  figur  das Figur-Objekt, für das ein Shape gezeichnet
   *                 werden soll
   * @param  farbe  die Farbe der Figur
   * @param  shape  ein Objekt der Klasse Shape, das tatsächlich
   *                 gezeichnet wird
   */
  public void zeichne(Object figur, String farbe, Shape shape)
  {
    figuren.remove(figur); // entfernen, falls schon eingetragen
    figuren.add(figur); // am Ende hinzufügen
    figurZuShape.put(figur, new ShapeMitFarbe(shape, farbe));
    erneutZeichnen();
  }
 
  /**
   * Entferne die gegebene Figur von der Leinwand.
   * @param  figur  die Figur, deren Shape entfernt werden soll
   */
  public void entferne(Object figur)
  {
    figuren.remove(figur); // entfernen,falls schon eingetragen
    figurZuShape.remove(figur);
    erneutZeichnen();
  }

  /**
   * Setze die Zeichenfarbe der Leinwand.
   * @param  farbname der Name der neuen Zeichenfarbe.
   */
  public void setzeZeichenfarbe(String farbname)
  {
    if (farbname.equals("rot"))
      graphic.setColor(Color.red);
    else if (farbname.equals("schwarz"))
      graphic.setColor(Color.black);
    else if (farbname.equals("blau"))
      graphic.setColor(Color.blue);
    else if (farbname.equals("gelb"))
      graphic.setColor(Color.yellow);
    else if (farbname.equals("gruen"))
      graphic.setColor(Color.green);
    else if (farbname.equals("lila"))
      graphic.setColor(Color.magenta);
    else if (farbname.equals("weiss"))
      graphic.setColor(Color.white);
    else
      graphic.setColor(Color.black);
  }

  /**
   * Warte für die angegebenen Millisekunden.
   * Mit dieser Operation wird eine Verzögerung definiert, die
   * für animierte Zeichnungen benutzt werden kann.
   * @param  millisekunden die zu wartenden Millisekunden
   */
  public void warte(int millisekunden)
  {
    try
    {
      Thread.sleep(millisekunden);
    }
    catch (Exception e)
    {
      // Exception ignorieren
    }
  }

  /**
   * Zeichne erneut alle Figuren auf der Leinwand.
   */
  private void erneutZeichnen()
  {
    loeschen();
    for (Iterator i = figuren.iterator(); i.hasNext();)
    {
      ((ShapeMitFarbe) figurZuShape.get(i.next())).draw(graphic);
    }
    zeichenflaeche.repaint();
  }

  /**
   * Lösche die gesamte Leinwand.
   */
  private void loeschen()
  {
    Color original = graphic.getColor();
    graphic.setColor(hintergrundfarbe);
    Dimension size = zeichenflaeche.getSize();
    graphic.fill(new Rectangle(0, 0, size.width, size.height));
    graphic.setColor(original);
  }

  /************************************************************************
   * Interne Klasse Zeichenflaeche - die Klasse für die GUI-Komponente,
   * die tatsächlich im Leinwand-Fenster angezeigt wird. Diese Klasse
   * definiert ein JPanel mit der zusätzlichen Möglichkeit, das auf ihm
   * gezeichnet Image aufzufrischen (erneut zu zeichnen)
   */
  private class Zeichenflaeche extends JPanel
  {
    public void paint(Graphics g)
    {
      g.drawImage(leinwandImage, 0, 0, null);
      //Beschrifte die Räume
      g.setFont(g.getFont().deriveFont(20f));
      g.drawString("Erdgeschoss", 280, 20);
      g.drawString("1. Stock", 1000, 20);
      g.drawString("Ein-/Ausgangsbereich", 30, 75);
      g.drawString("Koridor10" , 230 , 75);
      g.drawString("Bäcker" , 430 , 75);
      g.drawString("REWE" , 30 , 275);
      g.drawString("Koridor9" , 230 , 275);
      g.drawString("Koridor8" , 430 , 275);
      g.drawString("Koridor7" , 30 , 475);
      g.drawString("Toiletten" , 230 , 475);
      g.drawString("Koridor6" , 430 , 475);
      g.drawString("Lagerraum" , 730 , 75);
      g.drawString("Koridor0" , 930 , 75);
      g.drawString("Getränkemarkt" , 1130 , 75);
      g.drawString("Elektronikladen" , 730 , 275);
      g.drawString("Koridor1" , 930 , 275);
      g.drawString("Koridor2" , 1130 , 275);
      g.drawString("Koridor5" , 730 , 475);
      g.drawString("Koridor4" , 930 , 475);
      g.drawString("Koridor3" , 1130 , 475);
      g.dispose();
    }
  }

  /************************************************************************
   * Interne Klasse ShapeMitFarbe - Da die Klasse Shape des JDK nicht auch
   * eine Farbe mitverwalten kann, muss mit dieser Klasse die Verknüpfung
   * modelliert werden.
   */
  private class ShapeMitFarbe
  {
    private Shape shape;
    private String farbe;

    public ShapeMitFarbe(Shape shape, String farbe)
    {
      this.shape = shape;
      this.farbe = farbe;
    }

    public void draw(Graphics2D graphic)
    {
      setzeZeichenfarbe(farbe);
      graphic.fill(shape);
    }
  }

}

Puh, das klingt erst einmal danach, als müsste ich meinen gesamten Code neu machen. Dafür habe ich leider nicht mehr genug Zeit. Ich dachte, vielleicht gäbe es eine flotte Alternative, die etwas eleganter ist :rolleyes::D
Ich dank dir trotzdem sehr für die Hilfe :)
 
D

David Nienhaus

Gast
Also um genau zu sein bis morgen um 12 Uhr. Da muss ich das Programm vorstellen. Ich hoffe einfach mal mir wird da kein Strick draus gedreht, da es eigentlich gar nicht verlangt war die Räume zu beschriften.
 

MoxxiManagarm

Top Contributor
Achso ne dann wird das nix hätte erst morgen Abend dafür Zeit gehabt. Solange dein Programm im großen und ganzen das tut was es soll wird's schon einiger Maßen gut gehen. Ansonsten kannst du auch in den meisten Fällen offen sagen, wo du verbesserungspotenzial selbst siehst aber es nicht implementieren konntest.
 
Ähnliche Java Themen

Ähnliche Java Themen


Oben