TigerJython | xx für Gymnasien |
16 Karten, die paarweise übereinstimmen, sind zu Beginn in einer zufälligen Reihenfolge verdeckt aufgelegt. Der erste Spieler deckt mit zwei Mausklicks zwei Karten auf. Wenn er zwei gleiche Karten trifft, bleiben die Karten aufgedeckt und sein Zug wird fortgesetzt. Sonst werden beide Karten wieder verdeckt und der zweite Spieler kommt zum Zug. Gewonnen hat der Spieler, der am Ende die meisten Paare aufgedeckt hat.
Player 0 |
Player 1 |
Die beiden Spieler wählen das gleiche Topic /swissgame/memory und müssen vor dem Spielbeginn die Programmzeile player = 0 bzw. player = 1 ergänzen. Der Player 0 beginnt. Bei beiden Spielern werden zu Beginn Karten in der gleichen zufälligen Reihenfolge gelegt. Dazu wird eine Liste rndList mit zufällig angeordneten Zahlen 0 bis 15 erzeugt. Die 16 Spielkarten werden danach gemäss dieser Liste angeordnet und zugedeckt (show(0)) angeeigt.
Die Überprüfung und Verdecken der zwei gewählten Karten erfolgt in den Callbacks onMousePressed() und onStateChanged(). Da man grundsätzlich in Callbacks nicht zu viele Operationen ausführen soll (insbesondere keine blockierende Funktionen), wird dies durch das Hauptprogramm gemacht. Dort wird in der while True-Schleife das Programm mit putSleep() angehalten, bis zwei Karten aufgedeckt sind. Die Programmausführung wird dann mit wakeUp() fortgesetzt. Nicht passende Karten werden nach einer Verzögerung von 1 Sekunde wieder zugedeckt.
Im Folgenden findet man zwei Lösungsvarianten. Die erste Lösung enthält ein Server- und ein Clientprogramm. In dieser Form ist es einfacher, der Interaktion zwischen dem Client und Server zu folgen. In der zweiten Variante werden Programmteile, die sowohl im Server- als auch im Client-Programm vorkommen, in der Datei memlib.py gespeichert. Diese muss in beiden Programmen importiert werden.
# Memory.py from gamegrid import * from mqttclient import GameClient import random player = x # set player = 0 or player = 1 myTopic = "/swissgame/memory" class MemoryCard(Actor): def __init__(self, cardNb): Actor.__init__(self, ["sprites/cardback.gif", "sprites/card" + str(cardNb) + ".gif"]) self.cardNb = cardNb def getCardNb(self): return self.cardNb def createCards(): cardList = [] for i in range(16): if i < 8: card = MemoryCard(i) else: card = MemoryCard(i - 8) cardList.append(card) k = 0 for i in rndList: x = i % 4 y = i // 4 loc = Location(x, y) addActor(cardList[k], loc) cardList[k].show(0) k += 1 def onMousePressed(e): global card1, card2, isFirst if not isMyMove or isGameOver: return loc = toLocationInGrid(e.getX(), e.getY()) client.sendMessage(str(loc.x) + str(loc.y)) # send location card = getOneActorAt(loc) if card.getIdVisible() == 1: # card already visible->ignore return card.show(1) # make card visible if isFirst: card1 = card setStatusText("Take second card!") isFirst = False else: # second card taken card2 = card isFirst = True wakeUp() def onNotifyExit(): client.disconnect() dispose() def onStateChanged(state): global isMyMove if state == "CONNECTING": setStatusText("Connecting to broker...") elif state == "CONNECTED": setStatusText("Connected. Waiting for partner...") elif state == "READY": if player == 0: setStatusText("Make a move!") client.sendMessage(str(rndList)) isMyMove = True else: setStatusText("Wait for partner's move!") elif state == "DISCONNECTED": setStatusText("Partner disconnected!") isMyMove = False def onMessageReceived(msg): global isFirstRec, card1, card2, rndList if msg[0] == "[": s = msg[1:-1] config = s.split(",") rndList = [int(z) for z in config] createCards() else: x = int(msg[0]) y = int(msg[1]) loc = Location(x, y) card = getOneActorAt(loc) card.show(1) if isFirstRec: card1 = card isFirstRec = False else: card2 = card isFirstRec = True wakeUp() makeGameGrid(4, 4, 115, Color.black, False, mousePressed = onMousePressed, notifyExit = onNotifyExit) addStatusBar(30) setTitle("Memory") rndList = random.sample(range(16), 16) createCards() show() doRun() PORT = 5000 isGameOver = False isMyMove = False isFirst = (player == 0) isFirstRec = True myHits = 0 partnerHits = 0 setTitle("Player #" + str(player)) host = "m2m.eclipse.org" client = GameClient(onStateChanged, onMessageReceived, myTopic) client.connect(host) while True: putSleep() if isDisposed(): break if card1.getCardNb() == card2.getCardNb(): # test if cards have same image if isMyMove: myHits += 1 setStatusText("Pair accepted. Take nextCard") else: partnerHits += 1 if myHits + partnerHits == 8: isGameOver = True if myHits > partnerHits: setStatusText("Game over! You won with " + str(myHits) + " hits.") elif myHits < partnerHits: setStatusText("Game over! You lost with only " + str(myHits) + " hits.") else: setStatusText("Game over! The score is even.") else: # hide the two cards delay(1000) card1.show(0) card2.show(0) if isMyMove: isMyMove = False setStatusText("Wait!") else: isMyMove = True setStatusText("You play. Take two cards!") |
Erklärungen zum Programmcode:
rndList = random.sample(range(16), 16): Erzeugt 16 eindeutige Zufallszahlen zwischen 0 und 15 | |
for i in rndList: Geht die Zufallsliste durch und legt mit Hilfe dieser Zufallszahlen Karten in die 16 Zellen |