#include <Keypad.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
const int rows = 3;
const int cols = 3;
bool gameOver = false;
bool player1Turn = true;
char field[rows][cols];
Adafruit_SSD1306 lcd(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
const byte ROWS = 4;
const byte COLS = 3;
char keys[ROWS][COLS] = {
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'},
{'*', '0', '#'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
void setup() {
lcd.begin(SSD1306_SWITCHCAPVCC, 0x3C);
lcd.setTextColor(SSD1306_WHITE);
lcd.clearDisplay();
makeField();
}
void loop() {
char key = keypad.getKey();
if (key) {
inputSym(key);
}
showField();
if (!gameOver) {
showField();
}
}
void makeField() {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
field[i][j] = ' ';
}
}
gameOver = false;
player1Turn = true;
}
void showField() {
lcd.clearDisplay();
int startX = 0;
int startY = 0;
int cellWidth = 20;
int cellHeight = 20;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int x = startX + j * cellWidth;
int y = startY + i * cellHeight;
lcd.setCursor(x, y);
lcd.print(field[i][j]);
}
}
if (gameOver) {
lcd.setCursor(0, 0);
lcd.setTextSize(1);
if (checkDraw()) {
lcd.clearDisplay();
lcd.println("It's a draw!");
} else {
lcd.clearDisplay();
lcd.print(player1Turn ? "X" : "0");
lcd.print("-player");
lcd.println(" wins!");
}
lcd.print("Press '0' to reset");
}
lcd.display();
lcd.setCursor(0, rows * cellHeight + 5);
lcd.print("Press '0' to reset");
lcd.display();
}
void inputSym(char key) {
if (gameOver && key == '0') {
makeField();
return;
}
int num = key - '0';
if (num >= 1 && num <= 9) {
int row, col;
switch (num) {
case 1: row = 0; col = 0; break;
case 2: row = 0; col = 1; break;
case 3: row = 0; col = 2; break;
case 4: row = 1; col = 0; break;
case 5: row = 1; col = 1; break;
case 6: row = 1; col = 2; break;
case 7: row = 2; col = 0; break;
case 8: row = 2; col = 1; break;
case 9: row = 2; col = 2; break;
}
placeSym(row, col);
}
}
void placeSym(int row, int col) {
if (field[row][col] != ' ') {
return;
}
field[row][col] = player1Turn ? 'X' : 'O';
if (checkWin()) {
gameOver = true;
lcd.clearDisplay();
lcd.setCursor(0, 0);
lcd.setTextSize(1);
lcd.print("Player ");
lcd.print(player1Turn ? "1" : "2");
lcd.println(" wins!");
lcd.println("Press '0' to reset");
lcd.display();
return;
} else if (checkDraw()) {
gameOver = true;
lcd.clearDisplay();
lcd.setCursor(0, 0);
lcd.println("It's a draw!");
lcd.println("Press '0' to reset");
lcd.display();
return;
}
player1Turn = !player1Turn;
}
bool checkWin() {
for (int i = 0; i < rows; i++) {
if (field[i][0] != ' ' && field[i][1] == field[i][0] && field[i][2] == field[i][0]) {
return true;
}
if (field[0][i] != ' ' && field[1][i] == field[0][i] && field[2][i] == field[0][i]) {
return true;
}
}
if (field[0][0] != ' ' && field[1][1] == field[0][0] && field[2][2] == field[0][0]) {
return true;
}
if (field[0][2] != ' ' && field[1][1] == field[0][2] && field[2][0] == field[0][2]) {
return true;
}
return false;
}
bool checkDraw() {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (field[i][j] == ' ') {
return false;
}
}
}
return true;
}