Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Ich habe einen Code geschrieben, der mir ein Feld z.b. bei der Koordinate 0,0 (x,y) zeichnet
nun möchte ich mit Hilfe einer Schleife, dass er je nach Eingabe der Länge der zu zeichnenden Felder (also 1 steht dann für 1x1 Feld, 2 steht für 2x2 Felder) vollständig zeichnet.
Bei meinem derzeitigem Code sieht das ganze bei 4x4 Feldern so hier aus:
Ihr erkennt das Problem sicher direkt.
Ab hier fehlt mir einfach das mathematische Verständnis, wie ich sowas in eine Schleife einbaue bzw. definiere.
Naja, im Prinzip kannst du zwei Schleifen (ineinander verschachtelt) verwenden. Jeweils eine für die X-Dimension und eine für die Y-Dimension. Beide mit derselben Länge/Anzahl an Iterationen.
Wie du es aber konkret machen musst, um da was zu zeichnen, hängt davon ab, welche API genau du verwendest, um zu zeichnen.
Danke für die Antwort,
ich überschreibe die PaintComponent Methode in einem Panel.
Das Zeichnen bekomme ich hin aber mir fehlt das Verständnis mathematischer Natur.
Ich versuche es mal so wie du gesagt hast.
Was genau meinst du denn mit "mathematisch"? Mit "Mathematik" hat das Problem eigentlich nichts zu tun. Das Problem hat ja auch nichts mit "3D" zu tun. Du hast ja nur zwei Dimensionen, also 2D.
Da möchte ich mich mal wieder mit dem melden, mit dem ich mich immer wieder einmische:
Bei der Programmierung (speziell der objektorientierten) ist es immer gut, sich alles genau vorzustellen. Der große Vorteil ist, dass man so eben eine sehr gute Vorstellung bekommt - auch Du!
Du musst Dir da ja nichts vorstellen. Du kannst es real anpacken. Nmm Dir Stift und Papier. Und nun machst Du es.
Wie malst Du die Rechtecke auf? Wie bekommst Du das Endergebnis aufs Papier?
Einen möglichen Algorithmus hast Du schon: Du fängst an einer Ecke an um da ein erstes Quadrat zu zeichen. Und dan zeichnest Du ein Quadrat nach dem anderen.
Ist das wirklich dein Vorgehen? Oder findest Du ein anderes Vorgehen? Ein Vorgehen, das evtl. schneller geht?
Oder wenn Du Probleme hast, da in abstrakten Quadraten zu denken: Das sieht doch z.B. aus wie ein Regal. Wie ist denn so ein Regal aufgebaut? Sind das einfach nur Kisten, die aneinander gereiht werden? (Wird es bestimmt auch geben.) Oder hast Du da evtl. schon anderes regal gesehen? Also z.B. mit Brettern irgendwas?
Hilft Dir evtl. so eine konkrete Vorstellung? Das ist etwas, das ich nur empfehlen kann. In den Anfängen der objektorientierten Entwicklung, z.B. bei der Sprache Smalltalk wurde das auch immer gut visualisiert: Instanzen waren dann Objekte, die sich Nachrichten geschickt haben. Das ging (aus meiner Sicht) dann auch in die Richtung, das abstrakte zu reduzieren.
Die Lösung funktioniert, aber ich würde dennoch gerne auf deine Antwort eingehen.
Ich habe vorhin angefangen mir aufzuschreiben, welche Kästchen gezeichnet werden müssen, erfolglos.
Ich habe z.b. 4x4 Kästchen, also muss ich
in Y0 die Kästchen 0,1,2,3 zeichnen.
In Y1 die Kästchen 0,1,2,3
In Y2 die Kästchen 0,1,2,3
In Y3 die Kästchen 0,1,2,3
Das sind 4x4=16 Kästchen
Ich bräuchte also eine Schleife(Y) die erst bei Y0 anfängt, da von X0-X3 geht und sich dann erhöht. Also ist die Idee mit den verschachtelten Schleifen meiner Meinung nach eigentlich die beste.
Also im Grundprinzip baue ich damit Reihe für Reihe auf.
Ich weiß nicht wieso ich nicht selber drauf kam...
Gibt es eine bessere Vorgehensweise oder einen anderen Denkansatz?
Worauf ich hinaus wollte ist einfach etwas anderes:
Anstatt Kästchen zu malen, malst Du nur Linien.
Um dieses Bild von 4x4 Kästchen zu malen, würde ich halt einfach erst 5 horizontale Linien malen mit Länge 4*Breite, jeweils im Anstand der gewünschten Höhe (Bei Dir sollen es Quadrate sein, also Höhe = Breite). Im Anschluss würde ich die 5 vertikalen Linien malen im Abstand der Breite und ich wäre fertig.
Das Vorgehen kann man dann also etwas verallgemeinern. Was ist notwendig für n*n Kästchen?
Um 1 Kästchen zu haben, brauchst Du zwei horizontale und zwei vertikale Linien.
Um 2x2 Kästchen zu haben, brauchst Du drei horizontale und drei vertikale Linien.
...
um n*n Kästchen zu haben, brauchst Du n+1 horizontale und n+1 vertikale Linien.
Die Länge jeder Linie ist n mal gewünschte Breite (oder Länge)
Der Abstand zwischen zwei Linien ist die gewünschte Breite (oder Länge)
Daher noch einmal mein Vorschlag: Statt es Dir abstrakt vorzustellen: Spiel es durch! Stift und Papier ist Dein Freund! Mal es einfach ein paar Mal auf und schau, wie Du es möglichst einfach aufmalen kannst. Den Weg versuchst Du dann so zu beschreiben, dass es jeder nachvollziehen kann, selbst wenn er die Aufgabe nicht kennt (Meine Beschreibung ist noch nicht ausreichend. Die Anfangspunkte jeder Linie sind noch nicht gegeben. Die horizontalen Linien müssen natürlich genau übereinnder sein - nur in der Höhe versetzt.)
Gerade wenn Du Probleme hast, die alles im Kopf vorzustellen ist das notwendig! Übe es also direkt von Anfang an! Spätestens bei den Abstrakten Datentypen wirst Du es brauchen. Bei verketteten Listen und Bäumen und so geht nichts über ein Aufmalen der jeweiligen Situation und dem Drchspielen der notwendigen Schritte mit Stift und Papier!
Es ist also schlicht normal, dass Du da gewisse Probleme hast. Das hat jeder (natürlich in unterschiedlicher Ausprägung)! Daher diese (eindringliche) Empfehlung. Stift und Papier oder im Büro im Team ein Whiteboard sind das beste Hilfsmittel! Oder bei fachlichen Dingen teilweise eine visualisierte Darstellung der Zusammenhänge die dann zur offiziellen Doku gehören und die dann eigentlich immer offen ist, wenn man da etwas macht.
Das finde ich aber deutlich komplizierter, auch wenn der Code kürzer ist.
Wie soll ich das angehen?
Mein Code bisher:
Java:
int blockX = mousePositionX * TILESIZE * ZOOM;
int blockY = mousePositionY * TILESIZE * ZOOM;
final int BLOCKSIZE = TILESIZE * ZOOM;
for (int x = blockX; x < ((tilePanel.getAmountOfSelectedBlocks() + 1) * BLOCKSIZE); x += BLOCKSIZE) { //+1 nur bei zweiter Methode
for (int y = blockY; y < ((tilePanel.getAmountOfSelectedBlocks() + 1) * BLOCKSIZE); y += BLOCKSIZE) {
g.drawLine(x, y, x + BLOCKSIZE, y);
g.drawLine(x, y, x, y + BLOCKSIZE);
}}
Dieser verhält sich absolut merkwürdig.
Ich kann es noch nichtmal erklären, was er macht.
Wäre es nicht besser den Code eher simpel zu halten, als unverständlich?
Die Idee ist dabei natürlich weiterhin, dass der Code übersichtlich ist und bleibt. Dazu muss man aber natürlich den Algorthmus als erstes verständlich formulieren. Das ist und bleibt immer der erste Schritt und am Anfang solltest Du den auch genau so durchführen, z.B. als Kommentar im Editor.
So ist Dein angepasster Code ist auch nicht das, was ich an möglicher Lösung skizziert habe. Wenn Du das mit den Horizontalen und Vertikalen Linien aufgreifen willst, dann
a) Mach das einmal manuell mit Stift und Papier für z.B. n = 5. Hast Du das hin bekommen?
b) Wie hast Du es hin bekommen? Kannst Du die Schritte genau bechreiben? Und zwar so genau, dass Du diese Anleitung an jemand anderes geben kannst und der kann es dann auch.
c) Wie sind die Schritte anzupassen, wenn Du statt n = 5 ein n=6 oder n=7 hast? Kannst Du die Schritte verallgemeinern?
Und dann kommt am Ende etwas gut lesbarer bei raus - dazu kann man dann auch Methoden verwenden. Deine Paint Methode könnte dann z.B. beinhalten:
Java:
drawVerticalLines(g);
drawHorizontalLines(g);
==> Damit ist der Code klar verständlich: Erst werden die vertikalen und dann die horizontalen Linien gezeichnet.
Ich hoffe, dass das mit dem möglichen Vorgehen auch soweit gut verständlich war, denn ich bin davon überzeugt, dass man so meist am einfachsten zum Ziel kommt.
Ich wünsche Dir auf jeden Fall weiter viel Spaß und Erfolg mit Deiner weiteren Entwicklung!
Vielen Dank!
Mein Projekt wird immer größer und momentan bin ich dran den Code zu säubern und Bugs zu beheben.
Wenn ich rausgefunden habe, wie ich intelliJ mit Github synchronisieren kann, kann ich gerne mal die Repo teilen.
Schön, dass du Erfolg hattest. Ich möchte allerdings auch mal meinen Senf dazu geben und sagen, dass meiner Meinung nach dieser Algorithmus schon eher schwer zu verstehen ist. Für außenstehende und ich denke auch für dich selbst (nach ein paar Wochen).
Mein alternativer Vorschlag: Bleib bei der drawRect Methode von Graphics. Denn, das ist ja das was du eigentlich tun willst; Rechtecke zeichnen.
Textuelle Beschreibung eines Algorithmus kann schon ziemlich komplex werden, aber ich versuche es einmal:
Um Verwirrung zu vermeiden sollten wir zwischen den Koordinaten der Rechtecke (im Grid) und der eigentlichen x/y Koordinaten der drawRect Methode unterscheiden. Rechtecke sprechen wir daher per "Zeile,Spalte" an. Die drawRect Methode behält das "x,y".
Stell dir das Grid so vor wie es hinterher aussehen soll (wie in deinem Beitrag #5). Wie würden wir also anfangen das erste Rechteck oben links zu zeichnen? (mittels drawRect). wir brauchen dafür: die x/y Koordinate, die Breite, die Höhe. Breite und Höhe sind Konstant; also kein Problem.
x/y von drawRect geht von der linken oberen Ecke aus. d.h. Um unser erstes Rechteck zu zeichnen brauchen wir x=0; y=0;
Okay, das war leicht. Das nächste Rechteck soll rechts davon gezeichnet werden. Jetzt kommen wir zur eigentlichen Berechnung der x/y drawRect Koordinaten. y ist weiterhin 0. x muss jetzt genau da sein wo das vorherige Rechteck aufhört. Das wissen wir weil wir die Breite des Rechtecks kennen. Also x=Breite.
Soweit ist noch nicht unbedingt eine Gesetzmäßigkeit erkennbar. Die wird im nächsten Schritt klar. Denn welchen Wert muss x haben wenn das dritte Rechteck gezeichnet werden soll? Es befinden sich zwei Rechtecke vor ihm. Also ist x = 2 * Breite.
Das vierte Rechteck müsste x = 3 * Breite bekommen. Ein fünftes x = 4 * Breite usw. Das ist die Gesetzmäßigkeit.
Für die y Koordinate gilt nebenbei genau dasselbe. Es muss nur jeweils x mit y und Breite mit Höhe getauscht werden.
Wir werden nur eine einzige drawRect Methode haben, die uns alle Rechtecke zeichnen soll. d.h die Konstanten (2 *, 3 *, 4 *) etc für die x/y Berechnung müssen dynamisch errechnet werden können. Wie kriegen wir das hin? Schauen wir nochmal darauf wie wir auf diese Multiplikatoren gekommen sind. Bei der (2 *) hatten wir das dritte Rechteck gezeichnet. Bei der (3 *) das vierte. Die Multiplikatoren stehen also im Zusammenhang mit dem jeweiligen Rechteck (immer Rechteck -1). Die Rechteck Koordinaten haben wir, weil wir wissen in welcher Zeile,Spalte sich das Rechteck befindet, welches wir gerade zeichnen wollen.
Das war im Grunde alles was den Algorithmus ausmacht. Jetzt geht es mehr in Richtung Code. Die Zeile, Spalte Koordinaten werden die Grenzen der beiden verschachtelten for-Schleifen sein. Und wenn wir das ganze '0' basiert aufbauen brauchen wir nichtmal das "-1" zu machen um den Multiplikator zu erhalten.
Somit haben wir alles was wir brauchen um einen funktionierenden Code zu schreiben. Beim editieren hat sich durchaus das bewahrheitet was ich befürchtet habe; Algorithmen textuell zu beschreiben ist Wortreich und wird sehr schnell unverständlich.
Ich denk aber wenn man sich den Code dazu ansieht sollte es klarer werden.
Code:
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
int amountSelectedBlocks = 4;
int tileSize = 100;
drawGrid(amountSelectedBlocks, amountSelectedBlocks, tileSize, tileSize, g);
}
private void drawGrid(int nRows, int nColumns, int boxHeight, int boxWidth, Graphics g)
{
for(int row = 0; row < nRows; row++)
{
for(int col = 0; col < nColumns; col++)
{
int width = boxWidth;
int height = boxHeight;
int x = col*boxWidth;
int y = row*boxHeight;
g.drawRect(x, y, width, height);
}
}
}
Wir können die innere for-Schleife auch auf eine Zeile reduzieren. Ich habe halt extra mal aufgeführt wie die Parameter der drawRect Methode zustande kommen. Mal von der Textwand der Erklärung abgesehen finde ich diese Variante wesentlich einfacher zu verstehen.