If-Abfrage später auslesen/Andere Option?

Hey! Ich muss ein Schulprojekt mit Arduino programmieren und habe mich für TicTacToe entschieden. Dabei habe ich 9 Knöpfe die je für ein Feld auf dem Lcd Display stehen. Ich versuche gerade einen Gewinnmechanismus zu programmieren, habe jetzt aber das Problem, dass ich die Taster jeweils doppelt belegt habe (1x drücken -> x, 2x drücken -> o) und ich jetzt wenn zwei x in einer Reihe sind und der o blockieren will, zuerst x angezeigt wird und damit der Gewinnmechanismus ausgelöst wird. Gibt es die Möglichkeit, die Abfrage des Gewinns erst nach einer Zeit durchzuführen oder eine andere Möglichkeit das Problem zu umgehen? Danke!

const int taster1 = 2;  //Taster 1 = Port 2
const int taster2 = 3;  //Taster 2 = Port 3
const int taster3 = 4;  //Taster 3 = Port 4
const int taster4 = 5;  //Taster 4 = Port 5
const int taster5 = 6;  //Taster 5 = Port 6
const int taster6 = 7;  //Taster 6 = Port 7
const int taster7 = 8;  //Taster 7 = Port 8
const int taster8 = 9;  //Taster 8 = Port 9
const int taster9 = 10;  //Taster 9 = Port 10
const int lautsprecher = 11;  //Lautsprecher = Port 11
const int taster = 12; //Neustartknopf = Port 12

int pinWert = 1;
int pinWert1 = 1;
int pinWert2 = 1;
int pinWert3 = 1;
int pinWert4 = 1;
int pinWert5 = 1;
int pinWert6 = 1;
int pinWert7 = 1;
int pinWert8 = 1;
int pinWert9 = 1;

int zaehler1;
int zaehler2;
int zaehler3;
int zaehler4;
int zaehler5;
int zaehler6;
int zaehler7;
int zaehler8;
int zaehler9;

#include  <LiquidCrystal_I2C.h>  //Bibliothek wird eingebunden
LiquidCrystal_I2C lcd(0x27, 20, 4);



void setup() {
   pinMode(taster, INPUT_PULLUP); //Neustartknopf als Objekt identifizieren, das ausgelesen wird
   pinMode(taster1, INPUT_PULLUP); //Taster 1 als Objekt identifizieren, das ausgelesen wird
   pinMode(taster2, INPUT_PULLUP); //Taster 2 als Objekt identifizieren, das ausgelesen wird
   pinMode(taster3, INPUT_PULLUP); //Taster 3 als Objekt identifizieren, das ausgelesen wird
   pinMode(taster4, INPUT_PULLUP); //Taster 4 als Objekt identifizieren, das ausgelesen wird
   pinMode(taster5, INPUT_PULLUP); //Taster 5 als Objekt identifizieren, das ausgelesen wird
   pinMode(taster6, INPUT_PULLUP); //Taster 6 als Objekt identifizieren, das ausgelesen wird
   pinMode(taster7, INPUT_PULLUP); //Taster 7 als Objekt identifizieren, das ausgelesen wird
   pinMode(taster8, INPUT_PULLUP); //Taster 8 als Objekt identifizieren, das ausgelesen wird
   pinMode(taster9, INPUT_PULLUP); //Taster 9 als Objekt identifizieren, das ausgelesen wird

//Serial.begin(9600);  //Für Test von Problem
   
display_grundeinstellung();  //"+"-Feld (TicTacToe Feld) wird geladen
}



void loop() {
neustart();  //Neustartknopf
auswahl1();  //Knopf 1
auswahl2();  //Knopf 2
auswahl3();  //Knopf 3
auswahl4();  //Knopf 4
auswahl5();  //Knopf 5
auswahl6();  //Knopf 6
auswahl7();  //Knopf 7
auswahl8();  //Knopf 8
auswahl9();  //Knopf 9
gewonnen();  //Gewinnmechanismus 
  
  
//Serial.println(zaehler1);  //Für Test von Problem
  
}



