Du bist nicht angemeldet.

  1. Übersicht
  2. » Allgemein
  3. » Monkey X: Memory
  4. » Eine Antwort schreiben

Eine Antwort schreiben

Schreibe deinen Beitrag und versende ihn
Beitragsoptionen
Bist Du ein Mensch oder ein Roboter ?

Verifizierung, dass diese Aktion durch eine reale Person vorgenommen wird und nicht von einem Programm.

Zurück

Themen-Übersicht (Neuester Beitrag zuerst)

Ronny
29.05.2015 14:51

Ok, so der Fehler war folgendes:

Die fehlerhafte Zeile(n):

cardSlots[i][0] = 50 +  (i Mod slotsPerRow) * slotsWidth
cardSlots[i][1] = 50 +  (i / slotsPerRow) * slotsHeight

Die hatten sich darauf verlassen, dass "cardSlots[x]" ein Array mit mindestens 2 Eintraegen waere...

Leider habe ich weiter oben (Zeile 123) einen Fehler gemacht:

	cardSlots[i].Resize(2)

Ich hatte da angenommen, dass es einfach den "cardSlots[x]"-Array auf die Laenge 2 setzt... dabei gibt "Resize(2)" aber einfach einen neuen Array mit der Groesse "2" zurueck ...

Loesung: austauschen mit

	cardSlots[i] = cardSlots[i].Resize(2) '[0] = x und [1] = y
	'oder
	cardSlots[i] = New Int[2] '[0] = x und [1] = y

Nun sollte Deinen weiteren Experimenten nichts mehr im Wege stehen :-)


bye
Ron

Ronny
24.05.2015 16:11

Resize ist eine Methode der Arrays ... in BlitzMax wuerde man

sets = sets[... setsAmount] 

schreiben

@arrayerror
Habe den hier nicht, aber das "GLFW2"-Target hat wohl Probleme mit meinem mehrdimensionalen Array (cardSlots[][]) - wenn ich da cardSlots[1][0] ueberschreibe - also "slot2-x", dann ueberschreibt es das fuer alles).


Schau ich mir nach Mittwoch an (Uni moechte gern ein paar Seiten von mir gedruckt sehen...).


bye
Ron

sushiTV
24.05.2015 14:47

heyho,

habe mir das ganze jetzt nochmal angeschaut, und ich denke das ich das meiste eigentlich verstanden habe *lach*

Zeile 113 ..

        setsAmount = 6
        'Platz schaffen fuer alle Array-Eintraege
        sets = sets.Resize(setsAmount)

Resize bestimmt die Größe (Länge - Length() gw_smiley_zwinkern ) des Arrays? das Resize kann man für alle Arrays einfach aufrufen? ist demnach eine Methode eines Arrays ?

(ich habe nämlich danach gesucht und nicht gefunden *lach*)

Wenn ich versuche das bsp. zum laufen zu bringen, gibts ne fehlermeldung mit "Array index out of range" bei Zeile 169 ?

und ich verstehe nicht so genau wieso *hehe*

happy auf jedenfall läßt sich der quellcode für mich nun nicht ganz so einfach lesen da ich ihn ja nicht selber geschrieben habe :-) kommen auch oft die Worte "card", "slots", "set", als bezeichner von variablen vor in unterschiedlicher kombination so das ich dann manchmal schauen muss was denn nun was ist - und wo was definiert ist*g* - bin halt ungeübt.

~s~

Ronny
20.05.2015 20:36

Ja ... du meinst eine Art "Assoziationsmemory"

Messer, Gabel, Loeffel
Hund, Katze, Maus
Regenwolke, Blitz, Schnee

... Wenn man das machen will, dann sollte man weg vom "TMemoryCardSet".
Jede "TMemoryCard" bekommt eine "typeID" - also eine Kennung die fuer alle "gleichartigen" Karten gleich ist.

Das Spiel zaehlt dann die offenen Karten (max 2) und reagiert auf "2 ungleiche typeID" und "2 gleiche typeID".


Ist nicht sonderlich schwer - bringt aber das in das Spiel, was ich "Twist" nennen wuerde.


Schroeder Kohl Merkel
Roster Steak und (schwer!) Grill-Maiskolben ;-)


bye
Ron

sushiTV
20.05.2015 20:17

Gedanke der die Herangehensweise nochmals verändern könnte:

