# Projekt TicTacToe
## Anfang
Jeder kennt TicTacToe und es ist einfaches, schnell verstandenes Spiel. Zudem ist es ein guter Einstieg um Objektorientiertes programmieren zu lernen.
Versuche mit deinen Kenntnissen die du gesammelt hast, TicTacToe zu programmieren, es ist herausfordernd, aber machbar.
Im folgenden Text findest du Hilfsmittel die dir dabei helfen, TicTacToe Objektorientiert zu programmieren.
## Voraussetzungen
Folgende Sachen musst du können:
- Variablen definieren
- Verzweigungen und Schleifen anwenden können
- Array verstehen, erstellen und benutzen können
- Grundprinzip der Objektorientierten Progammierung(Klassen, Methoden, Objekte) verstehen
- GET und SET Methoden erstellen können
- Konstruktor und seine Parameter verstehen
- Verstehen wie man Funktionen aufruft
- Unterschied zwischen private und public verstehen
Als Hilfestellung: https://www.w3schools.com/php/default.asp
## Herangehensweise (Planung)
Es ist wichtig für objektorientiertes Programmieren einen Plan zu haben.
Hier ein paar Punkte für den Start:
- Das Spiel in Klassen aufteilen (Klassendiagramm erstellen)
- Festlegen, welche Funktionen in welcher Klasse benötigt werden (z.B GET und SET Methoden)
- Nötige Parameter definieren, die bei den Funktionen übergeben werden müssen
- Überlegen welche Funktionen andere Funktionen aufrufen müssen (z.B GET und SET müssen in anderen Funktionen aufgerufen werden)
- Überlegen wie das aktuell laufende Spiel gespeichert werden kann
- Möglichkeit entwicklen um das Spiel neuzustarten (Button?)
## Erste Schritte
1. Die Klassen mit ihren Attributen erstellen
2. Getter und Setter Methoden schreiben.
3. Konstruktor erstellen.
4. Objekte erstellen
5. Methoden erstellen welche in Zukunft noch benutzt werden.
6. 2D Array programmieren für das board
7. Nach und nach die einzelene Algorithmen für die Methoden programmieren.
8. Button erstellen für Neustart/Reset
## Probleme
Problem: Namen bei Variablen/Klassen/Methoden verwendet, wo man später nicht mehr wusste, für was sie zuständig sind oder einen verwirren.
> Lösung: Namen so wählen, dass es für andere übersichtlich bleibt und Sinn ergibt.
Problem: Die verschiedenen Klassen sinnvoll zu verknüpfen, so dass das Gewollte ah funktioniert.
> Lösung: Genau überlegen für was die Methoden im Spiel gebraucht werden.
Problem: Einzelne Methoden sind zu lang geworden.
> Lösung: Sobald eine Methode mehr als eine Funktion erfüllt, lohnt es sich diese aufzuteilen. Wenn Methoden zu lang werden, sind sie unübersichtlich und fehleranfällig.
Problem: Die Methoden sind nicht weit genug aufgeteilt.
> Lösung: z.B. hatte ich ursprünglich keine Methode um x und y einzugeben, sondern es an den nötigen Stellen einzeln umgesetzt, was zu Problemen führte. An solches Stellen hilft es für diese Funktion eine eigene Methode zu implementieren.
Problem: Vergessen, wozu der Code nützlich ist, den man vor einigen Tagen geschrieben hat.
> Lösung: Punkt 1. hilft schon dabei. Einige Kommentare im Code z. B. zu den Methoden kann noch weitere Unterstützung bieten.
Problem: Das Programm läuft nicht wie gewollt.
> Lösung: Ermittle den Fehler anhand von Debuggern (print() zwischen Zeilen im Code).
Problem: Der Fehler wurde gefunden, man weiß aber nicht wie man ihn behebt.
> Lösung: Erst das Problem googlen. Oft wurden ähnliche Fehler online schon behoben. Wenn man nicht weiter weiß, frag Freunde oder Lehrer. Zusammen kann man das Problem möglicherweise weiter aufteilen oder ganz lösen.
Problem: Probleme beim Aufrufen der Getter und Setter Methoden
> Lösung: Getter und Setter Methodenaufruf im PHP Manual nachschlagen
Problem: Abspeichern der aktuellen Spielsession
> Lösung: Sessions im PHP Manual nachschlagen
Problem: Klassen inkludieren
> Lösung: Include im PHP Manual nachschlagen
---
## UML-Klassendiagramm
::: spoiler Entwürfe
```plantuml
skinparam style strictuml
skinparam class {
BackgroundColor white
ArrowColor gray
BorderColor black
}
class Player {
- symbol: String
- number: int
+ getNickName(): String
+ getSymbol(): String
+ getPlayerNumber(): int
+ setNickName(String)
+ setSymbol(String)
+ setPlayerNumber(Int)
}
class Game {
- player1: Player
- player2: Player
- current_Player: Player
- board: GameBoard
- gameState: Integer
+ getPlayer1():Player
+ getPlayer2():Player
+ setPlayer1(Player)
+ setPlayer2(Player)
+ getGameBoard():GameBoard
+ setGameBoard(GameBoard)
+ getCurrentPlayer():Player
+ setCurrentPlayer(Player)
+ getGameState(): Int
+ setGameState(int)
+ reset()
+ run()
+ changePlayer()
}
class Gameboard{
- array[][]:string
+ getBoard(): Array
+ setBoard(): Array
+ countFreeItems(): Integer
+ isWin(): Boolean
+ setItem(x,y,player)
+ getItem(x,y):String
+ reset()
}
Game -- Gameboard
Game -- Player
```
```plantuml
skinparam style strictuml
skinparam class {
BackgroundColor white
ArrowColor gray
BorderColor black
}
class Player {
- symbol: char
+ getSymbol(): char
+ setSymbol(String)
}
class Game {
- firstPlayer: Player
- secondPlayer: Player
- currentPlayer: Player
- tttboard: GameBoard
- validValue: boolean
- x: int
- y: int
+ getFirstPlayer():Player
+ getSecondPlayer():Player
+ setFirstPlayer(Player)
+ setSecondPlayer(Player)
+ getBoard():Board
+ setBoard(Board)
+ getCurrentPlayer():Player
+ setCurrentPlayer(Player)
+ getGameState(): Int
+ setGameState(int)
+ setXY()
+ getX(): int
+ getY(): int
+ checkTaken(): boolean
+ makeTurn()
}
class Board{
- array[][]: char
+ getItem(x,y): char
+ setItem(x,y,player)
+ getTttboard(): Array
+ setTttboard(char[][])
+ countFreeItems(): Integer
+ checkWin(currentPlayer)
+ checkNoDraw(): boolean
+ drawBoard()
}
Game -- Board
Game -- Player
```
```plantuml
skinparam style strictuml
skinparam class {
BackgroundColor white
ArrowColor gray
BorderColor black
}
class Player {
- symbol: String
- number: int
+ getSymbol(): String
+ getNumber(): int
+ setSymbol(String)
+ setNumber(Int)
}
class Game {
- player[]: array of Player
- current_Player: Player
- board: GameBoard
- gameState: Integer
+ getPlayer(int number):Player
+ setPlayer(Player)
+ getBoard():GameBoard
+ setBoard(GameBoard)
+ getCurrentPlayer():Player
+ setCurrentPlayer(Player)
+ getState(): Int
+ setState(int)
+ reset()
+ run()
+ changePlayer()
}
class Gameboard{
- array[][]:string
+ getBoard(): Array
+ setBoard(): Array
+ countFreeItems(): Integer
+ hasWin(player): Boolean
+ setItem(x, y, player)
+ getItem(x, y): String
+ reset()
}
Game -- Gameboard
Game -- Player
```
:::
```plantuml
skinparam style strictuml
skinparam class {
BackgroundColor white
ArrowColor gray
BorderColor black
}
class Player {
- character: string
- number: int
- name: string
+ Player()
+ getCharacter(): string
+ setCharacter(string)
+ getNumber(): string
+ setNumber(int)
+ getName(): string
+ setName(string)
}
class Board {
- fields[]: array
+ getFields(): array
+ setFields(array)
+ setCharacter(Player, index:int): bool
+ getCharacter(index:int): string,
+ checkWin(Player): bool
+ checkDraw(): bool
+ reset()
+ showBoard()
}
class TicTacToe {
- player[]: array
- activePlayer: Player
- tttBoard: Board
+ TicTacToe()
+ getBoard(): Board
+ getActivePlayer(): Player
+ setActivePlayer(Player)
+ getPlayer1(): Player
+ setPlayer1(Player)
+ getPlayer2(): Player
+ setPlayer2(Player)
+ switchPlayer()
+ playTTT()
}
TicTacToe -- Board
TicTacToe -- Player
```
**Lizenz** für den oben stehenden Text: CC0
**Autoren:** RM, HB, NM, IF