void display_grundeinstellung () {
lcd.init();  //Start d. Kommunikation mit dem Display
lcd.backlight();  //Hintergrundbeleuchtung wird aktiviert
lcd.clear();  //Löscht d. Bildschirminhalt


zaehler1 = 0;
zaehler2 = 0;
zaehler3 = 0;
zaehler4 = 0;
zaehler5 = 0;
zaehler6 = 0;
zaehler7 = 0;
zaehler8 = 0;
zaehler9 = 0;


lcd.setCursor(0,0); 
lcd.print("+");  //Feld 1

lcd.setCursor(1,0);
lcd.print("+");  //Feld 2

lcd.setCursor(2,0);
lcd.print("+");  //Feld 3

lcd.setCursor(0,1);
lcd.print("+");  //Feld 4

lcd.setCursor(1,1);
lcd.print("+");  //Feld 5

lcd.setCursor(2,1);
lcd.print("+");  //Feld 6

lcd.setCursor(0,2);
lcd.print("+");  //Feld 7

lcd.setCursor(1,2);
lcd.print("+");  //Feld 8

lcd.setCursor(2,2);
lcd.print("+");  //Feld 9
}

void neustart () {
 pinWert = digitalRead(taster);
 
if (pinWert == 0){
display_grundeinstellung();  //"+"-Feld (TicTacToe Feld) wird geladen
}


}


void auswahl1 () {
pinWert1 = digitalRead(taster1);

if (pinWert1 == 0){
  zaehler1 = zaehler1 + 1; //Knopf 1 wird gedrückt -> zaehler 1 geht 1 rauf
  delay(300);
}

if (zaehler1 == 1) {  //Wenn Knopf 1 1x gedrückt wurde
  lcd.setCursor(0,0); 
  lcd.print("x");  //Feld 1 = x
}

if (zaehler1 == 2) {  //Wenn Knopf 1 2x gedrückt wurde
  lcd.setCursor(0,0); 
  lcd.print("o");  //Feld 1 = o
}
}


void auswahl2 () {
pinWert2 = digitalRead(taster2);

if (pinWert2 == 0){
  zaehler2 = zaehler2 + 1; //Knopf 2 wird gedrückt -> zaehler 2 geht 1 rauf
  delay(300);
}

if (zaehler2 == 1) {  //Wenn Knopf 2 1x gedrückt wurde
  lcd.setCursor(1,0); 
  lcd.print("x");  //Feld 1 = x
}

if (zaehler2 == 2) {  //Wenn Knopf 2 2x gedrückt wurde
  lcd.setCursor(1,0); 
  lcd.print("o");  //Feld 1 = o
}
}


void auswahl3 () {
pinWert3 = digitalRead(taster3);

if (pinWert3 == 0){
  zaehler3 = zaehler3 + 1; //Knopf 3 wird gedrückt -> zaehler 3 geht 1 rauf
  delay(300);
}

if (zaehler3 == 1) {  //Wenn Knopf 3 1x gedrückt wurde
  lcd.setCursor(2,0); 
  lcd.print("x");  //Feld 1 = x
}

if (zaehler3 == 2) {  //Wenn Knopf 3 2x gedrückt wurde
  lcd.setCursor(2,0); 
  lcd.print("o");  //Feld 1 = o
}
}


void auswahl4 () {
pinWert4 = digitalRead(taster4);

if (pinWert4 == 0){
  zaehler4 = zaehler4 + 1; //Knopf 4 wird gedrückt -> zaehler 4 geht 1 rauf
  delay(300);
}

if (zaehler4 == 1) {  //Wenn Knopf 4 1x gedrückt wurde
  lcd.setCursor(0,1); 
  lcd.print("x");  //Feld 1 = x
}

if (zaehler4 == 2) {  //Wenn Knopf 4 2x gedrückt wurde
  lcd.setCursor(0,1); 
  lcd.print("o");  //Feld 1 = o
}
}


void auswahl5 () {
pinWert5 = digitalRead(taster5);

if (pinWert5 == 0){
  zaehler5 = zaehler5 + 1; //Knopf 5 wird gedrückt -> zaehler 5 geht 1 rauf
  delay(300);
}

if (zaehler5 == 1) {  //Wenn Knopf 5 1x gedrückt wurde
  lcd.setCursor(1,1); 
  lcd.print("x");  //Feld 1 = x
}

if (zaehler5 == 2) {  //Wenn Knopf 5 2x gedrückt wurde
  lcd.setCursor(1,1); 
  lcd.print("o");  //Feld 1 = o
}
}


void auswahl6 () {
pinWert6 = digitalRead(taster6);

if (pinWert6 == 0){
  zaehler6 = zaehler6 + 1; //Knopf 6 wird gedrückt -> zaehler 6 geht 1 rauf
  delay(300);
}

if (zaehler6 == 1) {  //Wenn Knopf 6 1x gedrückt wurde
  lcd.setCursor(2,1); 
  lcd.print("x");  //Feld 1 = x
}

if (zaehler6 == 2) {  //Wenn Knopf 6 2x gedrückt wurde
  lcd.setCursor(2,1); 
  lcd.print("o");  //Feld 1 = o
}
}


void auswahl7 () {
pinWert7 = digitalRead(taster7);

if (pinWert7 == 0){
  zaehler7 = zaehler7 + 1; //Knopf 7 wird gedrückt -> zaehler 7 geht 1 rauf
  delay(300);
}

if (zaehler7 == 1) {  //Wenn Knopf 7 1x gedrückt wurde
  lcd.setCursor(0,2); 
  lcd.print("x");  //Feld 1 = x
}

if (zaehler7 == 2) {  //Wenn Knopf 7 2x gedrückt wurde
  lcd.setCursor(0,2); 
  lcd.print("o");  //Feld 1 = o
}
}


void auswahl8 () {
pinWert8 = digitalRead(taster8);

if (pinWert8 == 0){
  zaehler8 = zaehler8 + 1; //Knopf 8 wird gedrückt -> zaehler 8 geht 1 rauf
  delay(300);
}

if (zaehler8 == 1) {  //Wenn Knopf 8 1x gedrückt wurde
  lcd.setCursor(1,2); 
  lcd.print("x");  //Feld 1 = x
}

if (zaehler8 == 2) {  //Wenn Knopf 8 2x gedrückt wurde
  lcd.setCursor(1,2); 
  lcd.print("o");  //Feld 1 = o
}
}


void auswahl9 () {
pinWert9 = digitalRead(taster9);

if (pinWert9 == 0){
  zaehler9 = zaehler9 + 1; //Knopf 9 wird gedrückt -> zaehler 9 geht 1 rauf
  delay(300);
}

if (zaehler9 == 1) {  //Wenn Knopf 9 1x gedrückt wurde
  lcd.setCursor(2,2); 
  lcd.print("x");  //Feld 1 = x
}

if (zaehler9 == 2) {  //Wenn Knopf 9 2x gedrückt wurde
  lcd.setCursor(2,2); 
  lcd.print("o");  //Feld 1 = o
}
}


void gewonnen () {
if(zaehler1 == 1 && zaehler2 == 1 && zaehler3 == 1){   //Waagerechte 1 = x
delay(2000);
lcd.clear();
lcd.print("X WON!!");  
}

if(zaehler4 == 1 && zaehler5 == 1 && zaehler6 == 1){   //Waagerechte 2 = x
delay(2000);  
lcd.clear();
lcd.print("X WON!!");  
}

if(zaehler7 == 1 && zaehler8 == 1 && zaehler9 == 1){   //Waagerechte 3 = x
delay(2000);
lcd.clear();
lcd.print("X WON!!");  
}

if(zaehler1 == 1 && zaehler4 == 1 && zaehler7 == 1){   //Senkrechte 1 = x
delay(2000);
lcd.clear();
lcd.print("X WON!!");  
}

if(zaehler2 == 1 && zaehler5 == 1 && zaehler8 == 1){   //Senkrechte 2 = x
delay(2000);
lcd.clear();
lcd.print("X WON!!");  
}

if(zaehler3 == 1 && zaehler6 == 1 && zaehler9 == 1){   //Senkrechte 3 = x
delay(2000);
lcd.clear();
lcd.print("X WON!!");  
}

if(zaehler1 == 1 && zaehler5 == 1 && zaehler9 == 1){   //Diagonale 1 = x
delay(2000);
lcd.clear();
lcd.print("X WON!!");  
}

if(zaehler3 == 1 && zaehler5 == 1 && zaehler7 == 1){   //Diagonale 2 = x
delay(2000);
lcd.clear();
lcd.print("X WON!!");  
}


if(zaehler1 == 2 && zaehler2 == 2 && zaehler3 == 2){   //Waagerechte 1 = o
delay(2000);
lcd.clear();
lcd.print("O WON!!");  
}

if(zaehler4 == 2 && zaehler5 == 2 && zaehler6 == 2){   //Waagerechte 2 = o
delay(2000);
lcd.clear();
lcd.print("O WON!!");  
}

if(zaehler7 == 2 && zaehler8 == 2 && zaehler9 == 2){   //Waagerechte 3 = o
delay(2000);
lcd.clear();
lcd.print("O WON!!");  
}

if(zaehler1 == 2 && zaehler4 == 2 && zaehler7 == 2){   //Senkrechte 1 = o
delay(2000);
lcd.clear();
lcd.print("O WON!!");  
}

if(zaehler2 == 2 && zaehler5 == 2 && zaehler8 == 2){   //Senkrechte 2 = o
delay(2000);
lcd.clear();
lcd.print("O WON!!");  
}

if(zaehler3 == 2 && zaehler6 == 2 && zaehler9 == 2){   //Senkrechte 3 = o
delay(2000);
lcd.clear();
lcd.print("O WON!!");  
}

if(zaehler1 == 2 && zaehler5 == 2 && zaehler9 == 2){   //Diagonale 1 = o
delay(2000);
lcd.clear();
lcd.print("O WON!!");  
}

if(zaehler3 == 2 && zaehler5 == 2 && zaehler7 == 2){   //Diagonale 2 = o
delay(2000);
lcd.clear();
lcd.print("O WON!!");  
}
}

