Zurück   Flashforum > Flash > ActionScript > Softwarearchitektur und Entwurfsmuster

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 10-03-2006, 23:45   #1 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Dieser Thread ist aus rendner[i]s Idee entstanden, ein Memoryspiel in OOP zu implementieren. Da ich gerade ein Buch über objektorientiertes Design lese, wollte ich hier gerne mal versuchen, die Methoden und Ideen aus dem Buch auf das konkrete Problem Memory anzuwenden. Ich bin gespannt, was dabei rauskommt. Wenn jemand Erfahrung im OODesign hat, ist er herzlich eingeladen, seinen Senf dazuzugeben. Die anderen natürlich auch.

Zuerst muss man mal klären, was das überhaupt ist: Memory.

Ich sehe eine Menge von Karten. Die Karten haben alle die gleiche Rückseite. Auf der Vorderseite ist ein Motiv. Jedes Motiv kommt genau zweimal im Spiel vor, die Karten bilden also Paare.
1. Die Karten werden gemischt und dann so auf dem Tisch ausgebreitet, dass nur die Rückseite sichtbar ist. Das Ziel eines Spielers ist es nun, soviele Paare wie möglich zu finden.
2. Der erste Spieler dreht zwei Karten um, so dass ihr Motiv sichtbar wird. Die Position der Karten auf dem Tisch bleibt unverändert.
2a. Sind die Karten verschieden, dreht der Spieler die Karten wieder um. Die Position bleibt dabei wiederum unverändert. Jetzt ist der nächste Spieler an der Reihe (zurück zu Schritt 2).
2b. Sind die Karten gleich, nimmt der Spieler die beiden Karten an sich und legt sie auf seinen Stapel. Die anderen Karten bleiben an ihrem Platz liegen. Die Positonen der beiden herausgenommenen Karten bleiben im weiteren Verlauf des Spiels leer.
3a. Gibt es noch weitere Karten auf dem Tisch, ist der Spieler nochmal dran (zurück zu Schritt 2)
3b. Hat der Spieler das letzte Kartenpaar entnommen, ist das Spiel beendet.
4. Die Stapel der Spieler werden nebeneinander gelegt. Wer den höchsten Stapel hat, hat das Spiel gewonnen.
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D

Geändert von hazy fantazy (11-03-2006 um 15:57 Uhr)
hazy fantazy ist offline   Mit Zitat antworten
Alt 11-03-2006, 00:05   #2 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
OK, dann suchen wir uns mal die Nomen und Verben raus.

1. Spieler, Spiel, Karte, Tisch, Paar, Position, Vorderseite, Rückseite, Stapel
2. mischen, umdrehen, aufdecken, entnehmen, vergleichen
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D
hazy fantazy ist offline   Mit Zitat antworten
Alt 11-03-2006, 00:29   #3 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Dann versuchen wir mal die Beziehungen zwischen den Nomen festzuhalten.

Ein Spiel besteht aus x Karten
Auf dem Tisch liegen x Karten
Ein Stapel besteht aus x Karten
Ein Spieler hat einen Stapel
Eine Karte hat eine Position, Vorderseite und Rückseite
Ein Paar besteht aus zwei Karten mit gleicher Vorderseite
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D
hazy fantazy ist offline   Mit Zitat antworten
Alt 11-03-2006, 01:06   #4 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Und dann der erste Usecase: Die Karten werden gemischt und verdeckt auf dem Tisch ausgebreitet. Wer macht hier was?

Das Spiel erfordert, dass ein Spieler alle Karten aufnimmt, mischt und sie dann auf dem Tisch ausbreitet. Sind die Spieler Teil des Spiels? Haben wir vorhin vergessen. Der Tisch auch?

Spiel -> starteSpiel() -> Spieler
Spieler -> mischen() -> Alle Karten (Collection?)
Spieler -> legeKarte(karte) -> Tisch (für jede Karte einzeln, Iterator?)

