Skip to content

Commit

Permalink
Ported minimax Tic Tac Toe to Processing
Browse files Browse the repository at this point in the history
  • Loading branch information
spencerstith committed Aug 26, 2021
1 parent 03d4b0f commit b12e3b9
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Tic Tac Toe AI with Minimax Algorithm
// The Coding Train / Daniel Shiffman
// https://thecodingtrain.com/CodingChallenges/154-tic-tac-toe-minimax.html
// https://youtu.be/I64-UTORVfU
// https://editor.p5js.org/codingtrain/sketches/0zyUhZdJD
// Ported to Processing4 by Spencer Stith <github.com/spencerstith>

char[][] board = {
{(char)0, (char)0, (char)0},
{(char)0, (char)0, (char)0},
{(char)0, (char)0, (char)0}
};

int w; // = width / 3;
int h; // = height / 3;

char ai = 'X';
char human = 'O';
boolean currentPlayerIsHuman = true;

HashMap<Character, Integer> scores;

void setup() {
size(400, 400);
w = width / 3;
h = height / 3;

scores = new HashMap<Character, Integer>();
scores.put('X', 10);
scores.put('O', -10);
scores.put('t', 0);

bestMove(); //<>//
}

boolean equals3(char a, char b, char c) {
return a == b && b == c && a != (char)0;
}

char checkWinner() {
// Must use 'n' for "null" since Java doesn't allow primitive data types to be null
char winner = 'n';

// horizontal
for (int i = 0; i < 3; i++) {
if (equals3(board[i][0], board[i][1], board[i][2])) {
winner = board[i][0];
}
}

// Vertical
for (int i = 0; i < 3; i++) {
if (equals3(board[0][i], board[1][i], board[2][i])) {
winner = board[0][i];
}
}

// Diagonal
if (equals3(board[0][0], board[1][1], board[2][2])) {
winner = board[0][0];
}
if (equals3(board[2][0], board[1][1], board[0][2])) {
winner = board[2][0];
}

int openSpots = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == (char)0) {
openSpots++;
}
}
}

if (winner == 'n' && openSpots == 0) {
return 't';
} else {
return winner;
}
}

void mousePressed() {
if (currentPlayerIsHuman) {
// Human make turn
int i = floor(mouseX / w);
int j = floor(mouseY / h);
// If valid turn
if (board[i][j] == (char)0) {
board[i][j] = human;
currentPlayerIsHuman = false;
bestMove();
}
}
}

void draw() {
background(255);
strokeWeight(4);

line(w, 0, w, height);
line(w * 2, 0, w * 2, height);
line(0, h, width, h);
line(0, h * 2, width, h * 2);

for (int j = 0; j < 3; j++) {
for (int i = 0; i < 3; i++) {
int x = w * i + w / 2;
int y = h * j + h / 2;
char spot = board[i][j];
textSize(32);
int r = w / 4;
if (spot == human) {
noFill();
circle(x, y, r * 2);
} else if (spot == ai) {
line(x - r, y - r, x + r, y + r);
line(x + r, y - r, x - r, y + r);
}
}
}

char result = checkWinner();
if (result != 'n') {
noLoop();
textAlign(CENTER, CENTER);
rectMode(CENTER);
fill(255);
rect(width / 2, height / 3, 200, 100);
fill(0);
if (result == 't') {
text("Tie!", width / 2, height / 3);
} else {
text(result + " wins!", width / 2, height / 3);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Tic Tac Toe AI with Minimax Algorithm
// The Coding Train / Daniel Shiffman
// https://thecodingtrain.com/CodingChallenges/154-tic-tac-toe-minimax.html
// https://youtu.be/I64-UTORVfU
// https://editor.p5js.org/codingtrain/sketches/0zyUhZdJD
// Ported to Processing4 by Spencer Stith <github.com/spencerstith>


import java.util.HashMap;

void bestMove() {
// AI to make its turn
int bestScore = Integer.MIN_VALUE;
int[] move = {0, 0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
// Is the spot available?
if (board[i][j] == (char)0) {
board[i][j] = ai;
int score = minimax(board, 0, false);
board[i][j] = (char)0;
if (score > bestScore) {
bestScore = score;
move[0] = i;
move[1] = j;
}
}
}
}
board[move[0]][move[1]] = ai;
currentPlayerIsHuman = true;
}

int minimax(char[][] board, int depth, boolean isMaximizing) {
char result = checkWinner();
if (result != 'n') {
return scores.get(result);
}

if (isMaximizing) {
int bestScore = Integer.MIN_VALUE;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
// Is the spot available?
if (board[i][j] == (char)0) {
board[i][j] = ai;
int score = minimax(board, depth + 1, false);
board[i][j] = (char)0;
bestScore = max(score, bestScore);
}
}
}
return bestScore;
} else {
int bestScore = Integer.MAX_VALUE;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
// Is the spot available?
if (board[i][j] == (char)0) {
board[i][j] = human;
int score = minimax(board, depth + 1, true);
board[i][j] = (char)0;
bestScore = min(score, bestScore);
}
}
}
return bestScore;
}
}

0 comments on commit b12e3b9

Please sign in to comment.