Da ja bei TicTocToe abwechselnd gesetzt wird, wäre es doch sinnvoll, das Setzen mit einem Tastendruck zu machen, jedoch nach jedem Tastendruck zwischen "X" und "O" umzuschalten.
Dann stellt sich Dein Problem gar nicht.

Beim durchlesen deines Programms ist mir was aufgefallen.

"Wir" nummerieren keine Pins durch, auch keine Variablen oder Funktionen,
"Wir" nutzen stattdessen Arrays und Schleifen
Auch kopieren "wir" keine Codepassagen, sondern nutzen Funktionen oder Methoden.

Das möchte ich auch dir raten.
Die Gründe dafür sind vielfältig.

Hallo 1kiara21

Nimm ein Stück Papier und werte die Gewinnfunktionen über eine Wertetabelle aus. Die ermittelten Gewinnfunktionen sind dann im Programm umsetzen.

Schöner Spagetticode.

Naja....Anfäger können das halt nicht besser. Die sollten dann die Tipps hier lesen und umsetzen, dann wirds schon.

Hm ... zu meiner Zeit gab's kleine weise Büchlein aka "Turbo C", "Ansi C", "K&R 1" ...

Wer liest denn heute noch, wenn einem im Web alles vorgemacht wird. :wink:

Beispiel YT.

"ChatGPT, schreib' mit ein tolles Programm mit Spagetticode, aber bitte vegan"

1 Like

Fangen wir mal mit Optimierungen an:
In kleinen Schritten: Doppelter Code ist schlechter Code:
Beispiel:

void gewonnen () {
  if (zaehler1 == 1 && zaehler2 == 1 && zaehler3 == 1) { //Waagerechte 1 = x
    delay(2000);
    lcd.clear();
    lcd.print("X WON!!");
  }

  if (zaehler4 == 1 && zaehler5 == 1 && zaehler6 == 1) { //Waagerechte 2 = x
    delay(2000);
    lcd.clear();
    lcd.print("X WON!!");
  }

  if (zaehler7 == 1 && zaehler8 == 1 && zaehler9 == 1) { //Waagerechte 3 = x
    delay(2000);
    lcd.clear();
    lcd.print("X WON!!");
  }

  if (zaehler1 == 1 && zaehler4 == 1 && zaehler7 == 1) { //Senkrechte 1 = x
    delay(2000);
    lcd.clear();
    lcd.print("X WON!!");
  }

  if (zaehler2 == 1 && zaehler5 == 1 && zaehler8 == 1) { //Senkrechte 2 = x
    delay(2000);
    lcd.clear();
    lcd.print("X WON!!");
  }

  if (zaehler3 == 1 && zaehler6 == 1 && zaehler9 == 1) { //Senkrechte 3 = x
    delay(2000);
    lcd.clear();
    lcd.print("X WON!!");
  }

  if (zaehler1 == 1 && zaehler5 == 1 && zaehler9 == 1) { //Diagonale 1 = x
    delay(2000);
    lcd.clear();
    lcd.print("X WON!!");
  }

  if (zaehler3 == 1 && zaehler5 == 1 && zaehler7 == 1) { //Diagonale 2 = x
    delay(2000);
    lcd.clear();
    lcd.print("X WON!!");
  }


  if (zaehler1 == 2 && zaehler2 == 2 && zaehler3 == 2) { //Waagerechte 1 = o
    delay(2000);
    lcd.clear();
    lcd.print("O WON!!");
  }

  if (zaehler4 == 2 && zaehler5 == 2 && zaehler6 == 2) { //Waagerechte 2 = o
    delay(2000);
    lcd.clear();
    lcd.print("O WON!!");
  }

  if (zaehler7 == 2 && zaehler8 == 2 && zaehler9 == 2) { //Waagerechte 3 = o
    delay(2000);
    lcd.clear();
    lcd.print("O WON!!");
  }

  if (zaehler1 == 2 && zaehler4 == 2 && zaehler7 == 2) { //Senkrechte 1 = o
    delay(2000);
    lcd.clear();
    lcd.print("O WON!!");
  }

  if (zaehler2 == 2 && zaehler5 == 2 && zaehler8 == 2) { //Senkrechte 2 = o
    delay(2000);
    lcd.clear();
    lcd.print("O WON!!");
  }

  if (zaehler3 == 2 && zaehler6 == 2 && zaehler9 == 2) { //Senkrechte 3 = o
    delay(2000);
    lcd.clear();
    lcd.print("O WON!!");
  }

  if (zaehler1 == 2 && zaehler5 == 2 && zaehler9 == 2) { //Diagonale 1 = o
    delay(2000);
    lcd.clear();
    lcd.print("O WON!!");
  }

  if (zaehler3 == 2 && zaehler5 == 2 && zaehler7 == 2) { //Diagonale 2 = o
    delay(2000);
    lcd.clear();
    lcd.print("O WON!!");
  }
}

