/*
Programmbeschreibung:
Die oberen vier Knöpe sind zum navigiern des Kursers und der untere Knopf zum Bestätigen der Position
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Initialisierung des LCD-Displays mit Adresse 0x27, 20 Zeichen und 4 Zeilen
LiquidCrystal_I2C lcd(0x27, 20, 4);

// Spielfeld und Variablen
char board[3][3] = {
  {' ', ' ', ' '},
  {' ', ' ', ' '},
  {' ', ' ', ' '}
};
int selectedRow = 0, selectedCol = 0;  // Aktuelle Auswahl
char currentPlayer = 'X';             // Aktueller Spieler
bool gameWon = false;                 // Status: Hat jemand gewonnen?
bool gameDraw = false;                // Status: Unentschieden?

// Taster-Pins
const int upButton = 6;
const int downButton = 7;
const int leftButton = 8;
const int rightButton = 9;
const int confirmButton = 10;

void setup() {
  // Initialisierung des LCD-Displays
  lcd.begin(20, 4);    // LCD mit 20 Zeichen und 4 Zeilen initialisieren
  lcd.backlight();     // Hintergrundbeleuchtung einschalten

  // Setze Taster-Pins
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(leftButton, INPUT_PULLUP);
  pinMode(rightButton, INPUT_PULLUP);
  pinMode(confirmButton, INPUT_PULLUP);

  drawBoard();         // Zeige das Start-Spielfeld an
}

// Hauptprogramm
void loop() {
  if (!gameWon && !gameDraw) {  // Nur wenn das Spiel noch läuft
    handleInput();
  }
}

// Eingaben verarbeiten
void handleInput() {
  if (digitalRead(upButton) == LOW) {
    selectedRow = (selectedRow + 2) % 3; // Nach oben (zyklisch)
    delay(200); // Entprellen
    drawBoard();
  }
  if (digitalRead(downButton) == LOW) {
    selectedRow = (selectedRow + 1) % 3; // Nach unten (zyklisch)
    delay(200);
    drawBoard();
  }
  if (digitalRead(leftButton) == LOW) {
    selectedCol = (selectedCol + 2) % 3; // Nach links (zyklisch)
    delay(200);
    drawBoard();
  }
  if (digitalRead(rightButton) == LOW) {
    selectedCol = (selectedCol + 1) % 3; // Nach rechts (zyklisch)
    delay(200);
    drawBoard();
  }
  if (digitalRead(confirmButton) == LOW) {
    if (board[selectedRow][selectedCol] == ' ') {
      board[selectedRow][selectedCol] = currentPlayer;
      if (checkWinner(currentPlayer)) {
        gameWon = true;
        displayWinner(currentPlayer);
      } else if (checkDraw()) {
        gameDraw = true;
        displayDraw();
      } else {
        currentPlayer = (currentPlayer == 'X') ? 'O' : 'X'; // Spielerwechsel
        drawBoard();
      }
    }
    delay(200);
  }
}

// Spielfeld zeichnen
void drawBoard() {
  lcd.clear(); // LCD Bildschirm löschen

  // Zeile 1 (erste drei Felder)
  lcd.setCursor(0, 0);
  lcdPrintCell(0, 0);
  lcd.print("|");
  lcdPrintCell(0, 1);
  lcd.print("|");
  lcdPrintCell(0, 2);

  // Zeile 2 (zweite drei Felder)
  lcd.setCursor(0, 1);
  lcdPrintCell(1, 0);
  lcd.print("|");
  lcdPrintCell(1, 1);
  lcd.print("|");
  lcdPrintCell(1, 2);

  // Zeile 3 (dritte drei Felder)
  lcd.setCursor(0, 2);
  lcdPrintCell(2, 0);
  lcd.print("|");
  lcdPrintCell(2, 1);
  lcd.print("|");
  lcdPrintCell(2, 2);

  // Zeile 4 für Statusanzeige
  lcd.setCursor(0, 3);
  if (!gameWon && !gameDraw) {
    lcd.print("Player: ");
    lcd.print(currentPlayer); // Zeigt den aktuellen Spieler
  }
}

// Funktion zum Zeichnen der Zellen auf dem Display
void lcdPrintCell(int row, int col) {
  if (selectedRow == row && selectedCol == col) {
    lcd.print("[");
    lcd.print(board[row][col]);
    lcd.print("]");
  } else {
    lcd.print(" ");
    lcd.print(board[row][col]);
    lcd.print(" ");
  }
}

// Überprüft, ob ein Spieler gewonnen hat
bool checkWinner(char player) {
  // Überprüfen von Zeilen
  for (int row = 0; row < 3; row++) {
    if (board[row][0] == player && board[row][1] == player && board[row][2] == player) {
      return true;
    }
  }

  // Überprüfen von Spalten
  for (int col = 0; col < 3; col++) {
    if (board[0][col] == player && board[1][col] == player && board[2][col] == player) {
      return true;
    }
  }

  // Überprüfen von Diagonalen
  if (board[0][0] == player && board[1][1] == player && board[2][2] == player) {
    return true;
  }
  if (board[0][2] == player && board[1][1] == player && board[2][0] == player) {
    return true;
  }

  return false; // Kein Gewinn gefunden
}

// Überprüft, ob das Spiel unentschieden endet
bool checkDraw() {
  for (int row = 0; row < 3; row++) {
    for (int col = 0; col < 3; col++) {
      if (board[row][col] == ' ') {
        return false; // Noch mindestens ein leeres Feld
      }
    }
  }
  return true; // Alle Felder sind gefüllt, ohne Gewinner
}

// Gewinner auf dem Display anzeigen
void displayWinner(char winner) {
  lcd.clear();  // Display löschen
  lcd.setCursor(0, 1);  // Gewinner-Nachricht zentriert in Zeile 2
  lcd.print("Player ");
  lcd.print(winner);
  lcd.print(" wins!");
}

// Unentschieden auf dem Display anzeigen
void displayDraw() {
  lcd.clear();  // Display löschen
  lcd.setCursor(0, 1);  // Nachricht zentriert in Zeile 2
  lcd.print("It's a Draw!");
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r
btn5:1.l
btn5:2.l
btn5:1.r
btn5:2.r
btn7:1.l
btn7:2.l
btn7:1.r
btn7:2.r
btn10:1.l
btn10:2.l
btn10:1.r
btn10:2.r
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL