Spelletje Tic-tac-toe, hulp nodig

Arduino specifieke Software
Berichten: 12
Geregistreerd: 15 Dec 2016, 19:45

Spelletje Tic-tac-toe, hulp nodig

Berichtdoor hans50-dec » 09 Jan 2017, 04:21

Beste mensen,
Momenteel ben ik bezig om een spel Tic-tac-toe te maken, de hardware is klaar en functioneert maar het programma laat me in de steek en ik weet niet waar het fout gaat. Alle hulp is van harte welkom.
Wat is de bedoeling? Het 'bord' bestaat uit 9 plexiglas tegels met daaronder een schakelaar en een twee-kleurige LED.
Wanneer er geen speler op het bord staat loopt een routine (flits) die LEDs om en om laat branden in een willeheurige volgorde.
Staat er een speler op het bord dan moet die routine onderbroken worden en de led van de betreffende tegel gaan branden. Staat een tweede speler op het bord dan moet eveneens die LED gaan banden maar dan in de andere kleur. In het programma heb ik een regel opgenomen die uitmaakt of de tegel een even- of oneven nummer heeft en daarmee wordt de kleur van de LED bepaalt.

Hieronde de code en zoals gezegd, alle hulp is welkom. Dank alvast.

Code: Alles selecteren
#include <Arduino.h>
#include <Shifter.h>
const unsigned long debounceTime = 20;   // milliseconds
const int numSwitches = 9;  // how many switches, for arrays below

// where switches are connected
const byte switchPin [numSwitches] = { 2, 5, 6, 7, 8, 9, 10, 11, 12 };

// when last changed state
unsigned long lastPressedTime [numSwitches];

// current state
int switchState [numSwitches];

// have we changed state in any switch?
bool stateChange = false;
unsigned long now = millis ();
long randNumber;

#define SER_Pin A3    //SER_IN data
#define RCLK_Pin A5   //L_CLOCK latch
#define SRCLK_Pin A2  //CLOCK
#define NUM_REGISTERS 3 //how many registers are in the chain
//initaize shifter using the Shifter library
Shifter shifter(SER_Pin, RCLK_Pin, SRCLK_Pin, NUM_REGISTERS);

void setupSwitches ()
{
  for (int i = 0; i < numSwitches; i++)
  {
    pinMode (switchPin [i], INPUT_PULLUP);
    switchState [i] = HIGH;    //NOT PRESSED
    lastPressedTime [i] = 0;
  }  // end of for each switch
}  // end of setupSwitches

void flits() // routine voor het snel in- en uitschakelen van de diverse leds
{
  randNumber = random(1, 18);
  shifter.setPin(randNumber, LOW);   //set pin i in the chain LOW (= relay ON)
  shifter.write();                   //send changes to the chain and display them
  delay(300);
  shifter.setPin(randNumber, HIGH);  //set pin i in the chain HIGH (= relay OFF)
  shifter.write();                   //send changes to the chain and display them
}  // end of flits

void setup()
{
  Serial.begin(9600);
  setupSwitches ();
  shifter.clear();    //set all pins on the shift register chain to LOW
}

void loop()
{
  for (int i = 0; i < numSwitches; i++)
  {
    int currentState = digitalRead (switchPin [i]);
    if ((currentState != switchState [i]) &&
        (now - lastPressedTime [i] >= debounceTime))
    {
      switchState [i] = currentState;
      lastPressedTime [i] = now;
      stateChange = true;   // a switch has changed state
    }  // end of changed state
    // end of for each switch
      Serial.println(switchState[i]);
    if (switchState[i] == HIGH)
    {
      flits();
    }
    else if ((switchState[i]==LOW) && (switchState[i]% 2 == 0))
    {
      Serial.print("switchState =  ");
      Serial.println(switchState[i]);
      Serial.println("player 1");
      //        player1();
    }
    else
    {
      Serial.println("player 2");
      //        player2();
    }
//    Serial.print ("Switch ");
//    Serial.print (i + 1);
//    Serial.print (" = ");
//    Serial.print ((switchState [i] == LOW) ? "ON  " : "off ");
    //  debugSwitchStatus ();
  }
}

Advertisement

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Spelletje Tic-tac-toe, hulp nodig

Berichtdoor Koepel » 09 Jan 2017, 04:40

Alweer een goed project :D
Kun je de hardware er bij geven ? Wat is het schema ? Een tekening met een pen en daar een foto van kan ook.
Kun je vertellen welke library je gebruikt ? Ik ken de Shifter library niet.

Je hebt de State-Change-Detection gecombineerd met een millis() timing voor debouncing. Daarvan raken mijn hersencellen helemaal ontregelt, dus zal ik het verder op mijn gevoel moeten doen. Mijn gevoel zegt dat het niet kan werken op die manier.
Je zet 'now' niet runtime op de waarde van millis(), dus er gaat sowieso al iets niet lekker.

Wat dacht je van de Bounce2 library ?
https://github.com/thomasfredericks/Bounce2
Dan krijg je goede informatie of dat een knop echt goed is ingedrukt.

Je schrijft dit:
Code: Alles selecteren
else if ((switchState[i]==LOW) && (switchState[i]% 2 == 0))
Begrijp je zelf wat de bedoeling is ? Je mag gerust code uitschrijven over meerdere regels, als het maar voor iedereen duidelijk is wat er gebeurt. In die regel doe je de bewerking "%2" op "switchState[i]", dus je doet die bewerking op "HIGH" of op "LOW".

Berichten: 12
Geregistreerd: 15 Dec 2016, 19:45

Re: Spelletje Tic-tac-toe, hulp nodig

Berichtdoor hans50-dec » 09 Jan 2017, 15:00

Dank voor je snelle reactie. Bijgaand wat foto's en schema van het project (110Vac voor de LED's moet worden 12Vdc, deze tekening is nog van een voorstadium). In de grote gaten in de randen komen veren om de plexiglas tegel omhoog te houden. Ik gebruik twe relais extra voor de 18 LED's. Deze worden aangestuurd met het shift register 74HC595 en dat, op zijn beurt, gebruikt de shifter bibliotheek (https://github.com/catchdave/arduino-gb/tree/master/libraries/Shifter.

Met de code
Code: Alles selecteren
else if ((switchState[i]==LOW) && (switchState[i]% 2 == 0))
wil ik uitlezen welke schakelaar is ingedrukt, dus de waarde [i], en bepalen of die waarde even of oneven is (&2 == 0). Ik, in mijn onkunde, dacht dat dit zou werken maar jij brengt me nu aan het twijfelen. Heb je een oplossing wellicht?
Bijlagen
TTT nieuw1.jpg
TTT nieuw1.jpg (62.61 KiB) 7922 keer bekeken
IMG_20170109_073218066.jpg
IMG_20170109_073218066.jpg (78.55 KiB) 7922 keer bekeken
IMG_20170109_073145324.jpg
IMG_20170109_073145324.jpg (116.53 KiB) 7922 keer bekeken

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Spelletje Tic-tac-toe, hulp nodig

Berichtdoor nicoverduin » 09 Jan 2017, 16:47

Als je i%2 doet krijg je de even switches. Het gaat immers om de even switches uit de array. Wil je de oneven vergelijk je i%2 met 1.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 4067
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Spelletje Tic-tac-toe, hulp nodig

Berichtdoor shooter » 09 Jan 2017, 17:39

je moet niet de switchstate[i]%2 maar de i%2 doen. want de state is boolean en i is een getal.
paul deelen
shooter@home.nl

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Spelletje Tic-tac-toe, hulp nodig

Berichtdoor Koepel » 10 Jan 2017, 00:58

Het schema begrijp ik niet. Die 1uF condensator, die zit toch wel op de 5V en GND ? Toch niet op een clock of latch signaal. Ooit heeft iemand het bizarre idee gehad om een condensator op het clock of latch signaal te zetten, maar dat is te absurd voor woorden. Helaas is dat daarna nagedaan. Het heeft zelfs als voorbeeld een tijdje op de website van Arduino.cc gestaan.

Je gebruikt nu cascade ? en dat werkt ?
Kun je die condensator weghalen ? werkt het dan nog steeds ? Heb je een test-sketch die ze allemaal achter elkaar aan zet ?
Wanneer het niet goed werkt, dan kun je ontkoppelcondensators voor de voedingsspanning bij de shift-registers zetten op de 5V en GND.

Arduino heeft een ShiftOut: https://www.arduino.cc/en/Reference/ShiftOut
Volgens mij kan dat ook. Het ligt er aan of je de 595 naast elkaar of in cascade gebruikt.

Misschien heb je er helemaal geen debounce in zitten, en heb ik je millis() verkeerd opgevat.
Kun je voor de code eerst goed beschrijven wat je wilt dat er gebeurt. Bij tic-tac-toe zullen de leds blijven branden tot het spel over is ? Kun je de tijden specificeren ? Hoe lang moet iemand op een tegel staan voordat het geaccepteerd wordt. Iets van 2 seconden ?
Heb je die Bounce2 library bekeken ? Die heeft ook een State-Change-Detection met de functies .rose() en .fell().

Berichten: 12
Geregistreerd: 15 Dec 2016, 19:45

Re: Spelletje Tic-tac-toe, hulp nodig

Berichtdoor hans50-dec » 13 Jan 2017, 03:09

Dank allen voor jullie suggesties. Een beetje late reactie maar het internet hier is als een jojo omdat alle kabels boven de grond aan palen hangen gaat er nog wel eens wat kapot.

Inmiddels heb ik de code wat aangepast maar het blijft nog altijd hangen in een loop en ik krijg er geen goed beeld op wat er loos is.
Voor de duidelijkheid, ik wil het volgende laten gebeuren.

Na de start van de arduino loopt de 'flits'. Deze moet stoppen wanneer de eerste speler op een tegel gaat staan. De LEDS onder die tegel moeten dan oplichten. De eerste speler krijgt een kleur (bv rood) en de volgende speler krijgt dan groen. De derde krijgt weer rood en zo verder.

Willen jullie svp een blik werpen op de code en mij in de goede richting sturen???

Code: Alles selecteren
#include <Arduino.h>
#include <Shifter.h>
// where switches are connected
const int numSw = 9;      // number of switches
const byte swPin [numSw] = { 2, 5, 6, 7, 8, 9, 10, 11, 12 };
int buttonP1 = 0;
int buttonP2 = 0;
const int pinGr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
const int pinRd[] = {9, 10, 11, 12, 13, 14, 15, 16, 17};
int player = 0;              // 0= player 1, 1= player2
int swState [numSw];         // current state of the switch
int lastSwState [numSw];     // previous state of the switch

// for flits
#define SER_Pin A3    //SER_IN data
#define RCLK_Pin A5   //L_CLOCK latch
#define SRCLK_Pin A2  //CLOCK
#define NUM_REGISTERS 3 //how many registers are in the chain
long randNumber;

//initaize shifter using the Shifter library
Shifter shifter(SER_Pin, RCLK_Pin, SRCLK_Pin, NUM_REGISTERS);