wird zu

void gewonnen2() {
  delay(2000);
  lcd.clear();
  lcd.print("X WON!!");
}

void gewonnen () {
  if (zaehler1 == 1 && zaehler2 == 1 && zaehler3 == 1) { //Waagerechte 1 = x
    gewonnen2();
  }

  if (zaehler4 == 1 && zaehler5 == 1 && zaehler6 == 1) { //Waagerechte 2 = x
    gewonnen2();
  }

  if (zaehler7 == 1 && zaehler8 == 1 && zaehler9 == 1) { //Waagerechte 3 = x
    gewonnen2();
  }

  if (zaehler1 == 1 && zaehler4 == 1 && zaehler7 == 1) { //Senkrechte 1 = x
    gewonnen2();
  }

  if (zaehler2 == 1 && zaehler5 == 1 && zaehler8 == 1) { //Senkrechte 2 = x
    gewonnen2();
  }

  if (zaehler3 == 1 && zaehler6 == 1 && zaehler9 == 1) { //Senkrechte 3 = x
    gewonnen2();
  }

  if (zaehler1 == 1 && zaehler5 == 1 && zaehler9 == 1) { //Diagonale 1 = x
    gewonnen2();
  }

  if (zaehler3 == 1 && zaehler5 == 1 && zaehler7 == 1) { //Diagonale 2 = x
    gewonnen2();
  }

  if (zaehler1 == 2 && zaehler2 == 2 && zaehler3 == 2) { //Waagerechte 1 = o
    gewonnen2();
  }

  if (zaehler4 == 2 && zaehler5 == 2 && zaehler6 == 2) { //Waagerechte 2 = o
    gewonnen2();
  }

  if (zaehler7 == 2 && zaehler8 == 2 && zaehler9 == 2) { //Waagerechte 3 = o
    gewonnen2();
  }

  if (zaehler1 == 2 && zaehler4 == 2 && zaehler7 == 2) { //Senkrechte 1 = o
    gewonnen2();
  }

  if (zaehler2 == 2 && zaehler5 == 2 && zaehler8 == 2) { //Senkrechte 2 = o
    gewonnen2();
  }

  if (zaehler3 == 2 && zaehler6 == 2 && zaehler9 == 2) { //Senkrechte 3 = o
    gewonnen2();
  }

  if (zaehler1 == 2 && zaehler5 == 2 && zaehler9 == 2) { //Diagonale 1 = o
    gewonnen2();
  }
     
  if (zaehler3 == 2 && zaehler5 == 2 && zaehler7 == 2) { //Diagonale 2 = o
    gewonnen2();
  }
}

wird zu

