1. Bonus-Aufgabe: AuD SnowBlocks

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

1. Bonus-Aufgabe: AuD SnowBlocks
Ich bin bei Teilaufgabe g) auf ein kleines Problem gestoßen und nach langem Rumprobieren wollte ich einfach mal fragen ob mir hier jemand weiterhelfen kann? Es geht um das Hinzufügen des “3D-Effekts”, bei dem meine Lösung mit der des Tests leider nicht übereinstimmt. Darum bin ich mal hergegangen und hab mir in Excel angeschaut was eigentlich beim entsprechenden AuDSnowBlocksTest miteinander verglichen wird. Ich hoffe ich habe die zugrundeliegenden Daten richtig interpretiert:

Meine Lösung: http://i.imgur.com/8SDZTfM.jpg
Musterlösung: http://i.imgur.com/d0vst3u.jpg (int[] colors aus Zeile 929)

Wie man gut sehen kann bekomm ich in Spalte 7 (bei 1 startend) und Reihe 7 (auch bei 1 startend) meinen AssertionError. Prinzipiell ist meiner Meinung nach in Spalte und Reihe 7 der Musterlösung was schief gelaufen. Immer vorausgesetzt, dass ich mir die Daten halbwegs sinnvoll habe ausgeben lassen. Ist dort dem AuD-Team ein Fehler unterlaufen? Denn das Bild legt die Vermutung nahe, dass die Schleifen der Musterlösung zum Zeichnen des lightColor-Teils oben und links um eins zu weit laufen.


edit: hier stand im Grunde der Beitrag von Jackpot, sry 4 spam. Habe auch denselben Fehler und insofern vermute ich, dass da wirklich ein Indexfehler unterlaufen ist.

Habe noch eine Frage zur Teilaufgabe f: wie greift ihr beim BORDER-Zeichnen aufs Feld zu (also welche Variable besagt, dass das Feld z. B. beim Index 5 anfängt und bei 14 aufhört)?


Ich hab mich da einfach an der Methode orientiert, die das Spielfeld zeichnet… sprich “hard-gecoded”. Wenn jetzt jemand auf die Idee kommen würde das Spielfeld zu verschieben würde mein Rand natürlich nicht mehr stimmen, da aber beide Methoden in der selben Klasse definiert sind, geh ich einfach mal davon aus, dass man darüber die Kontrolle hat. Habe aber auch keine Variable gefunden, die die Position des Spielfelds im Koodinatensystem des Bildschirms beschreibt.


Jep :blush:. Danke für den Hinweis.

Mittlerweile ist der Test überarbeitet und die korrigierte Version online.

Klingt gut ;).


Ich hab auch eine Frage zu dieser Aufgabe.
Und zwar geht es auch um die Tests. Bei mir kracht es bei der Methode

iBlockSRotation0to1Blocked() .
Dann habe ich versucht nachzuvollziehen, wieso mein Code nicht stimmt und frage mich nun Folgendes:
In der AuDSnowBlocksTest.java-Klasse steht in der Methode iBlockSRotation0to1Blocked() folgender Teil:

...
game.getGameLogic().rotate();
assert (tiles[6][4].getType() == TileType.OCCUPIED_S) : assertString;
assert (tiles[6][5].getType() == TileType.OCCUPIED_S) : assertString;
assert (tiles[5][5].getType() == TileType.OCCUPIED_S) : assertString;
assert (tiles[5][6].getType() == TileType.OCCUPIED_S) : assertString;
...

Da es in der Methode darum geht, zu testen, ob man die S-Figur von Rotation = 0 auf 1 richtig dreht, müssten nach dem Rotieren (also im Status: rotation=1) 3 von den 4 Tiles der Figur unterschiedliche y-Koordinaten haben. Im Test wird meiner Meinung nach eher geprüft, ob sich die Figur in rotation = 0 befindet, da im Test die 4 Tiles nur auf 2 unterschiedliche y-Koordinaten “verteilt” sind.
Ich hoffe man versteht, was ich meine und falls ich komplett daneben liege, klärt mich bitte auf :slight_smile:

Wenns geht, diesen Beitrag bitte löschen. Ich stand auf dem Schlauch. Das wird schon richtig überpürft, da sich die Figur gar nicht rotieren darf an dieser Stelle. Da war dann auch mein Fehler im Code.
Nun funktioniert es :slight_smile:


