<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Anmerkungen zum Design]]></title><description><![CDATA[<p>Hallo!</p>
<p>Ich hätte gern kritische Anmerkungen zu folgendem Designentwurf (Tetris in vereinfachter Ausführung, also kein entfernen von vollständig gefüllten Zeilen und rundenbasiert). Das Ganze war ein Programmiertest im Rahmen einer Bewerbung bei einer Firma.</p>
<p>Klasse für Spielsteine</p>
<pre><code class="language-cpp">#include &quot;global.h&quot;

#pragma once

class Piece
{
private:
	shape array[4][4];

public:
	typedef void (Piece::*PPieceFunction)(void);

	Piece(void);
	~Piece(void);

	void initForm();
	void rotateLeft(void);
	void rotateRight(void);
	bool isFieldPart(int x, int y);
	bool rowIsEmpty(int x);

};
</code></pre>
<p>Klasse für Spielfeld</p>
<pre><code class="language-cpp">#include &quot;piece.h&quot;

#pragma once

const int dimBoardWidth = 9;
const int dimBoardHeight = 20;

const int boardEmptyField = 0;
const int currentStone = 1;
const int boundedStone = 2;

class Board
{	
private:
	int gameBoard[dimBoardWidth][dimBoardHeight];
	int posX, posY; // Position der unteren linken Ecke des Steines
	bool gameOver;

	bool isDropDownPossible(Piece stone);
	bool isMoveLeftPossible(Piece stone);
	bool isMoveRightPossible(Piece stone);
	bool isRotatePossible(Piece stone, Piece::PPieceFunction pFunction);

	void drawPiece (Piece stone, const int paintAction);

public:
	Board(void);
	~Board(void);

	bool getGameState(void) { return gameOver; }

	void moveLeft(Piece stone);
	void moveRight(Piece stone);

	void stoneDropIn(Piece&amp; stone);
	void dropDown(Piece&amp; stone);
	void rotateLeft(Piece&amp; stone);
	void rotateRight(Piece&amp; stone);

	void showBoard(void);

};
</code></pre>
<p>Daraus habe ich dann im Hauptprogramm die restlichen Funktion erstellt (drehen, runter, links, rechts, usw.). Was sagt Ihr zu dem Entwurf? Kann man daran was optimieren und wenn „ja“, was? Die Firma meinte, mein Entwurf sei nicht optimal, aber ich sehe nicht unbedingt einen besseren Weg.</p>
<p>Gruß,<br />
Sid73</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/182127/anmerkungen-zum-design</link><generator>RSS for Node</generator><lastBuildDate>Fri, 03 Jul 2026 02:21:47 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/182127.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 21 May 2007 18:10:42 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Anmerkungen zum Design on Mon, 21 May 2007 18:10:42 GMT]]></title><description><![CDATA[<p>Hallo!</p>
<p>Ich hätte gern kritische Anmerkungen zu folgendem Designentwurf (Tetris in vereinfachter Ausführung, also kein entfernen von vollständig gefüllten Zeilen und rundenbasiert). Das Ganze war ein Programmiertest im Rahmen einer Bewerbung bei einer Firma.</p>
<p>Klasse für Spielsteine</p>
<pre><code class="language-cpp">#include &quot;global.h&quot;

#pragma once

class Piece
{
private:
	shape array[4][4];

public:
	typedef void (Piece::*PPieceFunction)(void);

	Piece(void);
	~Piece(void);

	void initForm();
	void rotateLeft(void);
	void rotateRight(void);
	bool isFieldPart(int x, int y);
	bool rowIsEmpty(int x);

};
</code></pre>
<p>Klasse für Spielfeld</p>
<pre><code class="language-cpp">#include &quot;piece.h&quot;

#pragma once

const int dimBoardWidth = 9;
const int dimBoardHeight = 20;

const int boardEmptyField = 0;
const int currentStone = 1;
const int boundedStone = 2;

class Board
{	
private:
	int gameBoard[dimBoardWidth][dimBoardHeight];
	int posX, posY; // Position der unteren linken Ecke des Steines
	bool gameOver;

	bool isDropDownPossible(Piece stone);
	bool isMoveLeftPossible(Piece stone);
	bool isMoveRightPossible(Piece stone);
	bool isRotatePossible(Piece stone, Piece::PPieceFunction pFunction);

	void drawPiece (Piece stone, const int paintAction);

public:
	Board(void);
	~Board(void);

	bool getGameState(void) { return gameOver; }

	void moveLeft(Piece stone);
	void moveRight(Piece stone);

	void stoneDropIn(Piece&amp; stone);
	void dropDown(Piece&amp; stone);
	void rotateLeft(Piece&amp; stone);
	void rotateRight(Piece&amp; stone);

	void showBoard(void);

};
</code></pre>
<p>Daraus habe ich dann im Hauptprogramm die restlichen Funktion erstellt (drehen, runter, links, rechts, usw.). Was sagt Ihr zu dem Entwurf? Kann man daran was optimieren und wenn „ja“, was? Die Firma meinte, mein Entwurf sei nicht optimal, aber ich sehe nicht unbedingt einen besseren Weg.</p>
<p>Gruß,<br />
Sid73</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289327</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289327</guid><dc:creator><![CDATA[Sid73]]></dc:creator><pubDate>Mon, 21 May 2007 18:10:42 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Mon, 21 May 2007 18:18:47 GMT]]></title><description><![CDATA[<p>Warum isDropDownPossible isMoveLeftPossible und isMoveRightPossible, statt isMovePossible mit der neuen Position?<br />
Das selbe gilt für die ganzen Move Methoden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289333</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289333</guid><dc:creator><![CDATA[ohkay]]></dc:creator><pubDate>Mon, 21 May 2007 18:18:47 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Mon, 21 May 2007 19:16:20 GMT]]></title><description><![CDATA[<p>in C++ gibts kein</p>
<pre><code class="language-cpp">int funktionOhneParameter(void);
</code></pre>
<p>sondern nur ein</p>
<pre><code class="language-cpp">int funktionOhneParameter();  // kein &quot;void&quot; in den Klammern
</code></pre>
<p>Nur als kleiner Hinweis.</p>
<p>Ansonsten uebergibst du viel zu viele Werte by-Value, die du wahrscheinlich als const-Referenzen uebergeben solltest. Das hat zwar alles nix mit Design zu tun, aber doch mit ordentlichem C++ <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>EDIT: ganz allgemein scheinst du &quot;const&quot; nicht zu moegen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289389</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289389</guid><dc:creator><![CDATA[Blue-Tiger]]></dc:creator><pubDate>Mon, 21 May 2007 19:16:20 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Mon, 21 May 2007 21:16:08 GMT]]></title><description><![CDATA[<p>Blue-Tiger schrieb:</p>
<blockquote>
<p>in C++ gibts kein</p>
<pre><code class="language-cpp">int funktionOhneParameter(void);
</code></pre>
<p>sondern nur ein</p>
<pre><code class="language-cpp">int funktionOhneParameter();  // kein &quot;void&quot; in den Klammern
</code></pre>
</blockquote>
<p>Was absolut unverbindlich sowie Geschmackssache ist. Und wenn man gleichzeitig C verwendet, wird man mit leeren Klammern schon mal auf Probleme stoßen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289458</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289458</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Mon, 21 May 2007 21:16:08 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Mon, 21 May 2007 21:28:28 GMT]]></title><description><![CDATA[<p>1. Nimm kein #pragma once, sondern include-Guards (oder zumindest beides)<br />
2. Achte auf Const-Correctness zB</p>
<pre><code class="language-cpp">bool getGameState(void) const { return gameOver; }
// statt
bool getGameState(void) { return gameOver; }
</code></pre>
<p>3. hier <code>void drawPiece (Piece stone, const int paintAction);</code> macht <code>const</code> wieder keinen Sinn.<br />
4. würde ich eher unsigned anstelle int benutzen, wenn du keine negativen Werte benötigst.<br />
5. wie schon gesagt. Benutz eher const-Referenzen als Copy-by-Value für nicht-Builtin Typen</p>
<p>Warum heißt Piece nicht Stone?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289471</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289471</guid><dc:creator><![CDATA[rüdiger]]></dc:creator><pubDate>Mon, 21 May 2007 21:28:28 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Tue, 22 May 2007 06:59:35 GMT]]></title><description><![CDATA[<p>ohkay schrieb:</p>
<blockquote>
<p>Warum isDropDownPossible isMoveLeftPossible und isMoveRightPossible, statt isMovePossible mit der neuen Position?<br />
Das selbe gilt für die ganzen Move Methoden.</p>
</blockquote>
<p>Die Funktionen unterscheiden sich tatsächlich nur in drei logischen Ausdrücken. Das könnte man natürlich auch alles in eine Funktion packen. Ich halte die Unterscheidung für sinnvoll, weil so gleich am Namen klar ist, was geprüft bzw. gemacht wird (teile und herrsche und so...).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289561</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289561</guid><dc:creator><![CDATA[Sid73]]></dc:creator><pubDate>Tue, 22 May 2007 06:59:35 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Tue, 22 May 2007 07:11:50 GMT]]></title><description><![CDATA[<p>Blue-Tiger schrieb:</p>
<blockquote>
<p>Ansonsten uebergibst du viel zu viele Werte by-Value, die du wahrscheinlich als const-Referenzen uebergeben solltest. Das hat zwar alles nix mit Design zu tun, aber doch mit ordentlichem C++ <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
</blockquote>
<p>Meinst Du in etwa so:</p>
<pre><code class="language-cpp">bool isMoveLeftPossible(const Piece stone);
</code></pre>
<p>Die Methoden mit Adressübergabe manipulieren das übergebene Objekt (stone), weshalb ich diese nicht als const übergeben kann. Ich habe zwar gelesen, dass man das Verändern in anderen Klassen vermeiden sollte, aber ich fand den anderen Weg (abfragen von Stautsvariablen und ändern im Hauptprogramm) zu umständlich/unübersichtlich.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289569</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289569</guid><dc:creator><![CDATA[Sid73]]></dc:creator><pubDate>Tue, 22 May 2007 07:11:50 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Tue, 22 May 2007 07:19:02 GMT]]></title><description><![CDATA[<p>rüdiger schrieb:</p>
<blockquote>
<p>1. Nimm kein #pragma once, sondern include-Guards (oder zumindest beides)</p>
</blockquote>
<p>Gibt's da Gründe für? Inkompatibilitäten? Ich habe #pragma once genommen, weil hier im Forum mal ein Fall diskutiert wurde, wo die include-Guards zu einen (schwierig zu findenden) Fehler geführt haben.</p>
<blockquote>
<p>Warum heißt Piece nicht Stone?</p>
</blockquote>
<p>In der Beschreibung stand etwas von &quot;While the pieces are falling...&quot; - ich dachte es erhöht den Wiedererkennungseffekt... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289572</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289572</guid><dc:creator><![CDATA[Sid73]]></dc:creator><pubDate>Tue, 22 May 2007 07:19:02 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Tue, 22 May 2007 07:23:33 GMT]]></title><description><![CDATA[<p>Er sagte doch &quot;const-<strong>Referenz</strong>&quot;: <code>bool isMoveLeftPossible(const Piece&amp; stone);</code> .</p>
<p>Ansonsten scheint mir das Vorgehen etwas inkonsistent - was genau machen die Funktionen Piece::rotateLeft() und Piece::rotateRight()? Ich hätte, wenn überhaupt, alle Bewegungen im Piece implementiert und auch dort die aktuelle Position gespeichert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289573</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289573</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Tue, 22 May 2007 07:23:33 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Tue, 22 May 2007 09:54:17 GMT]]></title><description><![CDATA[<p>CStoll schrieb:</p>
<blockquote>
<p>Er sagte doch &quot;const-<strong>Referenz</strong>&quot;: <code>bool isMoveLeftPossible(const Piece&amp; stone);</code> .</p>
</blockquote>
<p><em>ähem</em> Die Idee hatte ich auch, da ja an dem Objekt nichts verändert wird, aber wenn ich das so mache, bekomme ich folgenden Fehler:</p>
<pre><code>'Piece::isFieldPart': this-Zeiger kann nicht von 'const Piece' in 'Piece &amp;' konvertiert werden
</code></pre>
<p>isFieldPart(x,y) prüft ob das Feld in der 4x4-Matrix (des Steins) belegt ist und liefert bool zurück. Das hat den Sinn nur genau die Felder zur prüfen, die bei entsprechender Bewegung belegt sein würden. Warum bekomme ich den Fehler, wo sich doch an der Adresse nichts ändert?</p>
<blockquote>
<p>Ansonsten scheint mir das Vorgehen etwas inkonsistent - was genau machen die Funktionen Piece::rotateLeft() und Piece::rotateRight()? Ich hätte, wenn überhaupt, alle Bewegungen im Piece implementiert und auch dort die aktuelle Position gespeichert.</p>
</blockquote>
<p>Die Funktionen drehen den Stein um die z-Achse (d.h. Zeilen und Spalten werden vertauscht) in die jeweilige Richtung. Der Aufruf sieht dann etwa so aus</p>
<pre><code class="language-cpp">void Board::rotateLeft(Piece&amp; stone)
{	
	if (isRotatePossible(stone, &amp;Piece::rotateLeft))
	{
		drawPiece(stone, boardEmptyField);
		stone.rotateLeft();
		drawPiece(stone, currentStone);
	}
}
</code></pre>
<p>Die Drehung selbst ist ja auch in Piece implementiert, aber ich muß ja über das Board abfragen, ob das nicht mit schon vorhandenen Steinen kollidiert bzw. ob überhaupt Platz zum drehen da ist!?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289719</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289719</guid><dc:creator><![CDATA[Sid73]]></dc:creator><pubDate>Tue, 22 May 2007 09:54:17 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Tue, 22 May 2007 10:08:03 GMT]]></title><description><![CDATA[<p>Du hast die Funktion isFieldPart ja auch nicht als const deklariert:</p>
<pre><code class="language-cpp">bool isFieldPart(int x, int y) const;
</code></pre>
<p>Dies zusammen mit der Übergabe mittels &quot;const T&amp;&quot; nennt man const-correctness, d.h. du kannst somit nur auf konstante Methoden bzw. Member zugreifen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289728</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289728</guid><dc:creator><![CDATA[Th]]></dc:creator><pubDate>Tue, 22 May 2007 10:08:03 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Tue, 22 May 2007 10:43:54 GMT]]></title><description><![CDATA[<p>Netter Ansatz, aber wie gesagt - ich hätte die Steinbewegungen einheitlicher umgesetzt. Sprich: Der Stein merkt sich auch sein aktuelle Position und bietet auch Methoden zum Verschieben und Fallen, so daß du nur noch eine Funktion isMovePossible(Piece,Piece::PPieceFunction) und MovePiece(Piece&amp;,Piece::PPieceFunction) benötigst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289744</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289744</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Tue, 22 May 2007 10:43:54 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Tue, 22 May 2007 11:35:01 GMT]]></title><description><![CDATA[<p>Sid73 schrieb:</p>
<blockquote>
<p>rüdiger schrieb:</p>
<blockquote>
<p>1. Nimm kein #pragma once, sondern include-Guards (oder zumindest beides)</p>
</blockquote>
<p>Gibt's da Gründe für? Inkompatibilitäten? Ich habe #pragma once genommen, weil hier im Forum mal ein Fall diskutiert wurde, wo die include-Guards zu einen (schwierig zu findenden) Fehler geführt haben.</p>
</blockquote>
<p>Dieses &quot;#pragma once&quot; ist die Erfindung eines Compilerherstellers, die unnötig ist, da das gleiche mit include-Guards standardkonform gelöst werden kann. Grundsätzlich sollte man ohne guten Grund nicht von ANSI-C++ abweichen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289792</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289792</guid><dc:creator><![CDATA[tntnet]]></dc:creator><pubDate>Tue, 22 May 2007 11:35:01 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Tue, 22 May 2007 12:08:31 GMT]]></title><description><![CDATA[<p>tntnet schrieb:</p>
<blockquote>
<p>Sid73 schrieb:</p>
<blockquote>
<p>rüdiger schrieb:</p>
<blockquote>
<p>1. Nimm kein #pragma once, sondern include-Guards (oder zumindest beides)</p>
</blockquote>
<p>Gibt's da Gründe für? Inkompatibilitäten? Ich habe #pragma once genommen, weil hier im Forum mal ein Fall diskutiert wurde, wo die include-Guards zu einen (schwierig zu findenden) Fehler geführt haben.</p>
</blockquote>
<p>Dieses &quot;#pragma once&quot; ist die Erfindung eines Compilerherstellers, die unnötig ist, da das gleiche mit include-Guards standardkonform gelöst werden kann. Grundsätzlich sollte man ohne guten Grund nicht von ANSI-C++ abweichen.</p>
</blockquote>
<p>Das ist allerdings keine Abweichung vom Standard. pragma Direktiven sind zwar implementationsabhängig, beeinträchtigen aber nicht die Konformität. Es ist daher auch nicht notwendig, das ganze mit einem #if zu umschließen, damit bei anderen Compilern nichts passiert - höchtens um sicherzugehen, dass diese die Direktive nicht falsch verstehen. Nicht standardkonform wäre allerdings wohl der Verzicht auf Includeguards, wenn diese ohne #pragma once notwendig wären.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1289833</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1289833</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Tue, 22 May 2007 12:08:31 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Wed, 23 May 2007 08:00:54 GMT]]></title><description><![CDATA[<p>CStoll schrieb:</p>
<blockquote>
<p>Netter Ansatz, aber wie gesagt - ich hätte die Steinbewegungen einheitlicher umgesetzt. Sprich: Der Stein merkt sich auch sein aktuelle Position und bietet auch Methoden zum Verschieben und Fallen, so daß du nur noch eine Funktion isMovePossible(Piece,Piece::PPieceFunction) und MovePiece(Piece&amp;,Piece::PPieceFunction) benötigst.</p>
</blockquote>
<p>Also nur nochmal für mich zum Verständnis: Du würdest lediglich eine Klasse für die Spielsteine nehmen und die Board-Klasse einfach als Matrix mit ein paar Funktionen im Hauptprogramm abbilden!?</p>
<p>Ansonsten danke an alle für Eure Anmerkungen!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1290367</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1290367</guid><dc:creator><![CDATA[Sid73]]></dc:creator><pubDate>Wed, 23 May 2007 08:00:54 GMT</pubDate></item><item><title><![CDATA[Reply to Anmerkungen zum Design on Wed, 23 May 2007 08:04:36 GMT]]></title><description><![CDATA[<p>Vermutlich ja. Oder ich würde alle Aktionen in die Spielfeld-Klasse packen und die Steine zu Datenobjekten &quot;degradieren&quot;. Aber auf jeden Fall würde die Kompetenzen klar aufteilen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1290369</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1290369</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Wed, 23 May 2007 08:04:36 GMT</pubDate></item></channel></rss>