void gewonnen () {
  if ((zaehler1 == 1 && zaehler2 == 1 && zaehler3 == 1) //Waagerechte 1 = x
      || (zaehler4 == 1 && zaehler5 == 1 && zaehler6 == 1) //Waagerechte 2 = x
      || (zaehler7 == 1 && zaehler8 == 1 && zaehler9 == 1) //Waagerechte 3 = x
      || (zaehler1 == 1 && zaehler4 == 1 && zaehler7 == 1) //Senkrechte 1 = x
      || (zaehler2 == 1 && zaehler5 == 1 && zaehler8 == 1) //Senkrechte 2 = x
      || (zaehler3 == 1 && zaehler6 == 1 && zaehler9 == 1) //Senkrechte 3 = x
      || (zaehler1 == 1 && zaehler5 == 1 && zaehler9 == 1) //Diagonale 1 = x
      || (zaehler3 == 1 && zaehler5 == 1 && zaehler7 == 1) //Diagonale 2 = x
      || (zaehler1 == 2 && zaehler2 == 2 && zaehler3 == 2) //Waagerechte 1 = o
      || (zaehler4 == 2 && zaehler5 == 2 && zaehler6 == 2) //Waagerechte 2 = o
      || (zaehler7 == 2 && zaehler8 == 2 && zaehler9 == 2) //Waagerechte 3 = o
      || (zaehler1 == 2 && zaehler4 == 2 && zaehler7 == 2) //Senkrechte 1 = o
      || (zaehler2 == 2 && zaehler5 == 2 && zaehler8 == 2) //Senkrechte 2 = o
      || (zaehler3 == 2 && zaehler6 == 2 && zaehler9 == 2) //Senkrechte 3 = o
      || (zaehler1 == 2 && zaehler5 == 2 && zaehler9 == 2) //Diagonale 1 = o
      || (zaehler3 == 2 && zaehler5 == 2 && zaehler7 == 2)) { //Diagonale 2 = o
    delay(2000);
    lcd.print("X WON!!");
    lcd.clear();
  }
}

Das ganze jetzt noch mit Array und for Scheifen --> 10 Zeilen code

Dem ist nichts hinzuzufügen.

Zu deinem Tastendruckproblem:
Du hast noch ein ganz anderes Problem: Du kannst besetzte Felder überschreiben.
Daher folgender Ansatz:

Zudem prüfst du bei dem Tastendruck ob das Feld bereits gesetzt ist. Wenn ja, passiert nix.
Wenn nein, setzt du das Feld und schaltest von x auf o um.

Tipp: wirf das ganze Programm weg und fange von vorne an.
Du hast alles mit 1000enden von ifs gemacht.
Schaue dir mal an, was ein Array ist, dann vielleicht noch was ein 2 Dimensionales Array ist und wie for Schleifen gehen.
Dann bekommt man das Programm in < 100 Zeile Code (ohne eine Zeile doppelten, kopierten Code)

Hier mal eine KI Antwort:

Tic Tac Toe Spiel in C mit 2D-Arrays und Schleifen

#include <stdio.h>

// Spielfeld definieren
char spielfeld[3][3] = {{' ', ' ', ' '},
                        {' ', ' ', ' '},
                        {' ', ' ', ' '}};

// Funktion zum Drucken des Spielfelds
void druckeSpielfeld() {
  for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
      printf("| %c ", spielfeld[i][j]);
    }
    printf("|\n");
  }
}

// Funktion zum Setzen eines Symbols auf eine Position
void setzeSymbol(char symbol, int zeile, int spalte) {
  if (zeile >= 0 && zeile < 3 && spalte >= 0 && spalte < 3 && spielfeld[zeile][spalte] == ' ') {
    spielfeld[zeile][spalte] = symbol;
  } else {
    printf("Ungültiger Zug!\n");
  }
}

// Funktion zum Prüfen des Gewinners
char pruefeGewinner() {
  // Zeilen prüfen
  for (int i = 0; i < 3; i++) {
    if (spielfeld[i][0] == spielfeld[i][1] && spielfeld[i][1] == spielfeld[i][2] && spielfeld[i][0] != ' ') {
      return spielfeld[i][0];
    }
  }

  // Spalten prüfen
  for (int i = 0; i < 3; i++) {
    if (spielfeld[0][i] == spielfeld[1][i] && spielfeld[1][i] == spielfeld[2][i] && spielfeld[0][i] != ' ') {
      return spielfeld[0][i];
    }
  }

  // Diagonalen prüfen
  if (spielfeld[0][0] == spielfeld[1][1] && spielfeld[1][1] == spielfeld[2][2] && spielfeld[0][0] != ' ') {
    return spielfeld[0][0];
  }

  if (spielfeld[0][2] == spielfeld[1][1] && spielfeld[1][1] == spielfeld[2][0] && spielfeld[0][2] != ' ') {
    return spielfeld[0][2];
  }

  // Unentschieden prüfen
  for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
      if (spielfeld[i][j] == ' ') {
        return ' '; // Spiel geht weiter
      }
    }
  }

  // Unentschieden
  return 'U';
}