Ein Memory kann ja auch aus zwei Bildern bestehen – ein Hund in [Schrift] und ein Hund als [Bild] – eine „schwarze Katze“ als Schrift und Bild usw. Prinzip sollte klar sein, könnte man auch mit Geometrischen Figuren oder anderem machen – also Paare Bilden.

~s~

sushiTV
20.05.2015 19:15

hmmmm,

als ich gestern abend nach hause kam, hatte ich mir deinen Quellcode noch angeschaut, aber gegen ende hin meinte dann mein Hirn wohl, das es schon spät ist und der Tag lang war gw_smiley_zwinkern

muss ich mir nochmal anschauen, und dann sind da bestimmt einige fragen.

gruß
~s~

Ronny
19.05.2015 21:35

Ok .. kurze Erklaerung: Diesen Thread gab es schon mal, ich habe aber gerade bei einer Korrektur am neuen Server ausversehen die Datenbank vom alten Server nochmal "ruebergeholt" ... weil ich urtuemlich der Annahme war, dass das Forum noch Verbindung zur alten DB aufnahm ... naja und bevor ich jetzt das Backup von heute Nacht 0 Uhr zurueckhole ... kann ich auch einfach unser Gequatsche um "Monkey X" und "Tutoriale" ein wenig aus dem Google-Cache fischen:

http://webcache.googleusercontent.com/search?q=cache:aenoAcJm6icJ:www.gamezworld.de/phpforum/viewtopic.php%3Fid%3D13584


SushiTV:
---------------
hehe,

ich habe gerade etwas anderes angefangen, die Idee hatte ich letzte Woche einfach spontan - ein Memory programmieren - da hatte ich hier noch nicht in's Forum geschaut.

Erstaunlicher weisse habe ich jetzt in recht kurzer zeit etwas geschafft mit Monkey-X *g*

hier jetzt posten macht in sofern wenig sinn denke ich, da die Bilder dann fehlen also man das nicht Kopieren kann und ausprobieren, würde ja fehlermeldungen bringen. (anhänge hier im Forum gehen ja nicht oder?)

gruß
~s~
---------------

In einem weiteren Post von SushiTV kam sein erster Code:

Import mojo


' ****** Klasse TMemory welches 1 Paar beinhaltet
Class TMemory
    Field x1, y1, w1, h1:Int '****** Koordinaten für 1. Bild des Paares 
    Field x2, y2, w2, h2:Int '****** Koordinaten für 2. Bild des Paares
    Field img:Image 		 '****** Bild des Memorys
    Field imgb:Image		 '****** Deckblatt / Rückseite (kann man vielleicht anders machen da man das ja nur einmal bräuchte
    Field Visible1 = False   '****** Aufgedeckt Bild 1, ja oder nein
    Field Visible2 = False	 '****** Aufgedeckt Bild 2, ja oder nein
    
 	Method New(bild1:String, bildback:String, a1:Int,a2:Int,a3:Int,a4:Int,b1:Int,b2:Int,b3:Int,b4:Int) '****** Methode New der die ganzen Parameter übergeben werden, Koordinaten sollten dann halt per Random generiert werden 
        Self.x1 = a1																				   '****** oder Umgekehrt, die Bilder zufällig verteilt, da habe ich noch keinen plan
        Self.y1 = a2
        Self.w1 = a3
        Self.h1 = a4
        Self.x2 = b1
        Self.y2 = b2
        Self.w2 = b3
        Self.h2 = b4
        Self.img = LoadImage (bild1)
        Self.imgb = LoadImage (bildback)
    End Method	
    
    Method OnCreate()
    End Method
    
    Method OnUpdate() '***** in der OnUpdate wird für jedes Paar überprüft ob die Maus auf dem Bild ist und geklickt wurde, je nachdem wird aktuell einfach der Zustand verändert ob Bild oder Deckblatt sichtbar ist
    If Visible1 = False Then
     If MouseX  > x1 And MouseX < x1+w1 And MouseY > y1 And MouseY < y1+h1 And MouseHit > 0 Then Visible1 = True
    Else If MouseX > x1 And MouseX < x1+w1 And MouseY > y1 And MouseY < y1+h1 And MouseHit > 0 Then Visible1 = False
    End If
    
    If Visible2 = False Then
     If MouseX  > x2 And MouseX < x2+w2 And MouseY > y2 And MouseY < y2+h2 And MouseHit > 0 Then Visible2 = True
    Else If MouseX  > x2 And MouseX < x2+w2 And MouseY > y2 And MouseY < y2+h2 And MouseHit > 0 Then Visible2 = False
    End If
     
    End Method
    
    Method OnDraw()
        If Visible1 = True Then DrawImage (img, x1,y1)
        If Visible1 = False Then DrawImage (imgb, x1,y1)
        If Visible2 = True Then DrawImage (img, x2,y2)
        If Visible2 = False Then DrawImage (imgb, x2,y2)
    End Method