iBlockSRotation0to1Blocked überprüft, ob du nur dann drehst, wenn es erlaubt ist.
Die Drehung ist erlaubt, wenn die im Aufgabenblatt rot markierten Felder frei sind. :wink:


Hallo,

ich bin gerade bei Teilaufgabe h).
Dabei stellt sich mir die Frage, wie man die Methode partOfBlock vom Interface SnowBlock verwenden soll.
Man hat ja nirgends ein Array o.ä., in dem die einzelnen Block-Objekte gespeichert sind.
Irgendwie muss man ja abprüfen, ob es sich um unterschiedliche “Blöcke” handelt.

Kann mir da jemand nen kurzen Hinweis geben? :slight_smile:

Vielen Dank


Auch ich hab so meine Probleme mit der partOfBlock(y, x) Methode. So wie ich das verstanden habe (und bitte korrigiert mich wenn ich falsch liege) dann gibt es immer nur einen einzigen konkreten Block im Spiel, nämlich currentBlock. Wenn der erstmal am Boden ist, dann werden nur noch die Tiles entsprechend gesetzt und der Block mit dem neu generierten überschrieben. Es gibt zwar eine Variable namens int[] lastTiles, aber die 4 Integer haben mit “Tiles” wenig zu tun, diese beschreiben nämlich nur den Typ der letzten 4 generierten Blöcke.

Zudem wird die zu implementierende Methode updateSnow() immer nur zu einem ganz konkreten Zeitpunkt aufgerufen, und zwar in der Methode:

private void addNextBlock() {
	removeLines();
	checkGameOver();
	if (!getGameOver()) {
		if (addBlocksAutomatically) {
			currentBlock = createBlock();
		}
	}
	updateSnow();
}

Sprich in der updateSnow() Methode kann partOfBlock(y, x) nur für Werte aus den beiden obersten, nicht sichtbaren Zeilen true liefern, da sich der neu erstellte Block noch nicht bewegt hat. D.h. zum Zeichnen des Schnees kann man doch partOfBlock(y, x) getrotst vergessen? Oder überseh ich da etwas?

Wie man im Spielfeld konkrete Nachbarschafftsverhältnisse zwischen einzelnen Blöcken feststellen kann habe ich noch nicht herausgefunden, weil ja immer nur der Typ in den Tiles hinterlegt ist und keine Referenz auf einen Block. Das wäre vorallem dann wichtig, um nach dem Entfernen kompletter Zeilen, einzelne übriggebliebene Blockbruchstücke richtig unterscheiden zu können.


So wie ich die Aufgabenstellung verstehe, braucht man keine Nachbarschaftsverhältnisse.

Regel f) “Regel d) (da steht nichts von anderen Regeln) muss auch nach dem Entfernen vollständiger Reihen gelten.”
Regel d) “Das oberste Tile einer Spalte, dass nicht zum gerade gesteuerten Block gehört, soll immer eine Schneehaube haben.”

Die obersten Tiles von Blöcken müssen keine Schneehaube haben (siehe z. B. Regel g und anschließendes Löschen einer Reihe unter dem obersten unter einem anderen Block eingefügten Block).

Und natürlich funktioniert partOfBlock() auch bei größeren y-Werten als den obersten 2 Reihen.

edit: habe wohl die Musterlösung verraten.


Das kommt auf deine Implementierung an. Und ja, man kann es ohne implementieren :D.

Wofür braucht man das?


Natürlich funktioniert die Methode, sie gibt nur immer false zurück. Also zumindest in der Spiele-Implementation, in AuDSnowBlocksTest könnte die Methode updateSnow() natürlich zu beliebigen Zeitpunkten aufgerufen werden (habe mich jetzt mit den einzelnen Tests noch nicht wirklich beschäftigt), aber ich meinte jetzt einfach das Spiel selbst. Dieses ruft die Methode immer nur dann auf, wenn ein neuer Block gerade generiert wurde und sich in den ersten beiden Zeilen aufhält. Sprich es wird immer nur dann kurz der Schnee „geupdated“ wenn der currentBlock eh nicht im sichtbaren Spielfeld ist, und wer zeichnet schon den Schnee außerhalb des sichtbaren Bereichs ;).

