#include <Keypad.h>
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#define TFT_DC 9
#define TFT_CS 10
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
struct coord {
int x, y;
};
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
char keys[ROWS][COLS] = {
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};
uint8_t colPins[COLS] = { 4, 3, 2, 1 }; // Pins connected to C1, C2, C3, C4
uint8_t rowPins[ROWS] = { 8, 7, 6, 5 }; // Pins connected to R1, R2, R3, R4
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
boolean gameStarted = false;
const coord pos[] = {
{60, 90},
{120, 90},
{180, 90},
{60, 150},
{120, 150},
{180, 150},
{60, 210},
{120, 210},
{180, 210}
};
int board[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // holds position data 0 is blank, 1 human, 2 is computer
int moves = 0, winner = 0;
void setup() {
Serial.begin(9600);
tft.begin();
tft.setCursor(20, 20);
tft.setTextColor(ILI9341_RED);
tft.setTextSize(3);
tft.println("Welcome to X|O");
tft.setCursor(20, 160);
tft.setTextColor(ILI9341_GREEN);
tft.setTextSize(2);
tft.println("Press '*' to play");
}
void loop() {
char key = keypad.getKey();
if (key == '*' && !gameStarted) {
disp_game();
gameStarted = true;
}
}
void disp_game() {
disp_reset();
do {
// (moves & 1)?cpuMove():playerMove();
if(moves & 1)cpuMove();
else playerMove();
checkWinner();
moves++;
}while (winner == 0 && moves < 9);
if (winner == 1)
dispGameOverMsg("Human wins!");
else if (winner == 2)
dispGameOverMsg("CPU WINS");
else
dispGameOverMsg("DRAW");
}
void cpuMove() {
int b = 0;
int counter = 0;
int movesPlayed = 0;
int firstMoves[] = {0, 2, 6, 8}; // will use these positions first
for (counter = 0; counter < 4; counter++) {
if (board[firstMoves[counter]] != 0) movesPlayed++;
}
do {
if (moves <= 2){
int randomMove = random(4);
int c = firstMoves[randomMove];
if (board[c] == 0){
delay(1000);
board[c] = 2;
drawO(firstMoves[randomMove]);
b = 1;
}
}
else{
int nextMove = checkOpponent();
if (nextMove == 100){
if (movesPlayed == 4) //All first moves are played{
int randomMove = random(9);
if (board[randomMove] == 0){
delay(1000);
board[randomMove] = 2;
drawO(randomMove);
b = 1;
}
}
else{
int randomMove = random(4);
int c = firstMoves[randomMove];
if (board[c] == 0){
delay(1000);
board[c] = 2;
drawO(firstMoves[randomMove]);
b = 1;
}
}
}
else{
delay(1000);
board[nextMove] = 2;
drawO(nextMove);
b = 1;
}
}
}
while (b < 1);
}
void playerMove() {
while (1) {
char key = keypad.getKey();
if (key != NO_KEY && key >= '1' && key <= '9' && board[key - '1'] == 0) {
drawX(key);
board[key - '1'] = 1;
break;
}
}
}
void drawO(int key) {
tft.drawCircle(pos[key].x, pos[key].y, 18, ILI9341_GREEN);
}
void drawX(int key) {
tft.drawLine(pos[key - '1'].x - 18, pos[key - '1'].y - 18, pos[key - '1'].x + 18, pos[key - '1'].y + 18, ILI9341_YELLOW);
tft.drawLine(pos[key - '1'].x - 18, pos[key - '1'].y + 18, pos[key - '1'].x + 18, pos[key - '1'].y - 18, ILI9341_YELLOW);
}
void checkWinner() {
// X win
for(int i=0;i<9;i+=3){
if(board[i]!=winner &&(board[i]==board[i+1]==board[i+2])){ //horizontal win
winner=board[i];
return;
}
}
for(int i=0;i<3;i++){
if(board[i]!=winner &&(board[i]==board[i+3]==board[i+6])){ //vertical win
winner=board[i];
return;
}
}
if(board[4]!=winner && (board[0]==board[4]==board[8])) winner = board[4];
if(board[4]!=winner && (board[2]==board[4]==board[6])) winner = board[4];
return;
// noughts win?
// if (board[0] == 1 && board[1] == 1 && board[2] == 1) {
// winner = 1;
// }
// if (board[3] == 1 && board[4] == 1 && board[5] == 1) {
// winner = 1;
// }
// if (board[6] == 1 && board[7] == 1 && board[8] == 1) {
// winner = 1;
// }
// if (board[0] == 1 && board[3] == 1 && board[6] == 1) {
// winner = 1;
// }
// if (board[1] == 1 && board[4] == 1 && board[7] == 1) {
// winner = 1;
// }
// if (board[2] == 1 && board[5] == 1 && board[8] == 1) {
// winner = 1;
// }
// if (board[0] == 1 && board[4] == 1 && board[8] == 1) {
// winner = 1;
// }
// if (board[2] == 1 && board[4] == 1 && board[6] == 1) {
// winner = 1;
// }
// // crosses win?
// if (board[0] == 2 && board[1] == 2 && board[2] == 2) {
// winner = 2;
// }
// if (board[3] == 2 && board[4] == 2 && board[5] == 2) {
// winner = 2;
// }
// if (board[6] == 2 && board[7] == 2 && board[8] == 2) {
// winner = 2;
// }
// if (board[0] == 2 && board[3] == 2 && board[6] == 2) {
// winner = 2;
// }
// if (board[1] == 2 && board[4] == 2 && board[7] == 2) {
// winner = 2;
// }
// if (board[2] == 2 && board[5] == 2 && board[8] == 2) {
// winner = 2;
// }
// if (board[0] == 2 && board[4] == 2 && board[8] == 2) {
// winner = 2;
// }
// if (board[2] == 2 && board[4] == 2 && board[6] == 2) {
// winner = 2;
// }
}
int checkOpponent()
{
if (board[0] == 1 && board[1] == 1 && board[2] == 0)
return 2;
else if (board[0] == 1 && board[1] == 0 && board[2] == 1)
return 1;
else if (board[1] == 1 && board [2] == 1 && board[0] == 0)
return 0;
else if (board[3] == 1 && board[4] == 1 && board[5] == 0)
return 5;
else if (board[4] == 1 && board[5] == 1 && board[3] == 0)
return 3;
else if (board[3] == 1 && board[4] == 0 && board[5] == 1)
return 4;
else if (board[1] == 0 && board[4] == 1 && board[7] == 1)
return 1;
else
return 100;
}
void disp_reset(){
// Clear screen
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(20, 20);
tft.setTextColor(ILI9341_RED);
tft.setTextSize(3);
tft.println("TIC-TAC-TOE");
winner = 0, moves = 0;
for (int i = 0; i < 9; i++) board[i] = 0;
// grid
tft.drawRect(30, 60, 180, 180, ILI9341_WHITE);
tft.drawFastVLine(90, 60, 180, ILI9341_WHITE);
tft.drawFastVLine(150, 60, 180, ILI9341_WHITE);
tft.drawFastHLine(30, 120, 180, ILI9341_WHITE);
tft.drawFastHLine(30, 180, 180, ILI9341_WHITE);
}
void dispGameOverMsg(String msg){
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(20, 20);
tft.setTextColor(ILI9341_RED);
tft.setTextSize(3);
tft.println(msg);
gameStarted = false;
tft.setCursor(20, 160);
tft.setTextColor(ILI9341_GREEN);
tft.setTextSize(2);
tft.println("Press '*' to play again");
while(1){
char key = keypad.getKey();
if (key == '*') {
disp_game();
gameStarted = true;
}
}
}