End Class




Class MyApp Extends App
    Field m01:TMemory, m02:TMemory, m03:TMemory, m04:TMemory
    Method OnCreate()
        'wird aufgerufen sobald die App fertiggeladen hat
    
        'Setzt die UpdateRate auf 15 Hertz.
        '15x pro Sekunde wird dadurch OnUpdate() aufgerufen
        'Diese muss unbedingt gesetzt werden, sonst passiert nix
        SetUpdateRate(15)
        m01 = New TMemory("Monkey001.png","Monkeyback.png", 20,20,100,100,130,20,100,100) '****** Koordinaten sind halt jetzt hier einfach hardcore per hand vergeben ;)
        m02 = New TMemory("Monkey002.png","Monkeyback.png", 20,130,100,100,130,130,100,100)
        m03 = New TMemory("Monkey003.png","Monkeyback.png", 20,240,100,100,130,240,100,100)
        m04 = New TMemory("Monkey004.png","Monkeyback.png", 20,350,100,100,130,350,100,100)

    End Method
    
     Method OnRender()
        'Bildschirm leeren, einfarbige Flaeche
        Cls

        'Farbe setzen
        SetColor(255, 255, 255)
        m01.OnDraw()
        m02.OnDraw()
        m03.OnDraw()
        m04.OnDraw()                           
    End Method
    
    
    Method OnUpdate()
        'wird aller "UpdateRate"-Hertz aufgerufen
        '(in unserem Fall aller 15x pro Sek)

        'pro UpdateRate erhoehen wir um 1, macht 15 Pixel pro Sekunde
        m01.OnUpdate()
        m02.OnUpdate()
        m03.OnUpdate()
        m04.OnUpdate()
    End Method
    
    
End Class    
    
Function Main()
    New MyApp
End Function


Es folgten noch ein paar Beispielcodes und Hinweise meinerseits.
Am Ende versprach ich, dass ich mal einen etwas umfangreicheren Code um seinen Ansatz herumstricke.


Hier nun noch folgend der letzte Code (ein erweitertes Beispielprogramm von mir).


Import mojo

'Das "drumherum" unseres Spiels
Class MemoryApp Extends App
	Field game:TGame 'unser derzeitiges Spiel

    Method OnCreate()
        'wird aufgerufen sobald die App fertiggeladen hat
    
        'Setzt die UpdateRate auf 15 Hertz.
        '15x pro Sekunde wird dadurch OnUpdate() aufgerufen
        'Diese muss unbedingt gesetzt werden, sonst passiert nix
        SetUpdateRate(15)

		'Erstellen des TGame-Objektes (dem eigentlichen Spiel)
		'TMemoryGame basiert auf "TGame" - das erlaubt uns einen
		'schicken Wechsel des Spiels ohne diesen "Wrapper" hier
		'veraendern zu muessen
		game = new TMemoryGame()
		'initialisieren des Spiels (Zeug laden)
		game.Init()
    End

        
    Method OnRender()
        'Einsprungspunkt für alle Darstellungen (zeichnen)

		'Spiel-"Grafik" darstellen
        game.Render()
    End

    
    Method OnUpdate()
        'wird aller "UpdateRate"-Hertz aufgerufen
        '(in unserem Fall aller 15x pro Sek)

		'Spiel-"Logik" aktualisieren
        game.Update()
    End
End


'die Main() wird automatisch aufgerufen - hier definieren wir was 
'beim Ausfuehren des Programmes gemacht wird
'"App" definiert, dass OnRender/OnUpdate usw ausgefuehrt werden - da 
'wir unsere MemoryApp von "App" erweitern, uebernehmen wir dieses Verhalten
Function Main()
        New MemoryApp
End Function



'=== Game-Basisklasse ("Vorlage" fuer alle verschiedenen Spiele) ===
Class TGame
	'abstract-Methoden muessen von jedem "TGame"-Abkoemmling
	'"gefuellt" werden 
	Method Init:Void() Abstract
	Method Reset:Void() Abstract
	Method InitDone:Bool() Abstract 'fertig mit Init-Vorgang? 
	Method Update:Void() Abstract
	Method Render:Void() Abstract