Hmm, ja ich glaube ich denke noch falsch. Einmal gezeichneter Schnee geht ja eigentlich nicht verloren, es sei denn das Tile wird absichtlich gelöscht. So gesehen müsste der Schnee aus dem vorherigen Zustand noch passen. Ich wollte wahrscheinlich jedesmal über das komplette Spielfeld laufen und alle Tiles entsprechend der Regeln neu updaten.


Okay, habe die Teilaufgabe h) jetzt erfolgreich getestet.
Die Methode “partOfBlock” macht in Verbindung mit dem “currentBlock” duchaus Sinn… :stuck_out_tongue:

Das so als Tipp am Rande, falls man - wie ich - folgendes zu lesen bekommt:
“Exception in thread “main” java.lang.AssertionError: updateSnow: only the upper tiles of the block O must get a snow layer!”

Frohe Weihnachten an alle! :slight_smile:


In welcher Klasse schaust du dir die partOfBlock-Methode an?


Hehe, du hast mich nicht ganz verstanden nehme ich an. Ich schau mir nicht die partOfBlock Methode an, sondern wann updateSnow() aufgerufen wird, was wiederum partOfBlock beachten soll. Und updateSnow() wird immer genau dann im Spiel aufgerufen, wenn es gerade keinen sichtbaren Block gibt (partOfBlock im sichtbaren Feld also eh immer false ist). Das ist bei den Tests aber vielleicht anders und am Ende auch gar nicht so wichtig ;).


[quote=Jackpot]
[…]Hehe, du hast mich nicht ganz verstanden nehme ich an. […] Und updateSnow() wird immer genau dann im Spiel aufgerufen, wenn es gerade keinen sichtbaren Block gibt (partOfBlock im sichtbaren Feld also eh immer false ist). Das ist bei den Tests aber vielleicht anders und am Ende auch gar nicht so wichtig ;).[/quote]

Hab dich zwar wirklich falsch verstanden, aber bei mir funktionieren die Testfälle ohne die Abfrage trotzdem nicht. Hängt aber eh von der Implementierung ab. :slight_smile:


Möglicherweise gibt es einen Bug im Konstruktor von GameLogic. Gelegentlich erhalte ich folgende Exception:

Exception in thread "main" java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0
	at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016)
	at java.awt.image.BufferedImage.<init>(BufferedImage.java:340)
	at Tile.<init>(Tile.java:31)
	at BlockT.init(BlockT.java:94)
	at GameLogic.createBlockWithType(GameLogic.java:113)
	at GameLogic.createBlock(GameLogic.java:158)
	at GameLogic.addNextBlock(GameLogic.java:60)
	at GameLogic.<init>(GameLogic.java:40)
	at AuDSnowBlocks.<init>(AuDSnowBlocks.java:33)
	at AuDSnowBlocksMain.main(AuDSnowBlocksMain.java:14)

Process finished with exit code 1

Konstruktor von GameLogic:

public GameLogic(boolean[][] field, int tileSize, boolean addBlocksAutomatically)
    {
        gameFieldTiles = new GameFieldTiles(field, tileSize);
        this.height = field.length;
        this.width = field[0].length;
        this.addBlocksAutomatically = addBlocksAutomatically;
        if (addBlocksAutomatically)
        {
            this.addNextBlock();
        }

        this.tileSize = tileSize;
    }

tileSize wird erst nach dem Aufruf von addNextBlock gesetzt. Leider erzeugt addNextBlock manchmal (Zufall) auch einen neuen BlockT, dessen Konstruktor getTileSize() von GameLogic aufruft, der dann 0 zurückgibt (Standardwert von int). Wenn man tileSize ganz am Anfang setzt, verschwindet der Fehler.


Frage zur TeilAufg a) warum wurde keine Variable für den Anzahl der vervollständigten Reihen deklariert?


Weil das ein Bestandteil der Aufgabenstellung ist.

@ Tamaskan:

Ich hatte auch den Fehler, aber man kann trotzdem einen grünen Haken bekommen.


Ich habe ne frage zur Implementierung des LBlocks. Ich glaube es ist kein Geheimnis dass der LBlock dem JBlock sehr start ähnelt. Ich habe jetzt code vom JBlock kopiert und nur teilweise abgeändert. Gibt es da Probleme und soll ich den bisschen umschreiben dass er so aussieht wie eigener code oder ist das berücksichtigt und es wird keine Probleme geben?