Der Spieler ist hier irgendwie merkwürdig. Wenn Spieler und Karten im Spiel enthalten sind, dann sollen sie auch nicht miteinander kommunizieren, weil sie im gleichen Scope liegen. aber wie kriege ich sonst die Nachricht mischen an den Mann gebracht? Vielleicht wäre ein neues Objekt Spielrunde besser?
Eine Spielrunde enthält die Karten, die Spieler und den Tisch.

Spiel -> new(spieler,karten) -> Spielrunde
Spielrunde -> mischen() -> Alle Karten (Collection?)
Spielrunde -> legeKarte(karte) -> Tisch (für jede Karte einzeln, Iterator?)
Tisch -> stellDichDar( position) -> Karte

Sieht besser aus, weil so die Messages nur von oben nach unten fliessen und nicht zwischen gleichrangigen Objekten, wie oben.
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D

Geändert von hazy fantazy (11-03-2006 um 16:05 Uhr)
hazy fantazy ist offline   Mit Zitat antworten
Alt 11-03-2006, 16:35   #5 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Die Karten liegen jetzt auf dem Tisch und der erste Spieler dreht jetzt 2 Karten um.

Spieler -> umdrehen() -> Karte

Das Problem hatten wir ja schonmal, der Spieler soll nicht mit der Karte kommunizieren, weil beide im gleichen Scope sind. Stattdessen muss die Spielrunde irgendwie informiert werden, dass der Spieler eine Karte umdrehen will. Weil der Spieler auch keine Nachrichten an die Spielrunde schicken kann, muss die Spielrunde den Spieler pollen.

Also Spielrunde pollt Spieler, bis er eine neue Position festgelegt hat. (Man könnte es vielleicht als Mausklick interpretieren?)

Spielrunde -> getPosition() -> Spieler
Spielrunde -> angeklickt( position) -> Tisch
Tisch -> aufdecken() -> Karte
Spielrunde -> getAnzahlAufgedeckteKarten() -> Tisch

Das geht solange, bis die Anzahl aufgedeckter Karten 2 ist.
Anschliessend werden die Karten verglichen. Zeigen sie das gleiche Motiv, bekommt der Spieler sie. Ist das Motiv verschieden, werden sie wieder zurückgedreht. Es ist jetzt die Frage, wo die Logik hinkommt, in die Spielrunde oder in den Tisch? Die Spielrunde wäre naheliegend, mal sehen:

Spielrunde -> sindMotiveGleich()-> Tisch
Tisch -> istMotivGleich( Karte 2) -> Karte 1

Sieht nicht schlecht aus. Wenn es der Tisch machen würde, müsste ich aber nicht immer abfragen, ob die Anzahl aufgedeckter Karten 2 ist. Stattdessen würde ich nur noch fragen, ob der Spielzug abgeschlossen ist und mir dann das Ergebnis holen.

Spielrunde -> getPosition() -> Spieler
Spielrunde -> angeklickt( position) -> Tisch
Tisch -> aufdecken() -> Karte

Wenn zwei Karten aufgedeckt sind:
Spielrunde -> istSpielzugVollständig() -> Tisch

Wenn ja:
Spielrunde -> getErgebnisDesLetztenSpielzugs() -> Tisch
Tisch istMotivGleich( Karte 2) -> Karte 1

Wenn die Karten gleich waren
Tisch -> entferneKarten() -> Tisch
liefere positives Ergebnis mit den Karten als Inhalt

Wenn die Karten nicht gleich waren
Tisch -> verdecken -> Karte 1
Tisch -> verdecken -> Karte 2
liefere negative Ergebnis

Ok, etwas unübersichtlich. Im Zusammenhang sieht das so aus:

Spielrunde -> getPosition() -> Spieler
Spielrunde -> angeklickt( position) -> Tisch
Tisch -> aufdecken() -> Karte

A:
Spielrunde -> getAnzahlAufgedeckteKarten() -> Tisch
Spielrunde: if anzahl == 2
Spielrunde -> sindMotiveGleich()-> Tisch
Tisch -> istMotivGleich( Karte 2) -> Karte 1
Spielrunde: if true
Spieler -> gebeKarten( Tisch.getAufgedeckteKarten())
Spielrunde: Weiter mit Pollen
Spielrunde: if false
Spielrunde -> verdeckeKarten() -> Tisch
Tisch -> verdecke() -> Karte 1
Tisch -> verdecke() -> Karte 2
Spielrunde -> aktiviereNächstenSpieler() -> Spielrunde
Spielrunde: weiter mit Pollen