End Class


'=== MemoryGame ===
Class TMemoryGame Extends TGame
    'Dinge wie "Fields/Const" kann man schoen am Kopf der Klasse definieren
    'gaenge aber auch zwischen den Funktionen oder am Ende ... aber Uebersicht
    'und so...
    Field sets:TMemoryCardSet[]
	'wieviele Sets gleichzeitig im Spiel?    
	Field setsAmount:Int = 12
	'jedes Spiel hat verschiedene Slots/Plaetze fuer die Karten, da es ja abhaengig
	'von "setsAmount" ist
	'"array of arrays": jede Zeile des ersten Arrays enthaelt zwei weitere Arrays
	'-> cardSlots[1][0] greift auf die 2. Zeile ("0" waere die erste) 
	'   zu - und dann auf die erste Zeile des weiteren Arrays
	'   -> in diesen speichern wir "x", in einer weiteren "y" der Slots ab.
	'   -> alternativ koennten wir auch "Punkte" speichern (und "Punkte" als Klasse
	'      muesste dann "Field x:int, y:int" besitzen).
	'      -> "Global cardSlots:TPoint[12]" und Zugriff: cardSlots[1].x
	Global cardSlots:Int[][]
   
	'alle MemoryGames haetten die gleichen Grafiken ...
	'...da nehmen wir "Global", dann haben alle "bla:TMemoryGame" die
	'   gleichen Bilder
	'   man koennte auch mehr Bilder anbieten als im Spiel vorhanden (mehr
	'   Abwechslung)
	Global cardImages:Image[6]
	Global coverImage:Image
	Global resourcesRequested:Bool = False
	
	
    Method Init:Void()
		'wenn wir noch nicht mit dem Laden der Bilder begonnen haben
		If Not resourcesRequested
			'fuer jedes "cardImage" versuche eine Karte einzuladen
			'Hinweis "to" versus "until":
			'	waehrend for "0 to 2" [0,1,2] beinhaltet, ist bei "until" nur [0,1] drin
			'	hier also von 0 bis 5... was 6 Elemente sind, genau soviel passen in
			'	obigen Array
			For Local i:Int = 0 Until cardImages.Length()
				cardImages[i] = LoadImage("karte"+i+".png")
			Next
			coverImage = LoadImage("cover.png")

			resourcesRequested = True
		Endif
		
		'wir wollen 6*2 Karten = 6 Sets
		setsAmount = 6
		'Platz schaffen fuer alle Array-Eintraege
		sets = sets.Resize(setsAmount)
		
		'Kartenslots definieren (kaum Rechenaufwand, also ruhig erstmal bei 
		'jedem Init()
		'jedes Set enthaelt 2 Karten - also brauchen wir "setsAmount * 2"
		'Plaetze fuer die Karten
		cardSlots = cardSlots.Resize(setsAmount * 2)
		'jeder Slot braucht noch "x" und "y", leider laesst sich das nicht
		'"leichter" in einem Rutsch initialisieren ...
		For Local i:Int = 0 Until cardSlots.Length()
			cardSlots[i].Resize(2) '[0] = x und [1] = y
		Next
		'nun enthaelt:
		'cardSlots[0][0]: "Slot1:x"
		'cardSlots[0][1]: "Slot1:y"
		'Dies nennt sich "zero based" (0 als erste Zeile)

		
		'nun braucht jeder Slot seinen eigentlichen Platz
		'dies koennten wir per "Algorithmus" machen - oder aber per Hand
		'...der Algorithmus ist nicht sonderlich schwer 
		'   ("%" -> modulo und "/" -> Division)
		'   er erlaubt auch ein einfacheres Anpassen der Set-Menge
		'   Sinn waere: "Slots pro Zeile" ausrechnen und diesen Wert als
		'               Modulo-Faktor in einer "Iteration" ueber alle Slots
		'               nutzen. Ergebnis ist die X-Slot-Position.
		'               Nutzt man "/" und rundet, erhaelt man die X-Slot-Position
		'               -> Slot 5, 4 Slots pro Zeile
		'                  x = 5 mod 4 = 1
		'                  y = 5 / 4 = 1 (ganzzahlig)
		'               -> Slot 5 waere also in der zweiten Zeile ("Zeile 0" ist erste)
		'                  und dort in der 1. Spalte
		'               -> ist in etwa wie "abzaehlen" (einfach im Kopf durchgehen)  
		'Variante A
		#rem
		cardSlots[ 0] = [ 50, 50]
		cardSlots[ 1] = [100, 50]
		cardSlots[ 2] = [150, 50]
		cardSlots[ 3] = [200, 50]

		cardSlots[ 4] = [ 50,100]
		cardSlots[ 5] = [100,100]
		cardSlots[ 6] = [150,100]
		cardSlots[ 7] = [200,100]

		cardSlots[ 8] = [200,150]
		cardSlots[ 9] = [200,150]
		cardSlots[10] = [200,150]
		cardSlots[11] = [200,150]
		#end
		
		'Variante B
		Local slotsPerRow:Int = 4
		Local slotsWidth:Int = 50, slotsHeight:Int = 50
		'wir fangen bei "50,50" an - weswegen wir die 50 immer schoen addieren muessen
		For Local i:Int = 0 Until cardSlots.Length()
			cardSlots[i][0] = 50 +  (i Mod slotsPerRow) * slotsWidth
			cardSlots[i][1] = 50 +  (i / slotsPerRow) * slotsHeight
		Next
		'-> wir haben nun alle Slots festgelegt


		'damit kein Kartenbild mehrfach genommen wird, muessen wir eine Tabelle
		'bereitstellen, die alle moeglichen Bilder beinhaltet, wird eines davon
		'ausgewaehlt, steht es den weiteren Karten nicht mehr zur Verfuegung
		Local availableCardImages:Int[cardImages.Length()]
		For Local i:Int = 0 Until cardImages.Length()
			availableCardImages[i] = i
		Next
		'availableCardImages nun [0,1, ..., Laenge-1)


		'gleiches tun wir fuer die moeglichen Positionen der Karten,
		'wir brauchen hier aber nur die Positionsnummer - nicht die Koordinaten
		Local availableCardSlots:Int[cardSlots.Length()]
		For Local i:Int = 0 Until cardSlots.Length()
			availableCardSlots[i] = i
		Next
		
		'nun mischen wir die Kartenslots durcheinander - dadurch koennen wir
		'nachfolgend einfach eine nach der anderen erstellen und von "oben"
		'Kartenslots abrufen.
		'Dafuer nutzen wir eine kleine Hilfsfunktion die einen "Mischalgorithmus"
		'nutzt
		availableCardSlots = ShuffleIntArray( availableCardSlots )
		'availableCardSlots nun also [1,5,11,...,3]

		
		
		For Local i:Int = 0 Until sets.Length()
			'Das bild nehmen, was an der Stelle liegt, die von der ersten
			'Zeile in "availableCardImages" definiert wird
		    Local img:Image = cardImages[availableCardImages[0]]
		    'Diese Zeile entfernen ... nun liegt andere Zeile an oberster
		    'Stelle
		    availableCardImages = availableCardImages[1..]

			'obersten Kartenslot
			Local cardSlot1:Int = availableCardSlots[0]
			'obersten Kartenslot entfernen
		    availableCardSlots = availableCardSlots[1..]

			'wieder obersten Kartenslot
			Local cardSlot2:Int = availableCardSlots[0]
			'obersten Kartenslot entfernen
		    availableCardSlots = availableCardSlots[1..]

			'Karten anlegen - mit ihren jeweiligen Koordinaten		
			'Dimensionen sind 40x40 - damit haben wir einen kleinen Rand bei den "50x50" Slots
			Local card1 := New TMemoryCard( cardSlots[cardSlot1][0], cardSlots[cardSlot1][1], 40, 40, i, img)
			Local card2 := New TMemoryCard( cardSlots[cardSlot2][0], cardSlots[cardSlot2][1], 40, 40, i, img)

			'beide Karten als ein Set speichern
		    sets[i] = New TMemoryCardSet(i, card1, card2)
		    
		    Print "Kartenset "+i+" initialisiert."
		Next		
		
		Print "Initialisierung beendet."
    End Method


	Method Reset:Void()
		'bis jetzt machen wir noch nix, aber eigentlich Karten
		'zuruecksetzen
	End Method


	Method InitDone:Bool()
		'Bei Zielen wie "Html5" bedeutet "LoadImage", dass die Anfrage
		'an den Server gestellt wird, doch bitte das Bild zu laden.
		'In dem Moment ist es noch nicht da ... das passiert dann
		'irgendwann spaeter
		'Aus diesem Grund ueberpruefen wir einfach jede Resource, ob
		'sie schon fertiggeladen ist ("nicht Null").
		'Hinweis: Eine fehlende Resource wuerde aber auch "null" sein.


		'noch nicht mal angefangen mit laden?
		if not resourcesRequested then return False
		
		'cover fehlt noch
		if not coverImage then return False

		'eine der Karten noch nicht geladen?
		for local i:int = 0 until cardImages.Length()
			if not cardImages[i] then return False
		Next

		'.... weitere Resourcen ueberpruefen
		
		Return True
	End Method


	Method Update:Void()
        For local i:int = 0 until sets.Length()
            sets[i].Update()
        Next
	End Method


	Method Render:Void()
		DrawText("render", 0,0)

        For Local i:Int = 0 Until sets.Length()
            sets[i].Render()
        Next
    End Method

    
    'Kleiner Helfer um Zahlenarrays "zu mischen"
    '(Fisher-Yates Shuffle algorithm)
	Function ShuffleIntArray:Int[](arr:Int[])
		'2-10x durchmischen
		For Local r:Int = 0 To Rnd(2, 10)
			For Local i:Int = arr.Length-1 To 0 Step -1
				Local index:Int = Int(Rnd (0, i))
				'array-zeilen vertauschen
				Local tmp:Int = arr[index]
				arr[index] = arr[i]
				arr[i] = tmp
			Next
		Next
		Return arr
	End Function
