#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
unsigned long lastReadMillis = 0;
unsigned long lastReadMillisVal = 0;
unsigned long lastReadMillisBtn = 0;
#define REFRESH_TIME 1000
int8_t player = 0;
int8_t selectedX = 0;
int8_t selectedY = 0;
bool newCordinates = 1;
int8_t winner = -1;
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
int8_t boxes[3][3] /*= {
{1, 0, 0},
{-1, 1, 0},
{1, -1, -1}
}*/;
enum layouts {
GAME,
WIN,
DRAW,
START,
RESTART
};
layouts currentLayout = START;
typedef struct
{
char *label;
int vertPin;
int horzPin;
int selectPin;
int vertVal;
int horzVal;
bool selectState;
} joysticks;
joysticks joystick[] = {
{"Player1", 14, 27, 26, 0, 0, false},
{"Player2", 25, 33, 32, 0, 0, false}
};
void setup(void) {
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
boxes[y][x] = -1;
}
}
u8g2.begin();
u8g2.setFont(u8g2_font_pcsenior_8f);
for (int i = 0; i < (sizeof(joystick) / sizeof(joystick[0])); i++) {
pinMode(joystick[i].selectPin, INPUT_PULLUP);
}
pinMode(26, INPUT);
Serial.begin(115200);
}
void loop(void) {
getJoystickData();
setPosition();
checkButton();
refreshDisplay();
bool drawFlag = 1;
switch (currentLayout) {
case GAME:
for (int playerNum = 0; playerNum <= 1; playerNum++) {
for (int x = 0; x < 3; x++) {
int count = 0;
for (int y = 0; y < 3; y++) {
if (boxes[y][x] == playerNum) {
count++;
if (count == 3) {
winner = playerNum;
currentLayout = WIN;
}
}
}
}
}
for (int playerNum = 0; playerNum <= 1; playerNum++) {
for (int y = 0; y < 3; y++) {
int count = 0;
for (int x = 0; x < 3; x++) {
if (boxes[y][x] == playerNum) {
count++;
if (count == 3) {
winner = playerNum;
currentLayout = WIN;
}
}
}
}
}
for (int playerNum = 0; playerNum <= 1; playerNum++) {
if (boxes[0][0] == playerNum && boxes[1][1] == playerNum && boxes[2][2] == playerNum) {
winner = playerNum;
currentLayout = WIN;
}
if (boxes[0][2] == playerNum && boxes[1][1] == playerNum && boxes[2][0] == playerNum) {
winner = playerNum;
currentLayout = WIN;
}
}
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
if (boxes[y][x] == -1) {
drawFlag = 0;
}
}
}
if (drawFlag) {
currentLayout = DRAW;
}
break;
case WIN:
if (joystick[0].selectState == 0 || joystick[1].selectState == 0) {
currentLayout = RESTART;
}
break;
case DRAW:
if (joystick[0].selectState == 0 || joystick[1].selectState == 0) {
currentLayout = RESTART;
}
break;
case START:
if (joystick[0].selectState == 0 || joystick[1].selectState == 0) {
currentLayout = GAME;
}
break;
case RESTART:
if (joystick[0].selectState == 0 || joystick[1].selectState == 0) {
currentLayout = GAME;
}
break;
}
delay(100);
}
/*void restartGame() {
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
boxes[y][x] = -1;
}
}
}
*/
void checkButton() {
if (joystick[player].selectState == 0 && millis() - lastReadMillisBtn > 100) {
if (boxes[selectedY][selectedX] == -1) {
boxes[selectedY][selectedX] = player;
player = !player;
newCordinates = 1;
lastReadMillisBtn = millis();
}
}
}
void setPosition() {
if (joystick[player].vertVal == 0 && millis() - lastReadMillisVal > 300) {
selectedY++;
if (selectedY > 2) {
selectedY = 0;
}
lastReadMillisVal = millis();
}
if (joystick[player].horzVal == 4095 && millis() - lastReadMillisVal > 300) {
selectedX--;
if (selectedX < 0) {
selectedX = 2;
}
lastReadMillisVal = millis();
}
if (joystick[player].horzVal == 0 && millis() - lastReadMillisVal > 300) {
selectedX++;
if (selectedX > 2) {
selectedX = 0;
}
lastReadMillisVal = millis();
}
if (joystick[player].horzVal == 4095 && millis() - lastReadMillisVal > 300) {
selectedX--;
if (selectedX < 0) {
selectedX = 2;
}
lastReadMillisVal = millis();
}
}
void getJoystickData() {
for (int i = 0; i < (sizeof(joystick) / sizeof(joystick[0])); i++) {
joystick[i].vertVal = analogRead(joystick[i].vertPin);
joystick[i].horzVal = analogRead(joystick[i].horzPin);
joystick[i].selectState = digitalRead(joystick[i].selectPin);
}
}
void refreshDisplay() {
if (millis() - lastReadMillis > REFRESH_TIME ) {
u8g2.firstPage();
do {
switch (currentLayout) {
case GAME:
game_layout();
break;
case WIN:
win_layout();
break;
case DRAW:
draw_layout();
break;
case START:
start_layout();
break;
}
} while (u8g2.nextPage());
lastReadMillis = millis();
}
}
void win_layout() {
u8g2.drawLine(10, 45, 50, 45);
u8g2.drawLine(10, 45, 20, 55);
u8g2.drawLine(10, 45, 20, 35);
u8g2.drawLine(78, 45, 118, 45);
u8g2.drawLine(108, 35, 118, 45);
u8g2.drawLine(108, 55, 118, 45);
u8g2.setFont(u8g2_font_pcsenior_8f);
u8g2.setCursor(20 + (winner * 60), 25);
u8g2.print("WIN");
u8g2.setFont(u8g2_font_pcsenior_8f);
u8g2.setCursor(80 - (winner * 60), 25);
u8g2.print("LOSE");
u8g2.setFont(u8g2_font_chikita_tf);
u8g2.setCursor(10, 60);
u8g2.print("press any key to restart");
}
void start_layout() {
u8g2.setFont(u8g2_font_pcsenior_8f);
u8g2.setCursor(15, 25);
u8g2.print("TIC-TAC GAME");
u8g2.setFont(u8g2_font_chikita_tf);
u8g2.setCursor(15, 50);
u8g2.print("press any key to start");
}
void draw_layout() {
u8g2.setFont(u8g2_font_pcsenior_8f);
u8g2.setCursor(50, 25);
u8g2.print("DRAW");
u8g2.setFont(u8g2_font_chikita_tf);
u8g2.setCursor(10, 50);
u8g2.print("press any key to restart");
}
void game_layout() {
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
switch (boxes[x][y]) {
case 1:
drawCross(y, x);
break;
case 0:
drawCircle(y, x);
break;
case -1:
if (newCordinates) {
selectedX = x;
selectedY = y;
newCordinates = 0;
}
break;
}
}
}
if (player) {
drawLitCross(selectedX, selectedY);
} else {
drawLitCircle(selectedX, selectedY);
}
u8g2.drawLine(50, 2, 50, 61);
u8g2.drawLine(71, 2, 71, 61);
u8g2.drawLine(32, 22, 91, 22);
u8g2.drawLine(32, 42, 91, 42);
u8g2.drawRFrame(31, 1, 61, 61, 3);
}
void drawCross(int column, int row) {
u8g2.drawLine(34 + (20 * column), 5 + (20 * row), 47 + (20 * column), 18 + (20 * row));
u8g2.drawLine(47 + (20 * column), 5 + (20 * row), 34 + (20 * column), 18 + (20 * row));
}
void drawCircle(int column, int row) {
u8g2.drawCircle(41 + (20 * column), 11 + (20 * row), 7, U8G2_DRAW_ALL);
}
void drawLitCross(int column, int row) {
u8g2.drawLine(38 + (20 * column), 9 + (20 * row), 43 + (20 * column), 14 + (20 * row));
u8g2.drawLine(43 + (20 * column), 9 + (20 * row), 38 + (20 * column), 14 + (20 * row));
}
void drawLitCircle(int column, int row) {
u8g2.drawCircle(41 + (20 * column), 11 + (20 * row), 3, U8G2_DRAW_ALL);
}