void checkSw() {
  // read the switch input pins:
  // compare the switchState to its previous state
  if (swState[numSw] != lastSwState[numSw])
    for  (int i = 0; i < numSw; i++)
    {
      swState[i] = digitalRead(swPin [i]);
      // if the state has changed, increment the counter
      if ((swState[i] == 0) && (i % 2 == 0))     // knop ingedrukt maar welke?
      {
        buttonP1 = i;
        shifter.setPin(buttonP1, LOW);   //set pin  in the chain LOW (= relay ON)
        shifter.write();          //send changes to the chain and display them
        Serial.println("buiten case player 1 ");
        player = 1;
      }
      else if (swState[i] == 0) //&& (i % 2 == 1))
      {
        buttonP2 = i;
        shifter.setPin(buttonP2, LOW); //set pin  in the chain LOW (= relay ON)
        shifter.write();            //send changes to the chain and display them
        Serial.println("buiten case player 2 ");
        Serial.println(buttonP2);
        player = 2;
      }
      else {
        randNumber = random(1, 18);
        shifter.setPin(randNumber, LOW);   //set pin  in the chain LOW (= relay ON)
        shifter.write();                   //send changes to the chain and display them
        delay(300);
        shifter.setPin(randNumber, HIGH);  //set pin  in the chain HIGH (= relay OFF)
        shifter.write();                   //send changes to the chain and display them
        Serial.println("Flits");
      }
      // Delay a little bit to avoid bouncing
      delay(50);
      // save the current state as the last state,
      //for next time through the loop
      lastSwState[i] = swState[i];
    } // end for loop
  //  return;
}

void setup()
{
  Serial.begin(9600);
  for (int i = 0; i < numSw; i++)
  {
    pinMode (swPin [i], INPUT_PULLUP);
    swState [i] = 1;  // not pressed
    shifter.clear();  //set all pins on the shift register chain to LOW
  }
}

void loop()
{
  shifter.clear();
  checkSw();
}



Berichten: 4067
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Spelletje Tic-tac-toe, hulp nodig

Berichtdoor shooter » 13 Jan 2017, 12:23

if (swState[numSw] != lastSwState[numSw]) die snap ik al niet.
moet deze niet in de for loop?
paul deelen
shooter@home.nl

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Spelletje Tic-tac-toe, hulp nodig

Berichtdoor Koepel » 13 Jan 2017, 21:41

@hans50-dec,
Helaas kan ik niet met een paar wijzigingen je sketch werkend krijgen. Het lijkt wel alsof je probeert om alles tegelijk te doen. De enige oplossing lijkt me om het zoveel mogelijk uit elkaar te trekken.

Je kunt dingen uit elkaar trekken, door bijvoorbeeld met een variabele bepaalde informatie naar het volgende deel over te brengen. Dan kun je de sketch opdelen in:
deel 1: input, lees knoppen
deel 2: processing, verwerk de informatie
deel 3: output, schrijf naar de leds

Je zou kunnen beginnen met een functie die kijkt welke knop wordt ingedrukt.

Het laten knipperen van de leds voordat het spel begint is een extra toevoeging. Het is iets dat je later toevoegt. Daarvoor is het nodig dat in de loop() bekent is of het knipperen bezig is of dat het spel bezig is. Daar heb je een globale variabele voor nodig.
Tenzij je ook tijdens het spel de ongebruikte tegels wilt laten knipperen, maar dat is me niet helemaal duidelijk.

Je schrijft de led meteen naar de uitgang. Dat betekend dat je binnen de sketch die gegevens niet hebt, en dat je dus niet weet welke tegels al aangezet zijn. Dat is een enorme beperking. Daarom begon ik mijn sketch om eerst een array te maken met de status van de tegels (char tile[]). Daarna rolde de rest van de sketch zich uit.

Ik vond het een leuke uitdaging en heb het volgende gemaakt. Probeer het eens in de seriële monitor te spelen. Ik ben er voor 80% tevreden over, dus er zitten nog wat zwakke plekken in.
Code: Alles selecteren
// Januari 2017
// A small test with tic-tac-toe.
// Created from scratch.

#define NUM_TILES 9
#define BLANK '.'

// Every tile is '.' or 'X' or 'O'.
// The dot for an empty tile is choosen to make it look better on the serial monitor.
char tile[NUM_TILES];   
int countActivatedTiles;