End Class



'Eine einzelne Karte
Class TMemoryCard
    Field x:Int, y:Int          'Koordinaten
    Field w:Int, h:Int          'Dimensionen
    Field img:Image             'Bild des Memorys
    Field flipped:Bool = False  'aufgedeckt, ja oder nein
    Field setNumber:Int = -1


    Method New(x:Int, y:Int, w:Int, h:Int, setNumber:Int, img:Image)
        Self.x = x
        Self.y = y
        Self.w = w
        Self.h = h
        Self.setNumber = setNumber
        Self.img = img
    End Method


    Method Reset:Void()
        flipped = False
    End Method
    

    Method Update:Void()
        'check ob maus drin
        If MouseX() >= x And MouseX() < x + w And MouseY() >= y And MouseY() < y + h
            'wenn ja und Maus geklickt... "flipped" umtauschen
            if MouseHit() then flipped = not flipped
        EndIf
    End Method


    Method Render:Void()
		If flipped
			If img
				DrawImage (img, x,y)
			Else
				'Farbe des Ersatzbildes ist einfach abhaengig von der 
				'Setnummer
				SetColor 70*(setNumber Mod 2),90*(setNumber Mod 3),80*(setNumber Mod 4)

				DrawRect(x,y,w,h)

				'Farbe zuruecksetzen
				SetColor 255,255,255
			Endif
		Else
			'hier greifen wir auf das in TMemoryGame als global definierte
			'coverBild zurueck - man koennte auch ein eigenes darstellen...
			If TMemoryGame.coverImage
				DrawImage (TMemoryGame.coverImage, x,y)
			Else
				'Deckblatt ist "grau"
				SetColor 100,100,100

				DrawRect(x,y,w,h)

				'Farbe zuruecksetzen
				SetColor 255,255,255
			Endif
		Endif
		
		DrawText(setNumber, x,y)
    End Method
End Class


'Die zusammengehoerigen Karten
Class TMemoryCardSet
    Field card1:TMemoryCard
    Field card2:TMemoryCard
    Field setNumber:Int 

    Method New(setNumber:Int, card1:TMemoryCard, card2:TMemoryCard)
        Self.card1 = card1
        Self.card2 = card2
        Self.setNumber = setNumber
    End Method


    'gibt "True" zurueck, wenn beide Karten aufgedeckt sind,
    'ansonsten "False"
    Method IsSolved:Bool()
        return card1.flipped and card2.flipped
    End Method
    

    'alle enthaltenen Karten aktualisieren
    Method Update:Void()
        'jede Karte schaut fuer sich selbst, ob sie aufgedeckt ist
        'oder nicht usw.
        card1.Update()
        card2.Update()
    End Method


    Method Render:Void()
        card1.Render()
        card2.Render()
    End Method
End Class

bye
Ron