Hardware components | ||||||
![]() |
| × | 1 | |||
| × | 1 | ||||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
![]() |
|
About
Read moreHello, I want to share my work on the project from nickthegreek82: arduino-touch-tic-tac-toe-game.
You need:
WiringThe wiring is as following for the touch-screen:
- Touch -> Arduino Due
- T_IRQ -> 22
- T_DO -> 24
- T_DIN -> 26
- T_CS -> 28
- T_CLK -> 30
For the display:
- Display -> Arduino Due
- SDO -> A.25
- LED -> 3.3V
- SCK -> A.27
- SDI -> A.26
- DC -> 9
- RESET -> 8
- CS -> 10
- GND -> GND
- VCC -> 3.3V
08.22.2017
Modified the KI and some code optimization.
08.26.2017
Some code optimization.
08.27.2017
Can you win against the CPU?
03.13.2018
found a better way for the A.I.
thanks goes to klauscam https://github.com/klauscam/ArduinoTicTacToe
/////////////////////////////////////////////
// 2.8" TOUCH SCREEN TIC TAC TOE //
// //
// http://www.educ8s.tv //
// //
// modified 08.2017 by rom3 //
/////////////////////////////////////////////
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <URTouch.h>
#include <avr/pgmspace.h>
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
#define TOUCH_ORIENTATION LANDSCAPE
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
Adafruit_GFX_Button buttons[9];
URTouch myTouch(30, 28, 26, 24, 22);
unsigned short int moves = 1;
unsigned short int winner = 0; //0 = Draw, 1 = Human, 2 = CPU
unsigned short int x,y; // position touch
unsigned short int cursor; // Cursor position
unsigned short int firstMoves[]={0,2,6,8}; // will use these positions first, if CPU begins
unsigned short int board[] = {0,0,0,0,0,0,0,0,0};// holds position data 0 is blank, 1 human, 2 is computer
bool player; // true=YOU, false=CPU
bool b=1;
char start[10] = {"Gamestart"};
char you[4] = {"YOU"};
char cpu[4] = {"CPU"};
char again[7] = {"Again?"};
const unsigned char circle[]PROGMEM={
0b0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0x80,0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xf0,0x0,0x0,0x0,
0x0,0x0,0xf,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfe,0x0,0x0,0x0,0x0,0x0,0x7f,0xf0,0x3,0xff,0x80,0x0,0x0,0x0,0x0,0xff,0x80,0x0,0x7f,0xc0,0x0,0x0,0x0,0x1,0xfe,0x0,0x0,0x1f,0xe0,0x0,0x0,
0x0,0x3,0xf8,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x3,0xf8,0x0,0x0,0x0,0xf,0xe0,0x0,0x0,0x1,0xfc,0x0,0x0,0x0,0xf,0xc0,0x0,0x0,0x0,0xfc,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x0,0x7e,0x0,0x0,
0x0,0x3f,0x0,0x0,0x0,0x0,0x3f,0x0,0x0,0x0,0x3e,0x0,0x0,0x0,0x0,0x1f,0x0,0x0,0x0,0x7e,0x0,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xf,0x80,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xf,0x80,0x0,
0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,0x3,0xc0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,
0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,
0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,0x3,0xc0,0x0,0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,
0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xf,0x80,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xf,0x80,0x0,0x0,0x7e,0x0,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x3e,0x0,0x0,0x0,0x0,0x1f,0x0,0x0,
0x0,0x3f,0x0,0x0,0x0,0x0,0x3f,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x0,0x7e,0x0,0x0,0x0,0xf,0xc0,0x0,0x0,0x0,0xfc,0x0,0x0,0x0,0xf,0xe0,0x0,0x0,0x1,0xfc,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x3,0xf8,0x0,0x0,
0x0,0x3,0xf8,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x1,0xfe,0x0,0x0,0x1f,0xe0,0x0,0x0,0x0,0x0,0xff,0x80,0x0,0x7f,0xc0,0x0,0x0,0x0,0x0,0x7f,0xf0,0x3,0xff,0x80,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfe,0x0,0x0,0x0,
0x0,0x0,0xf,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xf0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};
const unsigned char x_bitmap[]PROGMEM={
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xc0,0x1,0xff,0xff,0xe0,0x0,
0x1,0xff,0xff,0xe0,0x1,0xff,0xff,0xc0,0x0,0x1,0xff,0xff,0xf0,0x3,0xff,0xff,0xc0,0x0,0x0,0xff,0xff,0xf0,0x7,0xff,0xff,0x80,0x0,0x0,0xff,0xff,0xf8,0x7,0xff,0xff,0x80,0x0,0x0,0x7f,0xff,0xf8,0xf,0xff,0xff,0x0,0x0,
0x0,0x3f,0xff,0xfc,0xf,0xff,0xfe,0x0,0x0,0x0,0x3f,0xff,0xfe,0x1f,0xff,0xfe,0x0,0x0,0x0,0x1f,0xff,0xfe,0x1f,0xff,0xfc,0x0,0x0,0x0,0x1f,0xff,0xff,0x3f,0xff,0xfc,0x0,0x0,0x0,0xf,0xff,0xff,0x7f,0xff,0xf8,0x0,0x0,
0x0,0xf,0xff,0xff,0xff,0xff,0xf8,0x0,0x0,0x0,0x7,0xff,0xff,0xff,0xff,0xf0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x1,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,
0x0,0x1,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x80,0x0,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x80,0x0,0x0,0x0,0x0,0x7f,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x3f,0xff,0xff,0xfe,0x0,0x0,0x0,
0x0,0x0,0x3f,0xff,0xff,0xfe,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x3f,0xff,0xff,0xfe,0x0,0x0,0x0,
0x0,0x0,0x3f,0xff,0xff,0xfe,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x80,0x0,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x80,0x0,0x0,0x0,0x1,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,
0x0,0x1,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x7,0xff,0xff,0xff,0xff,0xf0,0x0,0x0,0x0,0xf,0xff,0xff,0xff,0xff,0xf8,0x0,0x0,
0x0,0xf,0xff,0xff,0xff,0xff,0xf8,0x0,0x0,0x0,0x1f,0xff,0xff,0x7f,0xff,0xfc,0x0,0x0,0x0,0x1f,0xff,0xfe,0x3f,0xff,0xfc,0x0,0x0,0x0,0x3f,0xff,0xfc,0x3f,0xff,0xfe,0x0,0x0,0x0,0x3f,0xff,0xfc,0x1f,0xff,0xfe,0x0,0x0,
0x0,0x7f,0xff,0xf8,0x1f,0xff,0xff,0x0,0x0,0x0,0xff,0xff,0xf8,0xf,0xff,0xff,0x80,0x0,0x0,0xff,0xff,0xf0,0x7,0xff,0xff,0x80,0x0,0x1,0xff,0xff,0xe0,0x7,0xff,0xff,0xc0,0x0,0x1,0xff,0xff,0xe0,0x3,0xff,0xff,0xc0,0x0,
0x3,0xff,0xff,0xc0,0x3,0xff,0xff,0xe0,0x0,0x3,0xff,0xff,0xc0,0x1,0xff,0xff,0xe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};
void setup() {
myTouch.InitTouch();
myTouch.setPrecision(PREC_HI);
tft.begin();
tft.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
//Draw white frame
tft.drawRect(0,0,320,240,ILI9341_WHITE);
//Print "Arduino" text
tft.setCursor(80,30);
tft.setTextColor(ILI9341_GREEN);
tft.setTextSize(4);
tft.print("Arduino");
//Print "Tic Tac Toe" Text
tft.setCursor(30,100);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(4);
tft.print("Tic Tac Toe");
//Create Red Button
// create buttons // x, y, w, h, outline, fill, text
buttons[0].initButton(&tft, 160,200,200,40,ILI9341_WHITE, ILI9341_RED, ILI9341_WHITE,
start, 2);
buttons[0].drawButton();
do{
waitonetouch(&x,&y);
if (buttons[0].contains(x,y))
b=0;
}while(b>0);
}
void loop()
{
for(unsigned short int i=0;i<9;i++)
{
board[i]=0;
}
tft.fillScreen(ILI9341_BLACK);
//Draw white frame
tft.drawRect(0,0,320,240,ILI9341_WHITE);
//Print "Tic Tac Toe" Text
tft.setCursor(30,30);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(4);
tft.print("Tic Tac Toe");
//Print "YouTube!" text
tft.setCursor(30,100);
tft.setTextColor(ILI9341_GREEN);
tft.setTextSize(4);
tft.print("Who begins");
//Create Red Button
// create buttons // x, y, w, h, outline, fill, text
buttons[0].initButton(&tft, 100,200,80,40,ILI9341_WHITE, ILI9341_RED, ILI9341_WHITE,
you, 2);
buttons[0].drawButton();
// create buttons // x, y, w, h, outline, fill, text
buttons[1].initButton(&tft, 200,200,80,40,ILI9341_WHITE, ILI9341_RED, ILI9341_WHITE,
cpu, 2);
buttons[1].drawButton();
b=1;
do{
waitonetouch(&x,&y);
if (buttons[0].contains(x,y))
{
b=0;
player = 1;
tft.fillScreen(ILI9341_BLACK);
//Draw white frame
tft.drawRect(0,0,320,240,ILI9341_WHITE);
tft.setCursor(30,30);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Ok, you begin.");
delay(2000);
}
if(buttons[1].contains(x,y))
{
b=0;
player = 0;
tft.fillScreen(ILI9341_BLACK);
//Draw white frame
tft.drawRect(0,0,320,240,ILI9341_WHITE);
tft.setCursor(30,30);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Ok, CPU begins.");
delay(2000);
}
}while(b>0);
b=1;
moves = 1;
winner = 0;
cursor = 10;
tft.fillScreen(ILI9341_BLACK);
//Draw frame
tft.drawRect(0,0,320,240,ILI9341_WHITE);
//Draw vertical line
tft.fillRect(80,15,5,205,ILI9341_WHITE);
tft.fillRect(150,15,5,205,ILI9341_WHITE);
//Draw horizontal line
tft.fillRect(15,80,205,5,ILI9341_WHITE);
tft.fillRect(15,150,205,5,ILI9341_WHITE);
tft.drawRect(230,10,80,220,ILI9341_WHITE);
{
do
{
if(moves%2==1 && player==false || moves%2==0 && player==true)
{
cursor+=10;
tft.setCursor(240,cursor);
tft.setTextSize(1);
tft.println("I draw");
arduinoMove();
checkWinner();
}else
{
cursor+=10;
tft.setCursor(240,cursor);
tft.setTextSize(1);
tft.println("Your move");
playerMove();
checkWinner();
}
delay(1000);
moves++;
}while (winner==0 && moves<10);
waitonetouch(&x,&y);
tft.fillScreen(ILI9341_BLACK);
//Draw frame
tft.drawRect(0,0,320,240,ILI9341_WHITE);
//Print "Game Over" Text
tft.setCursor(50,30);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(4);
tft.print("GAME OVER");
if(winner == 0)
{
//Print "DRAW!" text
tft.setCursor(110,100);
tft.setTextColor(ILI9341_YELLOW);
tft.setTextSize(4);
tft.print("DRAW");
}
if(winner == 1)
{
//Print "HUMAN WINS!" text
tft.setCursor(40,100);
tft.setTextColor(ILI9341_BLUE);
tft.setTextSize(4);
tft.print("HUMAN WINS");
}
if(winner == 2)
{
//Print "CPU WINS!" text
tft.setCursor(60,100);
tft.setTextColor(ILI9341_RED);
tft.setTextSize(4);
tft.print("CPU WINS");
}
// create buttons // x, y, w, h, outline, fill, text
buttons[0].initButton(&tft, 160,200,200,40,ILI9341_WHITE, ILI9341_RED, ILI9341_WHITE,
again, 2);
buttons[0].drawButton();
do{
waitonetouch(&x,&y);
if (buttons[0].contains(x,y))
b=0;
}while(b>0);
}
}
void playerMove()
{
waitonetouch(&x,&y);
if((x>15 && x<85) && (y>15 && y<85)) //0
{
if(board[0]==0)
{
board[0]=1;
drawX(15,15);
}
else error();
}
else if((x>85 && x<155)&& (y>15 && y<85)) //1
{
if(board[1]==0)
{
board[1]=1;
drawX(85,15);
}
else error();
}
if((x>155 && x<225)&& (y>15 && y<85)) //2
{
if(board[2]==0)
{
board[2]=1;
drawX(155,15);
}
else error();
}
if((x>15 && x<85)&& (y>85 && y<155)) //3
{
if(board[3]==0)
{
board[3]=1;
drawX(15,85);
}
else error();
}
if((x>85 && x<155)&& (y>85 && y<155)) //4
{
if(board[4]==0)
{
board[4]=1;
drawX(85,85);
}
else error();
}
if((x>155 && x<225)&& (y>85 && y<155)) //5
{
if(board[5]==0)
{
board[5]=1;
drawX(155,85);
}
else error();
}
if((x>15 && x<85)&& (y>155 && y<225)) //6
{
if(board[6]==0)
{
board[6]=1;
drawX(15,155);
}
else error();
}
if((x>85 && x<155)&& (y>155 && y<225)) //7
{
if(board[7]==0)
{
board[7]=1;
drawX(85,155);
}
else error();
}
if((x>155 && x<225)&& (y>155 && y<225)) //8
{
if(board[8]==0)
{
board[8]=1;
drawX(155,155);
}
else error();
}
}
void error(){
cursor+=10;
tft.setCursor(240,cursor);
tft.setTextSize(1);
tft.println("Error");
delay(1000);
cursor+=10;
tft.setCursor(240,cursor);
tft.println("Try again.");
playerMove();
}
unsigned short int checkOpponent(unsigned short int x, unsigned short int y)
{
if(board[1]==x && board[2]==x && board[0]==y){
if(y==0){
return 0;
}
else return 1;
}
if(board[3]==x && board[6]==x && board[0]==y){
if(y==0){
return 0;
}
else return 6;
}
if(board[0]==y && board[4]==x && board[8]==x){
if(y==0){
return 0;
}
else return 8;
}
if(board[0]==x && board[1]==y && board[2]==x){
if(y==0){
return 1;
}
else return 0;
}
if(board[4]==x && board[7]==x && board[1]==y){
if(y==0){
return 1;
}
else return 7;
}
if(board[0]==x && board[1]==x && board[2]==y){
if(y==0){
return 2;
}
else return 0;
}
if(board[5]==x && board[8]==x && board[2]==y){
if(y==0){
return 2;
}
else return 8;
}
if(board[4]==x && board[6]==x && board[2]==y){
if(y==0){
return 2;
}
else return 6;
}
if(board[4]==x && board[5]==x && board[3]==y){
if(y==0){
return 3;
}
else return 5;
}
if(board[0]==x && board[6]==x && board[3]==y){
if(y==0){
return 3;
}
else return 6;
}
if(board[3]==x && board[4]==y && board[5]==x){
if(y==0){
return 4;
}
else return 3;
}
if(board[1]==x && board[7]==x && board[4]==y){
if(y==0){
return 4;
}
else return 1;
}
if(board[0]==x && board[8]==x && board[4]==y){
if(y==0){
return 4;
}
else return 0;
}
if(board[2]==x && board[6]==x && board[4]==y){
if(y==0){
return 4;
}
else return 2;
}
if(board[3]==x && board[4]==x && board[5]==y){
if(y==0){
return 5;
}
else return 3;
}
if(board[2]==x && board[8]==x && board[5]==y){
if(y==0){
return 5;
}
else return 2;
}
if(board[7]==x && board[8]==x && board[6]==y){
if(y==0){
return 6;
}
else return 8;
}
if(board[0]==x && board[3]==x && board[6]==y){
if(y==0){
return 6;
}
else return 0;
}
if(board[4]==x && board[2]==x && board[6]==y){
if(y==0){
return 6;
}
else return 2;
}
if(board[1]==x && board[4]==x && board[7]==y){
if(y==0){
return 7;
}
else return 1;
}
if(board[6]==x && board[8]==x && board[7]==y){
if(y==0){
return 7;
}
else return 6;
}
if(board[6]==x && board[7]==x && board[8]==y){
if(y==0){
return 8;
}
else return 6;
}
if(board[5]==x && board[2]==x && board[8]==y){
if(y==0){
return 8;
}
else return 2;
}
if(board[4]==x && board[0]==x && board[8]==y){
if(y==0){
return 8;
}
else return 0;
}
else
return 100;
}
void arduinoMove()
{
if(moves<2)
{
do{
unsigned short int randomMove =random(4);
unsigned short int c=firstMoves[randomMove];
if(board[c]==0){
board[c]=2;
drawCpuMove(firstMoves[randomMove]);
return;
}
}while(moves<2);
}
if(moves<3)
{
if(board[4]==0)
{
board[4]=2;
drawCpuMove(4);
return;
}
}
unsigned short int twoPlayer = checkOpponent(2,0);//CPU two in a row?
if(twoPlayer < 9)
{
board[twoPlayer]=2;
drawCpuMove(twoPlayer);
return;
}
unsigned short int nextMove = checkOpponent(1,0);//Player two in a row?
if(nextMove < 9)
{
board[nextMove]=2;
drawCpuMove(nextMove);
return;
}
unsigned short int next = checkOpponent(0,2);
if(next < 9)
{
board[next]=2;
drawCpuMove(next);
return;
}
do
{
unsigned short int randomMove =random(9);
if (board[randomMove]==0)
{
board[randomMove]=2;
drawCpuMove(randomMove);
return;
}
}while(nextMove == 100);
}
void drawCircle(unsigned short int x, unsigned short int y)
{
tft.drawBitmap(x,y,circle,65,65,ILI9341_RED);
}
void drawX(unsigned short int x, unsigned short int y)
{
tft.drawBitmap(x,y,x_bitmap,65,65,ILI9341_BLUE);
}
void drawCpuMove(unsigned short int move)
{
switch(move)
{
case 0: drawCircle(15,15); break;
case 1: drawCircle(85,15); break;
case 2: drawCircle(155,15); break;
case 3: drawCircle(15,85); break;
case 4: drawCircle(85,85); break;
case 5: drawCircle(155,85); break;
case 6: drawCircle(15,155); break;
case 7: drawCircle(85,155);break;
case 8: drawCircle(155,155);break;
}
}
void checkWinner()
// checks board to see if there is a winner
// places result in the global variable 'winner'
{
// noughts win?
if (board[0]>0 && board[1]==board[0] && board[2]==board[0]) {
winner=board[0];
tft.fillRect(15, 45, 205, 5, ILI9341_WHITE);
}
if (board[3]>0 && board[4]==board[3] && board[5]==board[3]) {
winner=board[3];
tft.fillRect(15, 115, 205, 5, ILI9341_WHITE);
}
if (board[6]>0 && board[7]==board[6] && board[8]==board[6]) {
winner=board[6];
tft.fillRect(15, 185, 205, 5, ILI9341_WHITE);
}
if (board[0]>0 && board[3]==board[0] && board[6]==board[0]) {
winner=board[0];
tft.fillRect(45, 15, 5, 205, ILI9341_WHITE);
}
if (board[1]>0 && board[4]==board[1] && board[7]==board[1]) {
winner=board[1];
tft.fillRect(115, 15, 5, 205, ILI9341_WHITE);
}
if (board[2]>0 && board[5]==board[2] && board[8]==board[2]) {
winner=board[2];
tft.fillRect(185, 15, 5, 205, ILI9341_WHITE);
}
if (board[0]>0 && board[4]==board[0] && board[8]==board[0]) {
winner=board[0];
for(unsigned short int xx=0;xx<6;xx++){
tft.drawLine(20+xx, 20, 210+xx, 210, ILI9341_WHITE);
}
}
if (board[2]>0 && board[4]==board[2] && board[6]==board[2]) {
winner=board[2];
for(unsigned short int xx=0;xx<6;xx++){
tft.drawLine(210+xx, 20, 20+xx, 210, ILI9341_WHITE);
}
}
}
void waitonetouch(unsigned short int *x,unsigned short int *y){
do
{
delay(10);
if (myTouch.dataAvailable() == true)
{
myTouch.read();
*x = myTouch.getX(); //Get touch point
*y = myTouch.getY();
return;
}
}while(myTouch.dataAvailable()==false);
}
/////////////////////////////////////////////
// 2.8" TOUCH SCREEN TIC TAC TOE //
// //
// http://www.educ8s.tv //
// //
// modified 08.2017 by rom3 //
/////////////////////////////////////////////
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <URTouch.h>
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
#define TOUCH_ORIENTATION LANDSCAPE
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
Adafruit_GFX_Button buttons[9];
URTouch myTouch(30, 28, 26, 24, 22);
char start[10] = {"Gamestart"};
char you[4] = {"YOU"};
char cpu[4] = {"CPU"};
char again[7] = {"Again?"};
int player;
int difficulty=8;
unsigned short int x,y,b; // position touch
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
int board[]={0,0,0,0,0,0,0,0,0};// holds position data 0 is blank, 1 human, 2 is computer
unsigned turn;
const unsigned char circle[]PROGMEM={
0b0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0x80,0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xf0,0x0,0x0,0x0,
0x0,0x0,0xf,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfe,0x0,0x0,0x0,0x0,0x0,0x7f,0xf0,0x3,0xff,0x80,0x0,0x0,0x0,0x0,0xff,0x80,0x0,0x7f,0xc0,0x0,0x0,0x0,0x1,0xfe,0x0,0x0,0x1f,0xe0,0x0,0x0,
0x0,0x3,0xf8,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x3,0xf8,0x0,0x0,0x0,0xf,0xe0,0x0,0x0,0x1,0xfc,0x0,0x0,0x0,0xf,0xc0,0x0,0x0,0x0,0xfc,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x0,0x7e,0x0,0x0,
0x0,0x3f,0x0,0x0,0x0,0x0,0x3f,0x0,0x0,0x0,0x3e,0x0,0x0,0x0,0x0,0x1f,0x0,0x0,0x0,0x7e,0x0,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xf,0x80,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xf,0x80,0x0,
0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,0x3,0xc0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,
0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,
0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,0x3,0xc0,0x0,0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,
0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xf,0x80,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xf,0x80,0x0,0x0,0x7e,0x0,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x3e,0x0,0x0,0x0,0x0,0x1f,0x0,0x0,
0x0,0x3f,0x0,0x0,0x0,0x0,0x3f,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x0,0x7e,0x0,0x0,0x0,0xf,0xc0,0x0,0x0,0x0,0xfc,0x0,0x0,0x0,0xf,0xe0,0x0,0x0,0x1,0xfc,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x3,0xf8,0x0,0x0,
0x0,0x3,0xf8,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x1,0xfe,0x0,0x0,0x1f,0xe0,0x0,0x0,0x0,0x0,0xff,0x80,0x0,0x7f,0xc0,0x0,0x0,0x0,0x0,0x7f,0xf0,0x3,0xff,0x80,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfe,0x0,0x0,0x0,
0x0,0x0,0xf,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xf0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};
const unsigned char x_bitmap[]PROGMEM={
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xc0,0x1,0xff,0xff,0xe0,0x0,
0x1,0xff,0xff,0xe0,0x1,0xff,0xff,0xc0,0x0,0x1,0xff,0xff,0xf0,0x3,0xff,0xff,0xc0,0x0,0x0,0xff,0xff,0xf0,0x7,0xff,0xff,0x80,0x0,0x0,0xff,0xff,0xf8,0x7,0xff,0xff,0x80,0x0,0x0,0x7f,0xff,0xf8,0xf,0xff,0xff,0x0,0x0,
0x0,0x3f,0xff,0xfc,0xf,0xff,0xfe,0x0,0x0,0x0,0x3f,0xff,0xfe,0x1f,0xff,0xfe,0x0,0x0,0x0,0x1f,0xff,0xfe,0x1f,0xff,0xfc,0x0,0x0,0x0,0x1f,0xff,0xff,0x3f,0xff,0xfc,0x0,0x0,0x0,0xf,0xff,0xff,0x7f,0xff,0xf8,0x0,0x0,
0x0,0xf,0xff,0xff,0xff,0xff,0xf8,0x0,0x0,0x0,0x7,0xff,0xff,0xff,0xff,0xf0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x1,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,
0x0,0x1,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x80,0x0,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x80,0x0,0x0,0x0,0x0,0x7f,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x3f,0xff,0xff,0xfe,0x0,0x0,0x0,
0x0,0x0,0x3f,0xff,0xff,0xfe,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x3f,0xff,0xff,0xfe,0x0,0x0,0x0,
0x0,0x0,0x3f,0xff,0xff,0xfe,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x80,0x0,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x80,0x0,0x0,0x0,0x1,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,
0x0,0x1,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x7,0xff,0xff,0xff,0xff,0xf0,0x0,0x0,0x0,0xf,0xff,0xff,0xff,0xff,0xf8,0x0,0x0,
0x0,0xf,0xff,0xff,0xff,0xff,0xf8,0x0,0x0,0x0,0x1f,0xff,0xff,0x7f,0xff,0xfc,0x0,0x0,0x0,0x1f,0xff,0xfe,0x3f,0xff,0xfc,0x0,0x0,0x0,0x3f,0xff,0xfc,0x3f,0xff,0xfe,0x0,0x0,0x0,0x3f,0xff,0xfc,0x1f,0xff,0xfe,0x0,0x0,
0x0,0x7f,0xff,0xf8,0x1f,0xff,0xff,0x0,0x0,0x0,0xff,0xff,0xf8,0xf,0xff,0xff,0x80,0x0,0x0,0xff,0xff,0xf0,0x7,0xff,0xff,0x80,0x0,0x1,0xff,0xff,0xe0,0x7,0xff,0xff,0xc0,0x0,0x1,0xff,0xff,0xe0,0x3,0xff,0xff,0xc0,0x0,
0x3,0xff,0xff,0xc0,0x3,0xff,0xff,0xe0,0x0,0x3,0xff,0xff,0xc0,0x1,0xff,0xff,0xe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};
void setup()
{
myTouch.InitTouch();
myTouch.setPrecision(PREC_HI);
tft.begin();
tft.setRotation(3);
}
void loop()
{
int board[9] = {0,0,0,0,0,0,0,0,0};
drawStartScreen();
do{
myTouch.read();
x = myTouch.getX(); //Get touch point
y = myTouch.getY();
delay(100);
}while(!(buttons[0].contains(x,y)));
tft.fillScreen(BLACK);
//Draw white frame
tft.drawRect(0,0,320,240,WHITE);
//Print "Tic Tac Toe" Text
tft.setCursor(30,30);
tft.setTextColor(WHITE);
tft.setTextSize(4);
tft.print("Tic Tac Toe");
//Print "YouTube!" text
tft.setCursor(30,100);
tft.setTextColor(GREEN);
tft.setTextSize(4);
tft.print("Who begins");
//Create Red Button
// create buttons // x, y, w, h, outline, fill, text
buttons[0].initButton(&tft, 100,200,80,40,WHITE, RED, WHITE,
you, 2);
buttons[0].drawButton();
// create buttons // x, y, w, h, outline, fill, text
buttons[1].initButton(&tft, 200,200,80,40,WHITE, RED, WHITE,
cpu, 2);
buttons[1].drawButton();
b=1;
do{
myTouch.read();
x = myTouch.getX(); //Get touch point
y = myTouch.getY();
if (buttons[0].contains(x,y))
{
b=0;
player = 1;
tft.fillScreen(BLACK);
//Draw white frame
tft.drawRect(0,0,320,240,WHITE);
tft.setCursor(30,30);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.print("Ok, you begin.");
delay(2000);
}
if(buttons[1].contains(x,y))
{
b=0;
player = 2;
tft.fillScreen(BLACK);
//Draw white frame
tft.drawRect(0,0,320,240,WHITE);
tft.setCursor(30,30);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.print("Ok, CPU begins.");
delay(2000);
}
}while(b);
tft.fillScreen(BLACK);
tft.drawRect(0,0,319,240,WHITE);
drawVerticalLine(125);
drawVerticalLine(195);
drawHorizontalLine(80);
drawHorizontalLine(150);
for(turn = 0; turn < 9 && win(board) == 0; ++turn) {
if((turn+player) % 2 == 0)
computerMove(board);
else {
//draw(board);
playerMove(board);
}
}
switch(win(board)) {
case 0:
Serial.println("It's a draw.\n");
break;
case 1:
//draw(board);
Serial.println("You lose.\n");
break;
case -1:
Serial.println("You win!\n");
break;
}
do{}while(myTouch.dataAvailable()==false);
//x = map(tp.y, 930, 88, 0, 480);
//y = map(tp.x, 908, 125, 0, 320);
//delay(250);}
}
void drawHorizontalLine(int y)
{
int i=0;
for(i=0;i<7;i++)
{
tft.drawLine(60,y+i,270,y+i,WHITE);
}
}
void drawVerticalLine(int x)
{
int i=0;
for(i=0;i<7;i++)
{
tft.drawLine(x+i,20,x+i,220,WHITE);
}
}
void drawStartScreen()
{
tft.fillScreen(BLACK);
//Draw white frame
tft.drawRect(0,0,319,240,WHITE);
//Print "Tic Tac Toe" Text
tft.setCursor(30,100);
tft.setTextColor(WHITE);
tft.setTextSize(4);
tft.print("Tic Tac Toe");
//Print "YouTube!" text
tft.setCursor(80,30);
tft.setTextColor(GREEN);
tft.setTextSize(4);
tft.print("Arduino");
buttons[0].initButton(&tft, 160,200,200,40,WHITE, RED, WHITE, start, 2);
buttons[0].drawButton();
}
void drawCircle(int x, int y)
{
drawBitmap(x,y,circle,65,65,RED);
}
void drawX(int x, int y)
{
drawBitmap(x,y,x_bitmap,65,65,BLUE);
}
void drawBitmap(int16_t x, int16_t y,
const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) {
int16_t i, j, byteWidth = (w + 7) / 8;
uint8_t byte;
for(j=0; j<h; j++) {
for(i=0; i<w; i++) {
if(i & 7) byte <<= 1;
else byte = pgm_read_byte(bitmap + j * byteWidth + i / 8);
if(byte & 0x80) tft.drawPixel(x+i, y+j, color);
}
}
}
void computerMove(int board[9]) {
int move = -1;
int score = -2;
int i;
for(i = 0; i < 9; ++i) {
if(board[i] == 0) {
board[i] = 1;
int tempScore = -minimax(board, -1, 0);
board[i] = 0;
if(tempScore > score) {
score = tempScore;
move = i;
}
}
}
//returns a score based on minimax tree at a given node.
board[move] = 1;
drawCpuMove(move);
delay(100);
}
void playerMove(int board[9]) {
int move = 0;
b = 1;
do{
if (myTouch.dataAvailable() == true)
{
myTouch.read();
x = myTouch.getX(); //Get touch point
y = myTouch.getY();
if((x>55 && x<125)&& (y>0 && y<80)) //0
{
if(board[0]==0)
{
move=0;
b=0;
}
}
else if((x>125 && x<195) && (y>0 && y<80)) //1
{
if(board[1]==0)
{
move=1;
b=0;
}
}
else if((x>195&&x<265)&& (y>0 && y<80)) //2
{
if(board[2]==0)
{
move=2;
b=0;
}
}
else if((x>55 && x<125)&& (y>80 && y<155)) //3
{
if(board[3]==0)
{
move=3;
b=0;
}
}
else if((x>125 && x<195)&& (y>80 && y<155)) //4
{
if(board[4]==0)
{
move=4;
b=0;
}
}
else if((x>195&&x<265)&& (y>80 && y<155)) //5
{
if(board[5]==0)
{
move=5;
b=0;
}
}
else if((x>55 && x<125)&& (y>155 && y<235)) //6
{
if(board[6]==0)
{
move=6;
b=0;
}
}
else if((x>125 && x<195)&& (y>155 && y<235)) //7
{
if(board[7]==0)
{
move=7;
b=0;
}
}
else if((x>195&&x<265)&& (y>155 && y<235)) //8
{
if(board[8]==0)
{
move=8;
b=0;
}
}
}
}while(b);
board[move] = -1;
drawPlayerMove(move);
delay(100);
}
int win(const int board[9]) {
//list of possible winning positions
unsigned wins[8][3] = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
int winPos;
for(winPos = 0; winPos < 8; ++winPos) {
if(board[wins[winPos][0]] != 0 && board[wins[winPos][0]] == board[wins[winPos][1]] && board[wins[winPos][0]] == board[wins[winPos][2]])
return board[wins[winPos][2]];
}
return 0;
}
int minimax(int board[9], int player, int depth) {
//check the positions for players
int winner = win(board);
if(winner != 0) return winner*player;
int move = -1;
int score = -2;
int i;
for(i = 0; i < 9; ++i) {
if(board[i] == 0) {
board[i] = player;
int thisScore=0;
if (depth<difficulty){
thisScore = -minimax(board, player*-1,depth+1);
}
if(thisScore > score) {
score = thisScore;
move = i;
}
//choose the worst move for opponent
board[i] = 0;
}
}
if(move == -1) return 0;
return score;
}
void drawCpuMove(int move)
{
switch(move)
{
case 0: drawCircle(55,15); break;
case 1: drawCircle(130,15); break;
case 2: drawCircle(205,15); break;
case 3: drawCircle(55,85); break;
case 4: drawCircle(130,85); break;
case 5: drawCircle(205,85); break;
case 6: drawCircle(55,155); break;
case 7: drawCircle(130,155);break;
case 8: drawCircle(205,155);break;
}
}
void drawPlayerMove(int move)
{
switch(move)
{
case 0: drawX(55,15); break;
case 1: drawX(130,15); break;
case 2: drawX(205,15); break;
case 3: drawX(55,85); break;
case 4: drawX(130,85); break;
case 5: drawX(205,85); break;
case 6: drawX(55,155); break;
case 7: drawX(130,155);break;
case 8: drawX(205,155);break;
}
}
Comments
Please log in or sign up to comment.