Stap 4: De Code
De volledige code is hieronder. Echter bijzondere aandacht besteden aan de constanten verklaard aan de bovenkant van de code. Voor de Arduino Mega-versie, check de definities van de pin voor de rode en groene LED's, de knoppen, de winst van rode en groene LEDs, de reset-knop. De meeste van hen zijn gedefinieerd als 3D-matrices en ik heb de code aangelegd om te corresponderen met de LEDs en de knoppen, zoals wordt weergegeven in de foto's. Bovenste knop links op de foto komt overeen met het eerste element in de array. We dan werken over naar rechts, beneden een rij, over weer een rij omlaag en over opnieuw. Vergeet niet, het Fritzing diagram staat 90° rechtsom gedraaid ten opzichte van de foto's - maar ik heb nota genomen van de "nummering" van de LEDs en de knoppen op het diagram.
Voor de Arduino Uno-versie, check de pinnen van de Charlieplex bij de bovenkant van het Wetboek, de analoge pin ("knoop") en de resetpin van de knop. Je moet niet hebben een probleem met de nummering van de LED en het kan worden overgelaten als-is. Als voor sommige vreemde reden, de matrix knop niet werkt, moet u te doen uw eigen probleemoplossing om te controleren de spanningswaarden die komen in de analoge pin op elke druk op de knop en de "resButtons"-matrix dienovereenkomstig aan te passen.
Vergeet niet, voor de Arduino Uno-versie, moet u de Charlieplex bibliotheek gekoppeld als een bestand onder de code. Unzip het en plaats deze in de omslag van bibliotheken voor de Arduino IDE (u kunt zoeken op het web als u niet weet hoe).
De intelligentie bit is niets meer dan de Arduino elke kolom-, rij- en diagonaal te controleren om te zien of er al twee rode LEDs verlicht en een vrije ruimte te plaatsen van een stuk. Dit zou betekenen dat de Arduino kon winnen en dit heeft voorrang. Als de Arduino niet zo'n lijn vindt, zal het dan doen hetzelfde opnieuw maar dit keer op zoek naar twee groene LEDs en een vrije ruimte. Dit betekent dat de mens kan winnen en de Arduino zal daarom leg een stukje om te blokkeren van de mens. Tot slot, als het niet kan winnen of blokkeren, het zal Kies een plaats willekeurig door één van de vrije ruimten op het bord te kiezen.
Ik heb het commentaar van de code zo veel mogelijk zodat u kunt begrijpen wat er gebeurt. Ik weet dat de code zou een stuk efficiënter. Ik denk dat het is niet slecht voor een eerste poging hoor. Succes!
Voor de Arduino Mega: (Arduino Uno versie is hieronder)
// TIC TAC TOE for Arduino Mega // by Nick Harvey // Include any libraries needed #include <liquidcrystal.h> // For the LCD // Define pins const int green[3][3] = { // Green is the player {30, 31, 32}, {33, 34, 35}, {36, 37, 38} }; const int red[3][3] = { // Red is the Arduino {40, 41, 42}, {43, 44, 45}, {46, 47, 48} }; const int button[3][3] = { // Buttons to choose position {2, 3, 4}, {5, 6, 7}, {8, 9, 10} }; const int greenWin = 50; // Lights if the player wins const int redWin = 51; // Lights if the Arduino wins const int resetButton = 11; // Button to start a new game const int win[8][3][3] = { // This 4D array defines all possible winning combinations { {1, 1, 1}, {0, 0, 0}, {0, 0, 0} }, { {0, 0, 0}, {1, 1, 1}, {0, 0, 0} }, { {0, 0, 0}, {0, 0, 0}, {1, 1, 1} }, { {1, 0, 0}, {1, 0, 0}, {1, 0, 0} }, { {0, 1, 0}, {0, 1, 0}, {0, 1, 0} }, { {0, 0, 1}, {0, 0, 1}, {0, 0, 1} }, { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }, { {0, 0, 1}, {0, 1, 0}, {1, 0, 0} } }; LiquidCrystal lcd(A4, A5, A3, A2, A1, A0); // Pins used for the LCD display (standard Arduino LCD library) // Global variables int gamePlay[3][3] = { // Holds the current game {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }; int squaresLeft = 9; // The number of free squares left on the board int played = 0; // Has the Arduino played or not // Global constants const int startupFlashSpeed = 100; // The time in milliseconds the LEDs light for on startup const int arduinoDelay = 3000; // How long the Arduino waits before playing (simulates thought) void setup() { // put your setup code here, to run once: // Start serial comms Serial.begin(9600); // Initialise LCD lcd.begin(16, 2); // Define green and red pins as outputs for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { pinMode(green[i][j], OUTPUT); pinMode(red[i][j], OUTPUT); } } // Define green and red win lights as outputs pinMode(greenWin, OUTPUT); pinMode(redWin, OUTPUT); // Define buttons as inputs for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { pinMode(button[i][j], INPUT); } } //Define reset button as input pinMode(resetButton, INPUT); initialise(); // Do startup flash startupFlash(); } void initialise() { // Prepare the board for a game disp("TIC TAC TOE"); // Set green and red LEDs off for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { digitalWrite(green[i][j], LOW); digitalWrite(red[i][j], LOW); gamePlay[i][j] = 0; } } // Set win LEDs off digitalWrite(greenWin, LOW); digitalWrite(redWin, LOW); // Reset variables squaresLeft = 9; // Tell the player it's their turn disp("Your turn..."); } void loop() { // put your main code here, to run repeatedly: // Wait for an input and call the buttonPress routine if pressed for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if ((digitalRead(button[i][j]) == HIGH) && (gamePlay[i][j] == 0)) { buttonPress(i, j); // Pass the x and y of the button pressed break; } } } } void buttonPress(int i, int j) { // Button pressed, light the green LED and note the square as taken Serial.print("Button press "); Serial.print(i); Serial.println(j); digitalWrite(green[i][j], HIGH); gamePlay[i][j] = 1; // Note the square played squaresLeft -= 1; // Update number of squares left printGame(); // Print the game to serial monitor checkGame(); // Check for a winner arduinosTurn(); // Arduino's turn } void arduinosTurn() { // Arduino takes a turn Serial.println("Arduino's turn"); disp("My turn..."); checkPossiblities(); // Check to see if a winning move can be played if (played == 0) { checkBlockers(); // If no winning move played, check to see if we can block a win } if (played == 0) { randomPlay(); // Otherwise, pick a random square } squaresLeft -= 1; // Update number of squares left played = 0; // Reset if played or not printGame(); // Print the games to serial monitor checkGame(); // Check for a winner disp("Your turn..."); // Tell the player it's their turn } void checkPossiblities() { // Check all rows, then columns, then diagonals to see if there are two reds lit and a free square to make a line of three Serial.println("Checking possibilities to win..."); disp("Can I win?"); int poss = 0; // Used to count if possible - if it gets to 2 then its a possiblity int x = 0; // The X position to play int y = 0; // The Y position to play int space = 0; // Is there a free square or not to play // Check rows for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[i][j] == 2) { poss += 1; // Square is red. Increment the possiblity counter } if (gamePlay[i][j] == 0) { space = 1; // Square is empty. Note this and the position x = i; y = j; } if ((poss == 2) && (space == 1)) { // 2 red squares and a free square Serial.print("Found an obvious row! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } poss = 0; x = 0; y = 0; space = 0; } // Check columns - same as for rows but the "for" loops have been reversed to go to columns for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[j][i] == 2) { poss += 1; } if (gamePlay[j][i] == 0) { space = 1; x = j; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { // This time also check if we've already played Serial.print("Found an obvious column! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } // Reset variables poss = 0; x = 0; y = 0; space = 0; } // Check crosses - as for rows and columns but "for" loops changed // Check diagonal top left to bottom right for (int i = 0; i < 3; i++) { if (gamePlay[i][i] == 2) { poss += 1; } if (gamePlay[i][i] == 0) { space = 1; x = i; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an obvious cross! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } // Reset variables poss = 0; x = 0; y = 0; space = 0; // Check diagonal top right to bottom left int row = 0; // Used to count up the rows for (int i = 2; i >= 0; i--) { // We count DOWN the columns if (gamePlay[row][i] == 2) { poss += 1; } if (gamePlay[row][i] == 0) { space = 1; x = row; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an obvious cross! "); Serial.print(x); Serial.println(y); playPoss(x, y); } row += 1; // Increment the row counter } // Reset variables poss = 0; x = 0; y = 0; space = 0; } void checkBlockers() { // As for checkPossibilites() but this time checking the players squares for places to block a line of three Serial.println("Checking possibilities to block..."); disp("Can I block?"); int poss = 0; int x = 0; int y = 0; int space = 0; // Check rows for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[i][j] == 1) { poss += 1; } if (gamePlay[i][j] == 0) { space = 1; x = i; y = j; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an blocker row! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } poss = 0; x = 0; y = 0; space = 0; } // Check columns for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[j][i] == 1) { poss += 1; } if (gamePlay[j][i] == 0) { space = 1; x = j; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an blocker column! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } poss = 0; x = 0; y = 0; space = 0; } // Check crosses for (int i = 0; i < 3; i++) { if (gamePlay[i][i] == 1) { poss += 1; } if (gamePlay[i][i] == 0) { space = 1; x = i; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an blocker cross! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } poss = 0; x = 0; y = 0; space = 0; int row = 0; for (int i = 2; i >= 0; i--) { if (gamePlay[row][i] == 1) { poss += 1; } if (gamePlay[row][i] == 0) { space = 1; x = row; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an blocker cross! "); Serial.print(x); Serial.println(y); playPoss(x, y); } row += 1; } poss = 0; x = 0; y = 0; space = 0; } void randomPlay() { // No win or block to play... Let's just pick a square at random Serial.println("Choosing randomly..."); int choice = random(1, squaresLeft); // We pick a number from 0 to the number of squares left on the board Serial.print("Arduino chooses "); Serial.println(choice); int pos = 1; // Stores the free square we're currently on for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[i][j] == 0) { // Check to see if square empty if (pos == choice) { // Play the empty square that corresponds to the random number playPoss(i, j); } pos += 1; // Increment the free square counter } } } } void playPoss(int x, int y) { // Simulate thought and then play the chosen square disp("Hmmm..."); delay(arduinoDelay); disp("OK"); digitalWrite(red[x][y], HIGH); gamePlay[x][y] = 2; // Update the game play array played = 1; // Note that we've played } void checkGame() { // Check the game for a winner // Check if the player has won Serial.println("Checking for a winner"); disp("Checking..."); int player = 1; int winner = 0; for (int i = 0; i < 8; i++) { // We cycle through all winning combinations in the 4D array and check if they correspond to the current game //Check game int winCheck = 0; for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { if ((win[i][j][k] == 1) && (gamePlay[j][k] == player)) { winCheck += 1; } } } if (winCheck == 3) { winner = 1; Serial.print("Player won game "); Serial.println(i); endGame(1); } } // Do the same for to check if the Arduino has won player = 2; winner = 0; for (int i = 0; i < 8; i++) { //Check game int winCheck = 0; for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { if ((win[i][j][k] == 1) && (gamePlay[j][k] == player)) { winCheck += 1; } } } if (winCheck == 3) { winner = 1; Serial.print("Arduino won game "); Serial.println(i); endGame(2); } } if (squaresLeft == -1) { endGame(0); } } void printGame() { // Prints the game to the serial monitor for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Serial.print(gamePlay[i][j]); Serial.print(" "); } Serial.println(""); } Serial.print(squaresLeft); Serial.println(" squares left"); } void endGame(int winner) { // Is called when a winner is found switch (winner) { case 0: Serial.println("It's a draw"); digitalWrite(greenWin, HIGH); digitalWrite(redWin, HIGH); disp("It's a draw!"); break; case 1: Serial.println("Player wins"); digitalWrite(greenWin, HIGH); disp("You win!!!"); break; case 2: Serial.println("Arduino wins"); digitalWrite(redWin, HIGH); disp("I win!!!"); break; } lcd.setCursor(0, 1); lcd.print("Press reset..."); while (digitalRead(resetButton) == LOW) { } initialise(); } void disp(String message) { // Used to quickly display a message on the LCD lcd.clear(); lcd.setCursor(0, 0); lcd.print(message); } void startupFlash() { // Flash at the start for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { digitalWrite(green[i][j], HIGH); digitalWrite(greenWin, HIGH); delay(startupFlashSpeed); digitalWrite(green[i][j], LOW); digitalWrite(greenWin, LOW); digitalWrite(red[i][j], HIGH); digitalWrite(redWin, HIGH); delay(startupFlashSpeed); digitalWrite(red[i][j], LOW); digitalWrite(redWin, LOW); } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { digitalWrite(green[j][i], HIGH); delay(startupFlashSpeed); digitalWrite(green[j][i], LOW); } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { digitalWrite(red[i][j], HIGH); delay(startupFlashSpeed); digitalWrite(red[i][j], LOW); } } for (int i = 0; i < 3; i++) { digitalWrite(red[i][i], HIGH); delay(startupFlashSpeed); digitalWrite(red[i][i], LOW); } int row = 0; for (int i = 2; i >= 0; i--) { digitalWrite(green[row][i], HIGH); delay(startupFlashSpeed); digitalWrite(green[row][i], LOW); row += 1; } }
Voor de Arduino Uno:
<p>// TIC TAC TOE for Arduino Uno<br>// by Nick Harvey</p><p>#include <charlieplex.h> byte pins[5] = {5, 6, 9, 10, 11}; Charlieplex charlie(pins, sizeof(pins));</charlieplex.h></p><p>// Define LEDs const int green[3][3] = { // Green is the player {0, 8, 14}, {2, 10, 16}, {4, 12, 6} }; const int red[3][3] = { // Red is the Arduino {1, 9, 15}, {3, 11, 17}, {5, 13, 7} }; const int button = A0; // The analog pin the button matrix is connected to</p><p>const int resButtons[3][3] = { // The resistance thresholds for the buttons {800, 400, 200}, {160, 140, 120}, {90, 85, 70} };</p><p>const int greenWin = 18; // Lights if the player wins const int redWin = 19; // Lights if the Arduino wins const int resetButton = 13; // Button to start a new game</p><p>const int win[8][3][3] = { // This 4D array defines all possible winning combinations { {1, 1, 1}, {0, 0, 0}, {0, 0, 0} }, { {0, 0, 0}, {1, 1, 1}, {0, 0, 0} }, { {0, 0, 0}, {0, 0, 0}, {1, 1, 1} }, { {1, 0, 0}, {1, 0, 0}, {1, 0, 0} }, { {0, 1, 0}, {0, 1, 0}, {0, 1, 0} }, { {0, 0, 1}, {0, 0, 1}, {0, 0, 1} }, { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }, { {0, 0, 1}, {0, 1, 0}, {1, 0, 0} } };</p><p>// Global variables int gamePlay[3][3] = { // Holds the current game {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }; int squaresLeft = 9; // The number of free squares left on the board int played = 0; // Has the Arduino played or not</p><p>// Global constants const int arduinoDelay = 3000; // How long the Arduino waits before playing (simulates thought)</p><p>void setup() { // put your setup code here, to run once:</p><p> // Start serial comms Serial.begin(9600);</p><p> // Define buttons as inputs pinMode(button, INPUT);</p><p> //Define reset button as input pinMode(resetButton, INPUT);</p><p> initialise(); }</p><p>void initialise() { // Prepare the board for a game Serial.println("Initialising..."); // Set green and red LEDs off for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { charlie.setLed(green[i][j], false); charlie.setLed(red[i][j], false); gamePlay[i][j] = 0; } } // Set win LEDs off charlie.setLed(greenWin, false); charlie.setLed(redWin, false);</p><p> // Reset variables squaresLeft = 9; } void loop() { // put your main code here, to run repeatedly: // Wait for an input and call the buttonPress routine if pressed int upper = 10000; if (analogRead(button) != 0) { int x; int y; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[i][j] == 0) { if ((analogRead(button) > resButtons[i][j]) && (analogRead(button) < upper)) { buttonPress(i, j); } } upper = resButtons[i][j]; } } } charlie.loop(); }</p><p>void buttonPress(int i, int j) { // Button pressed, light the green LED and note the square as taken Serial.print("Button press "); Serial.print(i); Serial.print(":"); Serial.println(j); charlie.setLed(green[i][j], true); gamePlay[i][j] = 1; // Note the square played squaresLeft -= 1; // Update number of squares left printGame(); // Print the game to serial monitor checkGame(); // Check for a winner arduinosTurn(); // Arduino's turn }</p><p>void arduinosTurn() { // Arduino takes a turn Serial.println("Arduino's turn"); checkPossiblities(); // Check to see if a winning move can be played if (played == 0) { checkBlockers(); // If no winning move played, check to see if we can block a win } if (played == 0) { randomPlay(); // Otherwise, pick a random square } squaresLeft -= 1; // Update number of squares left played = 0; // Reset if played or not printGame(); // Print the games to serial monitor checkGame(); // Check for a winner }</p><p>void checkPossiblities() { // Check all rows, then columns, then diagonals to see if there are two reds lit and a free square to make a line of three Serial.println("Checking possibilities to win..."); int poss = 0; // Used to count if possible - if it gets to 2 then its a possiblity int x = 0; // The X position to play int y = 0; // The Y position to play int space = 0; // Is there a free square or not to play // Check rows for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[i][j] == 2) { poss += 1; // Square is red. Increment the possiblity counter } if (gamePlay[i][j] == 0) { space = 1; // Square is empty. Note this and the position x = i; y = j; } if ((poss == 2) && (space == 1)) { // 2 red squares and a free square Serial.print("Found an obvious row! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } poss = 0; x = 0; y = 0; space = 0; }</p><p> // Check columns - same as for rows but the "for" loops have been reversed to go to columns for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[j][i] == 2) { poss += 1; } if (gamePlay[j][i] == 0) { space = 1; x = j; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { // This time also check if we've already played Serial.print("Found an obvious column! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } // Reset variables poss = 0; x = 0; y = 0; space = 0; }</p><p> // Check crosses - as for rows and columns but "for" loops changed // Check diagonal top left to bottom right for (int i = 0; i < 3; i++) { if (gamePlay[i][i] == 2) { poss += 1; } if (gamePlay[i][i] == 0) { space = 1; x = i; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an obvious cross! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } // Reset variables poss = 0; x = 0; y = 0; space = 0; // Check diagonal top right to bottom left int row = 0; // Used to count up the rows for (int i = 2; i >= 0; i--) { // We count DOWN the columns if (gamePlay[row][i] == 2) { poss += 1; } if (gamePlay[row][i] == 0) { space = 1; x = row; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an obvious cross! "); Serial.print(x); Serial.println(y); playPoss(x, y); } row += 1; // Increment the row counter } // Reset variables poss = 0; x = 0; y = 0; space = 0; }</p><p>void checkBlockers() { // As for checkPossibilites() but this time checking the players squares for places to block a line of three Serial.println("Checking possibilities to block..."); int poss = 0; int x = 0; int y = 0; int space = 0; // Check rows for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[i][j] == 1) { poss += 1; } if (gamePlay[i][j] == 0) { space = 1; x = i; y = j; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an blocker row! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } poss = 0; x = 0; y = 0; space = 0; }</p><p> // Check columns for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[j][i] == 1) { poss += 1; } if (gamePlay[j][i] == 0) { space = 1; x = j; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an blocker column! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } poss = 0; x = 0; y = 0; space = 0; }</p><p> // Check crosses for (int i = 0; i < 3; i++) { if (gamePlay[i][i] == 1) { poss += 1; } if (gamePlay[i][i] == 0) { space = 1; x = i; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an blocker cross! "); Serial.print(x); Serial.println(y); playPoss(x, y); } } poss = 0; x = 0; y = 0; space = 0; int row = 0; for (int i = 2; i >= 0; i--) { if (gamePlay[row][i] == 1) { poss += 1; } if (gamePlay[row][i] == 0) { space = 1; x = row; y = i; } if ((poss == 2) && (space == 1) && (played == 0)) { Serial.print("Found an blocker cross! "); Serial.print(x); Serial.println(y); playPoss(x, y); } row += 1; } poss = 0; x = 0; y = 0; space = 0; }</p><p>void randomPlay() { // No win or block to play... Let's just pick a square at random Serial.println("Choosing randomly..."); int choice = random(1, squaresLeft); // We pick a number from 0 to the number of squares left on the board Serial.print("Arduino chooses "); Serial.println(choice); int pos = 1; // Stores the free square we're currently on for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gamePlay[i][j] == 0) { // Check to see if square empty if (pos == choice) { // Play the empty square that corresponds to the random number playPoss(i, j); } pos += 1; // Increment the free square counter } } } }</p><p>void playPoss(int x, int y) { // Simulate thought and then play the chosen square int delayStop = millis() + arduinoDelay; while (millis() < delayStop) { charlie.loop(); } charlie.setLed(red[x][y], true); gamePlay[x][y] = 2; // Update the game play array played = 1; // Note that we've played }</p><p>void checkGame() { // Check the game for a winner // Check if the player has won Serial.println("Checking for a winner"); int player = 1; int winner = 0; for (int i = 0; i < 8; i++) { // We cycle through all winning combinations in the 4D array and check if they correspond to the current game //Check game int winCheck = 0; for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { if ((win[i][j][k] == 1) && (gamePlay[j][k] == player)) { winCheck += 1; } } } if (winCheck == 3) { winner = 1; Serial.print("Player won game "); Serial.println(i); endGame(1); } } // Do the same for to check if the Arduino has won player = 2; winner = 0; for (int i = 0; i < 8; i++) { //Check game int winCheck = 0; for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { if ((win[i][j][k] == 1) && (gamePlay[j][k] == player)) { winCheck += 1; } } } if (winCheck == 3) { winner = 1; Serial.print("Arduino won game "); Serial.println(i); endGame(2); } } if (squaresLeft == -1) { endGame(0); } }</p><p>void printGame() { // Prints the game to the serial monitor for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Serial.print(gamePlay[i][j]); Serial.print(" "); } Serial.println(""); } Serial.print(squaresLeft); Serial.println(" squares left"); }</p><p>void endGame(int winner) { // Is called when a winner is found switch (winner) { case 0: Serial.println("It's a draw"); charlie.setLed(greenWin, true); charlie.setLed(redWin, true); break; case 1: Serial.println("Player wins"); charlie.setLed(greenWin, true); break; case 2: Serial.println("Arduino wins"); charlie.setLed(redWin, true); break; } while (digitalRead(resetButton) == LOW) { charlie.loop(); } initialise(); }</p>