TicTac Toe Projekt
Praktikum aus Programmierung
Markus
Fraisl (email:
12.1.2003
Im Zuge des Rechnerpraktikums aus Java Programmierung ist mir die Aufgabe gestellt worden, mittels Thread-Technologie und Socketprogrammierung ein Spiel zu programmieren; ich habe mich aus Gründen der Einfachheit des Spiels an sich (und dadurch auch aus Gründen der einfacheren Programmierbarkeit) für TicTacToe entschieden. Sinn des Projekts ist es, dass sich verschiedene user via telnet am TicTacToeServer einloggen können sollen, um miteinander über Netzwerk spielen bzw. miteinander kommunizieren zu können, wofür die Programmierung eines Protokolls vorgesehen ist. Zwei user sollen jeweils miteinander spielen können, wozu immer 2 Protokolle an einem Spiel hängen. Das Problem dabei ist, dass eben mehrere user gleichzeitig online sein können, und jeder von diesen im Prinzip ein Spiel mit einem anderen Benutzer starten kann, wobei hier wiederum das Problem ist, dass genau 2 Spieler gleichzeitig miteinander spielen, wodurch sich das Problem ergibt, dass diese eben über das Spiel miteinander „verknüpft“ sein müssen. Durch diese Tatsache des „Verknüpft-sein–müssens“ ergibt sich wiederum die Frage, wie denn vom System erkannt wird, welcher Spieler gerade am Zug ist (da nicht jeder der beiden Benutzer gleichzeitig in das Spielfeld eingreifen darf), bzw. wie vom System, zu welcher Zeit erkannt wird, wann ein Spieler gewonnen hat (und vor allem welcher Spieler dies ist). Nicht zuletzt sollte auch beachtet werden, was passiert, wenn sich ein Benutzer ausloggt, und dafür gesorgt werden, dass vor allem dadurch keine Fehler auf längere Sicht entstehen können (durch Benutzer, die zwar im System verzeichnet, aber schon lange ausgeloggt sind).
Das Problem ist primär, dass sich 2 Protokolle an ein Spiel anhängen, wofür man eindeutige Erkennungsmerkmale braucht, damit eine Kommunikation der user über den Server ermöglicht wird. Ein Protokoll soll jeweils für Ein- bzw. Ausgabe an einen Benutzer bzw. an das System sorgen, wodurch ein sicheres Kommunizieren mit dem System und – im Spiel – auch mit anderen Benutzern von statten gehen kann. Das eigentliche Problem stellt also vor allem das Protokoll bzw. dessen Entwicklung dar, da dadurch festgelegt wird, wie ein Benutzer mit dem System zu kommunizieren hat. Auch der Spielablauf an sich, wie man diese Kommunikation von 2 Protokollen miteinander realisiert, ist ein Punkt, dem unbedingt Aufmerksamkeit geschenkt werden sollte.

Use Case Diagramm
Das zentrale Problem, die Kommunikation bzw. das Anhängen zweier Protokolle an ein Spiel habe ich dadurch gelöst, dass ein Benutzer immer ein Spiel starten kann, und dann auf jemanden warten muss, der sich eventuell zu ihm ins Spiel „einloggt“.
Die Kommunikation der user erfolgt über das Protokoll, wozu ich am Server eine Threadliste angelegt habe, in der jeder Thread eine ID hat, somit eindeutig identifiziert werden kann. Auch jeder Benutzer bekommt (dieselbe ID wie sein Thread) beim Einloggen zugewiesen.
Ein anderer Spieler der also ebenfalls spielen will, kann durch Eingabe des Wortes „list“ eine Userliste der gerade online stehenden user abfragen, und sich danach mit einem gerade wartenden user verbinden.
Wer am Zug ist, bzw. wo man im Spiel gerade steht, wickelt das Spiel selbst ab, dazu braucht es das Protokoll eigentlich nicht; zur Kommunikation aber werden jeweils Referenzen der jeweiligen user und der jeweiligen Protokolle ans Spiel übergeben, sodass immer bekannt ist, an wen was ausgegeben bzw von wem was eingegeben wird.
Das Protokoll, welches die Aufgabe hat Input – Output – Brücke zwischen user und System zu sein, implementiert Methoden, wie man die Online user Liste abfragen kann, wie man ein Spiel starten bzw. sich einem Spiel anhängen kann, wie man eine Anleitung zum Spiel erhält, wie man eine Anleitung der Befehle, die man eingeben darf/kann erhält und wie man sich wieder ausloggt.
Zur Kommunikation mit dem Spiel werden jeweils Referenzen übergeben, sodass ein Zugreifen auf die Methoden des Protokolls ermöglicht wird. Auch hat das Protokoll eine Referenz auf den Server und auf den eigenen Thread, wodurch deren Manipulation durch das Protokoll ermöglicht wird.
Am Server selbst sind drei LinkedLists implementiert: eine für die Threads, eine für die user/Spieler und eine für die Spiele. Wenn sich ein user ausloggt, dann wird er und auch sein Thread von der Liste wieder gelöscht, wodurch es zu einer Absturzminimierung auf Serverseite kommt. Auch wenn ein Spiel beendet wird, sei es, weil ein Benutzer einen Abbruch erwirkt, oder weil es endet, da ein Spieler gewonnen hat, wird es wieder aus der LinkedList entfernt.

Klassendiagramm

Sequenzdiagramm
Ich habe mir im Zuge der Implementierung gedacht, dass es, da ja sowieso schon 2 Protokolle, an die jeweils ein Benutzer geknüpft ist, während eines Spiels miteinander verbunden sind, sollte es auch kein Problem sein, einen kleinen Chat zu realisieren. Dadurch ist es nun möglich, dass 2 Benutzer während eines Spiels miteinander Gedanken austauschen.
Für das Starten des Servers – an sich etwas, was einen Benutzer nicht zu kümmern hat – habe ich ein batch-Skript erstellt, welches das Initialisieren des Servers mit einem befehl ausführt. Ansonsten gibt es keine Besonderheiten in der Implementierung
Um in den Genuss des Spiels zu gelangen, muss sich ein Anwender mit dem Befehl „telnet IPAdresse 4444“ am Server einloggen. Danach wird er gefragt, welchen Namen er haben will. Sodann stehen im einige Möglichkeiten zur Auswahl: „anleitung“ bewirkt eine Ausgabe der generellen Spielanleitung (wie das Spiel funktioniert, was das Ziel des Spiels ist, wie ein Spieler gewinnen kann); „help“ bewirkt eine Ausgabe der Befehle, die er eingeben kann, um zu seinem Ziel zu kommen. Mit „spiel“ kann ein Benutzer ein Spiel starten, und hat dann zu warten, bis sich ein anderer Benutzer durch den Befehl „spielmit“ zu ihm gesellt. Wenn ein anderer Benutzer diesen Befehl eingibt, dann sieht er zuerst eine Liste der user, die online sind und eventuell auf ein Spiel warten. Er kann dann durch Eingabe der ID des user in ein Spiel einsteigen. Der Benutzer, der im Spiel an der Reihe ist, kann mit „-Zahl,Zahl“, wobei die Zahl immer von 0 bis 2 geht, dies also die 3x3 Matrix des Spielfelds von TicTacToe darstellt, den Ort wählen, wo er gerne sein Symbol platzieren würde. Mit „/text“, wobei text eine Nachricht darstellt, kann ein Benutzer während des Spiels mit einem anderen Benutzer chatten. Am Ende des Spiels erhält der Gewinner 2 Punkte. Durch „cancel“ wird ein Spiel abgebrochen, wodurch der Gegner desjenigen, der abgebrochen hat, als „Schadensersatz“ einen Punkt bekommt, aber auch ein user, der schon des Wartens auf einen Opponenten überdrüssig geworden ist, kann sich dadurch wieder aus dem von ihm initiierten Spiel ausklinken. Mit „bye“ schließlich kann ein user sich vom TicTacToe Server ausloggen und wird mit einer kurzen Abschlussnachricht verabschiedet.