void setup()
{
  Serial.begin( 9600);
  while(!Serial);   // for Leonardo/Micro: wait for serial monitor.
  Serial.println(F( "\nTic-tac-toe"));
  Serial.println(F( "Enter a number for the next 'X' or 'O'"));

  ResetTiles();
  PrintTiles();
}

void loop()
{
  int button = -1;     // default -1 means no button information received.
  boolean updateTiles = false;  // default false means no update needed.

  // -----------------------------------
  // Part 1, read the inputs
  // -----------------------------------
  // The variable 'button' is used to pass on information to the next part.
 
  if( Serial.available() > 0)
  {
    char charIn = Serial.read();
    if( isdigit( charIn))
    {
      button = charIn - '0';   // convert printable digit to binary number
    }
  }

  // -----------------------------------
  // Part 2, process the information
  // -----------------------------------
  // The variable 'updateTiles' is used to pass on information to the next part.
 
  if( button >= 0)        // something received ?
  {
    if( tile[button] == BLANK)   // accept only if tile is still blank
    {
      if( countActivatedTiles % 2 == 0)  // test for even numbers
      {
        // It is an even number
        tile[button] = 'X';
      }
      else
      {
        // It is an odd number
        tile[button] = 'O';
      }
      countActivatedTiles++;

      updateTiles = true;
    }
  }

  // -----------------------------------
  // Part 3, write to the outputs
  // -----------------------------------
 
  if( updateTiles)
  {
    // Print the tiles.
    PrintTiles();

    // Check if there was a special condition.
   
    // Check if the tiles are all filled.
    if( countActivatedTiles == NUM_TILES)
    {
      ResetTiles();
      PrintTiles();
    }

    // Check if someone has won.
    if( CheckTiles())
    {
      Serial.println(F( "WIN !"));
      Serial.println(F( "-------------"));
      ResetTiles();
      PrintTiles();
    }
  }
}


void PrintTiles()
{
  for( int row=0; row<3; row++)
  {
    switch( row)
    {
      case 0:
        Serial.print(F( "0 1 2   "));
        break;
      case 1:
        Serial.print(F( "3 4 5   "));
        break;
      case 2:
        Serial.print(F( "6 7 8   "));
        break;
    }
    for( int column=0; column<3; column++)
    {
      Serial.print( tile[row * 3 + column]);
      Serial.print( ' ');
    }
    Serial.println();
  }
  Serial.println(F( "-------------"));
}


void ResetTiles()
{
  for( int i=0; i<NUM_TILES; i++)
  {
    tile[i] = BLANK;    // For now a dot as blank.
  }
  countActivatedTiles = 0;
}


boolean CheckTiles()
{
  boolean win = false;
 
  for( int i=0; i<2; i++)
  {
    char c;
    if( i==0)
      c = 'X';
    else
      c = 'O';

    if( (tile[0] == c && tile[1] == c && tile[2] == c) ||
      (tile[3] == c && tile[4] == c && tile[5] == c) ||
      (tile[6] == c && tile[7] == c && tile[8] == c) ||
      (tile[0] == c && tile[3] == c && tile[6] == c) ||
      (tile[1] == c && tile[4] == c && tile[7] == c) ||
      (tile[2] == c && tile[5] == c && tile[8] == c) ||
      (tile[0] == c && tile[4] == c && tile[8] == c) ||
      (tile[2] == c && tile[4] == c && tile[6] == c))
    {
      win = true;
    }
  }
  return( win);
}

Berichten: 12
Geregistreerd: 15 Dec 2016, 19:45

Re: Spelletje Tic-tac-toe, hulp nodig

Berichtdoor hans50-dec » 13 Jan 2017, 23:55

@Koepel,
Thanks, ik ga er even voor zitten om het tot me te laten doordringen.

Volgende

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: esjovilivel en 28 gasten