B:
Spielrunde -> istSpielzugVollständig() -> Tisch
Spielrunde -> getErgebnisDesLetztenSpielzugs() -> Tisch
Tisch istMotivGleich( Karte 2) -> Karte 1
Tisch: if true
Tisch -> entferneKarten() -> Tisch
liefere positives Ergebnis mit den Karten als Inhalt
Tisch: if false
Tisch -> verdecken -> Karte 1
Tisch -> verdecken -> Karte 2
liefere negative Ergebnis
Spielrunde: if ergebnis positiv
Spieler -> gebeKarten( ergebnis.getKarten())
Spielrunde: Weiter mit Pollen
Spielrunde: if false
Spielrunde -> aktiviereNächstenSpieler() -> Spielrunde
Spielrunde: weiter mit Pollen

B ist (wahrscheinlich) besser, weil dort die Spielrunde nicht als Gottklasse für den Tisch fungiert. Bleiben wir erstmal bei B.
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D

Geändert von hazy fantazy (11-03-2006 um 20:40 Uhr)
hazy fantazy ist offline   Mit Zitat antworten
Alt 11-03-2006, 20:49   #6 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Jetzt sind wir ja schon fast fertig. Die letzte Frage ist: Wie wird das Spiel beendet? Wenn das Ergebnis positiv war, fragen wir den Tisch, ob er noch weitere Karten hat, und wenn nicht, beenden wir das Spiel.

Spielrunde: if ergebnis negativ
Spielrunde -> aktiviereNächstenSpieler() -> Spielrunde
Spielrunde: weiter mit Pollen

Spielrunde: if ergebnis positiv
Spieler -> gebeKarten( ergebnis.getKarten())
Spielrunde -> gibEsNochKarten() -> Tisch
if ja
Spielrunde: Weiter mit Pollen
if nein //spiel beenden
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D

Geändert von hazy fantazy (11-03-2006 um 20:50 Uhr)
hazy fantazy ist offline   Mit Zitat antworten
Alt 11-03-2006, 21:19   #7 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Hier ist jetzt mal der ganze Entwurf soweit wie ich den habe:


Spiel -> new(spieler,karten) -> Spielrunde
Spielrunde -> mischen() -> karten
Spielrunde -> zeigeKarten( karten) -> Tisch
Tisch -> zeigDich( position) -> Karte (für alle Karten)

Repeat
Repeat
Spielrunde -> getPosition() -> Spieler
Spielrunde -> angeklickt( position) -> Tisch
Tisch -> aufdecken() -> Karte
Until Spielrunde -> istSpielzugVollständig() -> Tisch

Spielrunde -> getErgebnisDesLetztenSpielzugs() -> Tisch
Tisch istMotivGleich( Karte 2) -> Karte 1
Tisch: if true
Tisch -> entferneKarten() -> Tisch
liefere positives Ergebnis mit den Karten als Inhalt
Tisch: if false
Tisch -> verdecken -> Karte 1
Tisch -> verdecken -> Karte 2
liefere negatives Ergebnis

Spielrunde: if ergebnis positiv
Spieler -> gebeKarten( ergebnis.getKarten())
Spielrunde: Weiter mit Pollen
Spielrunde: if false
Spielrunde -> aktiviereNächstenSpieler() -> Spielrunde
Spielrunde: weiter mit Pollen

Spielrunde: if ergebnis negativ
Spielrunde -> aktiviereNächstenSpieler() -> Spielrunde
Spielrunde: weiter mit Pollen

Spielrunde: if ergebnis positiv
Spieler -> gebeKarten( ergebnis.getKarten())
Until ! Spielrunde -> gibEsNochKarten() -> Tisch