int main() {
  char spieler = 'X'; // 'X' beginnt das Spiel

  while (1) {
    druckeSpielfeld();

    // Spielerzug einholen
    int zeile, spalte;
    printf("Spieler %c, gib deine Zeile ein (0-2): ", spieler);
    scanf("%d", &zeile);
    printf("Spieler %c, gib deine Spalte ein (0-2): ", spieler);
    scanf("%d", &spalte);

    setzeSymbol(spieler, zeile, spalte);

    // Prüfen auf Gewinner oder Unentschieden
    char gewinner = pruefeGewinner();

    if (gewinner != ' ') {
      druckeSpielfeld();
      if (gewinner == 'U') {
        printf("Unentschieden!\n");
      } else {
        printf("Spieler %c hat gewonnen!\n", gewinner);
      }
      break;
    }

    // Nächster Spieler
    if (spieler == 'X') {
      spieler = 'O';
    } else {
      spieler = 'X';
    }
  }

  return 0;
}

Die kannst du mit deinem LCD und Tasten nicht direkt verwenden. Aber: du kannst dir mal ansehen wie das mit den 2D-Arrays und Schleifen geht. An besten brauchst du neben dem

char spielfeld[3][3]

ein 2 Array für die Pindefinitionen.
Im Setup kannst du dann die
pinMode(taster1, INPUT_PULLUP);
auch in einer doppelten for Schleife setzen und im loop in einer doppelten for Schleife auswerten.

Hier mal keine KI Antwort:

#include <Streaming.h>
#include <Button_SL.hpp>

Print &cout {Serial};
using namespace Btn;

constexpr uint8_t BOARD_COLS {3};
constexpr uint8_t BOARD_ROWS {BOARD_COLS};
constexpr uint8_t BOARD_SIZE {(BOARD_COLS + 2) * (BOARD_ROWS + 2)};
constexpr uint8_t BOARD_OFFSET {BOARD_COLS + 2};

// Index - Offsets to test whether three identical characters are in a row
//                      CHECK       ROW,     COL   DIAG. RIGHT       DIAG. LEFT
constexpr uint8_t DIRECTIONS[] {BOARD_OFFSET, 1, BOARD_OFFSET + 1, BOARD_OFFSET - 1};

constexpr char BD {'@'};   // Value: border of playing field
constexpr char FD {' '};   // Value: playing field
constexpr char BOARD_INIT[BOARD_SIZE] {BD, BD, BD, BD, BD, BD, FD, FD, FD, BD, BD, FD, FD,
                                       FD, BD, BD, FD, FD, FD, BD, BD, BD, BD, BD, BD};

ButtonSL bArray[] {{4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}};
char board[BOARD_SIZE];

//////////////////////////////////////////////////////////////////////////////
/// @brief Sets the playing field to its initial values
///
/// @param (&brd)[N]   The playing field as an array
//////////////////////////////////////////////////////////////////////////////
template <size_t N> void resetBoard(char (&brd)[N]) { memcpy(brd, BOARD_INIT, N); }

//////////////////////////////////////////////////////////////////////////////
/// @brief Display of the playing field
///
/// @param  BDtparam (&brd)[N]   The playing field as an array
//////////////////////////////////////////////////////////////////////////////
template <size_t N> void showBoard(char (&brd)[N]) {
  for (byte i = BOARD_OFFSET; i < (N - BOARD_OFFSET); ++i) {
    if (brd[i] != BD) {
      cout << _FMT("[%,%,%]\n", brd[i], brd[i + 1], brd[i + 2]);
      i += 3;
    }
  }
}

//////////////////////////////////////////////////////////////////////////////
/// @brief Conversion from the simple offset (buttons) in the array
///        to the array from the playing field
///
/// @param pos
/// @return uint8_t
//////////////////////////////////////////////////////////////////////////////
uint8_t calcBoardOffset(uint8_t pos) {
  uint8_t col = pos % BOARD_COLS;
  uint8_t row = pos / BOARD_ROWS;
  return (BOARD_OFFSET + 1) + (row * BOARD_OFFSET) + col;
}

//////////////////////////////////////////////////////////////////////////////
/// @brief Implementation of a move. The player value is placed on the
///        corresponding field of the playing field (array).
///
/// @param brd      Array representing the playing field
/// @param pos      Position on the playing field (index 0 - 9)
/// @param value    Player value (-1 = player 1 or 1 = player 2)
/// @return true    Value was set
/// @return false   Value was not set
//////////////////////////////////////////////////////////////////////////////
bool move(char brd[], uint8_t pos, char value) {
  bool isValueAssigned {false};
  if (pos > (BOARD_COLS * BOARD_ROWS - 1)) {
    cout << "ERROR!\n";   // Index out of bounds
    return isValueAssigned;
  }

  uint8_t idx = calcBoardOffset(pos);
  // Only set player value if this field has not yet received one
  if (brd[idx] == FD) {
    brd[idx] = value;
    isValueAssigned = true;
  }
  return isValueAssigned;
}

//////////////////////////////////////////////////////////////////////////////
/// @brief Check whether there are three identical, consecutive values
///        horizontally, vertically or diagonally on the playing field.
///        https://www.youtube.com/watch?v=e5lKoL9G0N4
///
/// @param brd    Array representing the playing field
/// @param idx    Index of the last player value entered on the playing field
/// @return true  identical Values
/// @return false no identical values
//////////////////////////////////////////////////////////////////////////////
bool isRowComplete(char brd[], uint8_t idx) {
  char compare = brd[idx];
  uint8_t sum {1};

  for (auto &dirIdx : DIRECTIONS) {   // Get the index of the corresponding direction for comparison
    uint8_t sIdx = idx + dirIdx;
    sum = 1;
    while (brd[sIdx] == compare) {   // Compare to the right
      sIdx += dirIdx;
      sum += 1;
    }
    sIdx = idx - dirIdx;
    while (brd[sIdx] == compare) {   // Compare to the left
      sIdx -= dirIdx;
      sum += 1;
    }
    if (sum == 3) { return true; }
  }
  return false;
}

//////////////////////////////////////////////////////////////////////////////
/// @brief Check whether a button has been pressed
///
/// @param (&btns)[N]  Array with push-button objects
/// @return int8_t      Index of the button pressed or -1 if none was pressed.
//////////////////////////////////////////////////////////////////////////////
template <size_t N> int8_t checkButtons(ButtonSL (&btns)[N]) {
  for (uint8_t i = 0; i < N; ++i) {
    if (btns[i].tick() != ButtonState::notPressed) { return i; }
  }
  return -1;
}

void setup() {
  Serial.begin(115200);
  for (auto &b : bArray) { b.begin(); }
  resetBoard(board);
  cout << "Player: 1 (X) has the turn\n";
  showBoard(board);
}

void loop() {
  static bool restart {false};
  static char player[2] {'X', 'O'};
  static uint8_t pCounter[2] {0};
  static uint8_t pIdx {0};

  int8_t bVal = checkButtons(bArray);
  if (bVal > (-1)) {
    if (move(board, bVal, player[pIdx]) == true) {
      pCounter[pIdx]++;
      if (isRowComplete(board, calcBoardOffset(bVal))) {   // Three in a row?
        cout << "\nPlayer: " << pIdx + 1 << " has won!\n";
        showBoard(board);
        restart = true;
      } else if (pCounter[0] + pCounter[1] == (BOARD_ROWS * BOARD_COLS)) {   // no and no remaining fields
        cout << "\nNo one has won\n";
        showBoard(board);
        restart = true;
      }

      if (restart == true) {
        pCounter[0] = 0;
        pCounter[1] = 0;
        resetBoard(board);
        restart = false;
        delay(5000);
      }

      pIdx = !pIdx;   // Swap Player
      cout << "\nPlayer: " << pIdx + 1 << " (" << player[pIdx] << ") has the turn\n";
      showBoard(board);
    }
  }
}

Edit: Code etwas abgeändert. Nun werden Zeichen statt Zahlen werden verwendet.

Zum Ausprobieren:

Kann man noch hübscher machen, ist aber mal ein Anfang :wink:.

1 Like

Warum macht ihr das?
Der nächste Shitcode, der von einem solchen Tool kommt und hier verbessert werden soll, löst dann wieder endlose Diskussionen aus.
Aber der hat ja auch....

Und vorher wird noch über diesen YT Kram gelästert, weil ja keiner mehr Bücher liest.

Ym2c

KI ist besser als YT, die weiß was der User denken soll duckundweg

1 Like

Ich habe doch gleich dazu geschrieben, das man sich nur ein paar Ideen holen kann. Der TO ist ja ein Copy Paste Weltmeister.

1 Like

Du solltest schon alle Wörter lesen…. und beim Zitieren nicht das entscheidende weglassen.

3 Likes

istockphoto-458713051-612x612

2 Likes