Dass der Spieler den Klick liefert, ist ja eigentlich Unsinn. In einer Implementation( in Flash) würde das die Karte tun. Was würde sich dadurch ändern?
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D
hazy fantazy ist offline   Mit Zitat antworten
Alt 11-03-2006, 23:39   #8 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Spiel -> new(spieler,karten) -> Spielrunde

Spielrunde -> mischen() -> karten
Spielrunde -> zeigeKarten( karten) -> Tisch

Spielrunde -> aktiviereErstenSpieler() -> Spielrunde
Spielrunde -> setAktivenSpieler( Spielrunde -> getNext() -> spieler)

Repeat
Repeat
Until Spielrunde -> istSpielzugVollständig() -> Tisch (Tisch handelt klicken und umdrehen intern)

Spielrunde -> getErgebnisDesLetztenSpielzugs() -> Tisch (Tisch handelt löschen oder zurückdrehen intern)

Spielrunde: if ergebnis negativ
Spielrunde -> aktiviereNächstenSpieler() -> Spielrunde
Spielrunde: weiter mit Pollen

Spielrunde: if ergebnis positiv
Spielrunde -> gebeKarten( ergebnis.getKarten()) -> Spieler
Until ! Spielrunde -> gibtEsNochKarten() -> Tisch

So sieht das schon besser aus. Ist die Frage, ob gibtEsNochKarten die richtige Frage ist. Könnte man auch istSpielBeendet nennen.

mfg. h
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D
hazy fantazy ist offline   Mit Zitat antworten
Alt 12-03-2006, 01:21   #9 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Also die Karten sind ja nicht wirklich interessant für den Spieler, das können wir auch durch Punkte ersetzen. Und das Polling muss auch nicht sein, wie ich jetzt gerade gelesen habe. Ein Callback ist auch erlaubt, auch wenn er weniger typsicher ist.

Spiel -> new(spieler,karten) -> Spielrunde

Spielrunde -> mischen() -> karten
Spielrunde -> zeigeKarten( karten) -> Tisch

Spielrunde -> aktiviereErstenSpieler() -> Spielrunde
Spielrunde -> setAktivenSpieler( Spielrunde -> getNext() -> spieler)


on spielzugIstVollständig von Tisch

Spielrunde -> getErgebnisDesLetztenSpielzugs() -> Tisch (Tisch handelt löschen oder zurückdrehen intern)

Spielrunde: if ergebnis negativ
Spielrunde -> aktiviereNächstenSpieler() -> Spielrunde

Spielrunde: if ergebnis positiv
Spielrunde -> gebePunkte(2) -> Spieler
Spielrunde -> gibtEsNochKarten() -> Tisch
if false spiel beenden

mfg. h
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D
hazy fantazy ist offline   Mit Zitat antworten
Alt 12-03-2006, 11:25   #10 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Die Karten brauche ich ausserhalb des Tisches gar nicht. Die ganze Zuweisung der Karten von aussen macht wenig Sinn. Selbst wenn ich verschiedene Sets von Karten mit unterschiedlichen Motiven benutzen wollte, würde das nur die UI betreffen. Das Kartenobjekt selbst ist davon nicht betroffen. Deshalb verschiebe ich mal die ganze Kartengeschichte in den Tisch.
setAktivenSpieler gehört auch nicht ins Interface von Spielrunde, also weg damit.

Spiel -> new(spieler) -> Spielrunde

Spielrunde -> neuesSpiel() -> Tisch

Spielrunde -> aktiviereErstenSpieler() -> Spielrunde


on spielzugIstVollständig von Tisch

Spielrunde -> getErgebnisDesLetztenSpielzugs() -> Tisch (Tisch handelt löschen oder zurückdrehen intern)

Spielrunde: if ergebnis negativ
Spielrunde -> aktiviereNächstenSpieler() -> Spielrunde

Spielrunde: if ergebnis positiv
Spielrunde -> addierePunkte(2) -> Spieler
Spielrunde -> istSpielBeendet() -> Tisch
if false spiel beenden

Auffällig ist, dass wir jetzt mit Memory gar nichts mehr zu tun haben. Das Spielrunde Objekt ist einfach ein abstraktes Objekt, das die Abfolge von Spielzügen koordiniert. Eigentlich schoen, dass ich da durch die relativ stumpfe Anwendung von ein paar Regeln hingekommen bin.
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D

Geändert von hazy fantazy (12-03-2006 um 11:28 Uhr)
hazy fantazy ist offline   Mit Zitat antworten
Alt 12-03-2006, 12:27   #11 (permalink)
helpQLODhelp
 
Benutzerbild von bokel
 
Registriert seit: Feb 2002
Ort: Köln
Beiträge: 8.505
Jetzt fehlt nur noch der Tisch
mfg. r
bokel ist offline   Mit Zitat antworten
Alt 12-03-2006, 16:55   #12 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Yep, eins nach dem anderen Der Tisch könnte vielleicht so aussehen:

Spielrunde -> neuesSpiel()-> Tisch
Tisch -> erzeugeKarten() -> Tisch
Tisch -> mischen() -> Karten
Tisch -> darstellen(position) -> Karte (für jede Karte)

Interaktion: Klick auf Karte
Karte -> aufdecken() -> Karte
Event: karteAufgedeckt -> Tisch
Tisch -> zweiKartenAufgedeckt() -> Tisch
Event: istSpielzugVollstaendig -> Spielrunde

Spielrunde -> getErgebnisDesLetztenSpielzugs() -> Tisch
Tisch -> istMotivGleich( Karte2) -> Karte1
if true
Tisch -> entferneKarte(Karte1) -> Karten
Tisch -> entferneKarte(Karte2) -> Karten
return PositivesErgebnis()
if false
Tisch -> verdecken() -> Karte1
Tisch -> verdecken() -> Karte2
return NegativesErgebnis()

Spielrunde -> istSpielBeendet() -> Tisch
Tisch -> getAnzahl() -> Karten
return Anzahl > 0

Anstatt Callbacks habe ich jetzt Events eingesetzt. Das finde ich irgendwie passender.

mfg. h
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D
hazy fantazy ist offline   Mit Zitat antworten
Alt 13-03-2006, 00:38   #13 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Und hier ist jetzt mal eine Implementation des ganzen. Durch die ganze Vorarbeit ging das ziemlich locker von der Hand. Die Erzeugung der GUI ist ein bißchen dirty. Das kann man bei Bedarf sicher hübscher machen, z.B. mit einer Factory für die Karten.
Angehängte Dateien
Dateityp: zip memory_ood.zip (15,0 KB, 83x aufgerufen)
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D
hazy fantazy ist offline   Mit Zitat antworten
Alt 13-03-2006, 07:58   #14 (permalink)
voidboy
 
Benutzerbild von rendner[i]
 
Registriert seit: Sep 2004
Ort: München
Beiträge: 5.586
Man das ist ja ein Ding, ich häng immer noch an der Überlegung wer die Karten bei mir anordnet und wer die Events verwaltet.
Ich sollte mir doch mal ein Buch was dieses Thema abgreift zulegen...

Werd mir das mal zu Gemüte führen und etwas sacken lassen und wenn ich Zeit habe setze ich mich mal wieder inspiriert an meins.
__________________
ERROR: Signature is too large
rendner[i] ist offline   Mit Zitat antworten
Alt 13-03-2006, 11:09   #15 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Hallo rendner[i],

lass dich davon nicht irritieren. Das sollte ja nur ein Versuch sein. Je nach Anforderung kann da bei dir was ganz anderes herauskommen.
Ich für meinen Teil fand es auf jeden Fall interessant mal so vorzugehen. Und ich bin mit dem Ergebnis ganz zufrieden. Deshalb habe ich mir gleich das nächste Buch über OOD bestellt

mfg. h
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D
hazy fantazy ist offline   Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
Pingbacks sind an
Refbacks sind an



Alle Zeitangaben in WEZ +1. Es ist jetzt 21:59 Uhr.

Domains, Webhosting & Vserver von Host Europe
Unterstützt das Flashforum!
Adobe User Group


Copyright ©1999 – 2014 Marc Thiele