Skip to content

Instantly share code, notes, and snippets.

@peterthorsteinson
Last active October 11, 2019 17:48
Show Gist options
  • Save peterthorsteinson/0799f7400178e0bddc130946059dbc24 to your computer and use it in GitHub Desktop.
Save peterthorsteinson/0799f7400178e0bddc130946059dbc24 to your computer and use it in GitHub Desktop.
using System;
namespace TicTacToeHumanVsMachineBruteForce
{
class Program
{
static char[] cells;
static Random rand = new Random();
static void Main()
{
int numberXWins = 0;
int numberOWins = 0;
int numberDraws = 0;
int numberGames = 0;
for (int i = 0; i < 1000; i++) // loop for playing 1000 games
{
numberGames++;
Console.WriteLine("Human is X, Maxchine is O. X goes first.\n");
cells = new char[] { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', };
Display();
int moveCount = 0;
while (true) // loop for playing a single game
{
// comment one and only one of the following two lines of code
//PlayHumanMove(); // real human player
PlayHumanMove(true); // simulate human player with random
moveCount++;
if (DidHumanWin())
{
numberXWins++;
Console.WriteLine("\n**********\nHuman wins!\n**********\n");
break;
}
PlayMachineMove();
moveCount++;
if (DidMachineWin())
{
numberOWins++;
Console.WriteLine("\n**********\nMachine wins!\n**********\n");
break;
}
if (moveCount >= 9) // last move for machine O was already played
{
numberDraws++;
Console.WriteLine("\n**********\nDraw!\n**********\n");
break;
}
}
}
Console.WriteLine("Games played: " + numberGames);
Console.WriteLine("X - Random simulated human wins: " + numberXWins + " -> " + (numberXWins * 100.0) / numberGames + " %");
Console.WriteLine("O - Machine wins: " + numberOWins + " -> " + (numberOWins * 100.0) / numberGames + " %");
Console.WriteLine("Draws: " + numberDraws + " -> " + (numberDraws * 100.0) / numberGames + " %");
}
static void Display()
{
Console.WriteLine();
Console.WriteLine(" " + cells[0] + " | " + cells[1] + " | " + cells[2]);
Console.WriteLine("---+---+---");
Console.WriteLine(" " + cells[3] + " | " + cells[4] + " | " + cells[5]);
Console.WriteLine("---+---+---");
Console.WriteLine(" " + cells[6] + " | " + cells[7] + " | " + cells[8]);
}
static void PlayHumanMove(bool simulateHumanWithRandom = false)
{
if (simulateHumanWithRandom)
{
int randpos;
while (true)
{
randpos = rand.Next(1, 10); // random move in (1, 10]
if (cells[randpos - 1] == ' ') break;
}
cells[randpos - 1] = 'X';
Display();
return;
}
Console.WriteLine("\nPlay X: 1 to 9, 0 to quit.");
int pos;
while (true)
{
if (!(int.TryParse(Console.ReadKey(true).KeyChar.ToString(), out pos)))
{
// human hit a key that is not a digit in 0 -> 9 so try again
Console.Beep();
continue;
}
if (pos == 0)
{
// human hit 0 key so terminate game
Console.WriteLine("\nBye");
Environment.Exit(0);
}
if (cells[pos - 1] != ' ')
{
// human tried to move in cell that is not blank
Console.Beep();
continue;
}
cells[pos - 1] = 'X';
Display();
return;
}
}
static void PlayMachineMove()
{
// center is best initial move so machine should move there right of the bat if possible
if (cells[4] == ' ')
{
cells[4] = 'O';
Display();
return;
}
// capitalize O on 1st row win
if (cells[0] == 'O' && cells[1] == 'O' && cells[2] == ' ')
{
cells[2] = 'O';
Display();
return;
}
if (cells[0] == 'O' && cells[2] == 'O' && cells[1] == ' ')
{
cells[1] = 'O';
Display();
return;
}
if (cells[1] == 'O' && cells[2] == 'O' && cells[0] == ' ')
{
cells[0] = 'O';
Display();
return;
}
// capitalize O on 2nd row win
if (cells[3] == 'O' && cells[4] == 'O' && cells[5] == ' ')
{
cells[5] = 'O';
Display();
return;
}
if (cells[3] == 'O' && cells[5] == 'O' && cells[4] == ' ')
{
cells[4] = 'O';
Display();
return;
}
if (cells[4] == 'O' && cells[5] == 'O' && cells[3] == ' ')
{
cells[3] = 'O';
Display();
return;
}
// capitalize O on 3rd row win
if (cells[6] == 'O' && cells[7] == 'O' && cells[8] == ' ')
{
cells[8] = 'O';
Display();
return;
}
if (cells[6] == 'O' && cells[8] == 'O' && cells[7] == ' ')
{
cells[7] = 'O';
Display();
return;
}
if (cells[7] == 'O' && cells[8] == 'O' && cells[6] == ' ')
{
cells[6] = 'O';
Display();
return;
}
// capitalize O on 1st col win
if (cells[0] == 'O' && cells[3] == 'O' && cells[6] == ' ')
{
cells[6] = 'O';
Display();
return;
}
if (cells[0] == 'O' && cells[6] == 'O' && cells[3] == ' ')
{
cells[3] = 'O';
Display();
return;
}
if (cells[3] == 'O' && cells[6] == 'O' && cells[0] == ' ')
{
cells[0] = 'O';
Display();
return;
}
// capitalize O on 2nd col win
if (cells[1] == 'O' && cells[4] == 'O' && cells[7] == ' ')
{
cells[7] = 'O';
Display();
return;
}
if (cells[1] == 'O' && cells[7] == 'O' && cells[4] == ' ')
{
cells[4] = 'O';
Display();
return;
}
if (cells[4] == 'O' && cells[7] == 'O' && cells[1] == ' ')
{
cells[1] = 'O';
Display();
return;
}
// capitalize O on 3rd col win
if (cells[2] == 'O' && cells[5] == 'O' && cells[8] == ' ')
{
cells[8] = 'O';
Display();
return;
}
if (cells[2] == 'O' && cells[8] == 'O' && cells[5] == ' ')
{
cells[5] = 'O';
Display();
return;
}
if (cells[5] == 'O' && cells[8] == 'O' && cells[2] == ' ')
{
cells[2] = 'O';
Display();
return;
}
// capitalize O on diag \ win
if (cells[0] == 'O' && cells[4] == 'O' && cells[8] == ' ')
{
cells[8] = 'O';
Display();
return;
}
if (cells[0] == 'O' && cells[8] == 'O' && cells[4] == ' ')
{
cells[4] = 'O';
Display();
return;
}
if (cells[4] == 'O' && cells[8] == 'O' && cells[0] == ' ')
{
cells[0] = 'O';
Display();
return;
}
// capitalize O on diag / win
if (cells[2] == 'O' && cells[4] == 'O' && cells[6] == ' ')
{
cells[6] = 'O';
Display();
return;
}
if (cells[2] == 'O' && cells[6] == 'O' && cells[4] == ' ')
{
cells[4] = 'O';
Display();
return;
}
if (cells[4] == 'O' && cells[6] == 'O' && cells[2] == ' ')
{
cells[2] = 'O';
Display();
return;
}
// prevent X from 1st row win
if (cells[0] == 'X' && cells[1] == 'X' && cells[2] == ' ')
{
cells[2] = 'O';
Display();
return;
}
if (cells[0] == 'X' && cells[2] == 'X' && cells[1] == ' ')
{
cells[1] = 'O';
Display();
return;
}
if (cells[1] == 'X' && cells[2] == 'X' && cells[0] == ' ')
{
cells[0] = 'O';
Display();
return;
}
// prevent X from 2nd row win
if (cells[3] == 'X' && cells[4] == 'X' && cells[5] == ' ')
{
cells[5] = 'O';
Display();
return;
}
if (cells[3] == 'X' && cells[5] == 'X' && cells[4] == ' ')
{
cells[4] = 'O';
Display();
return;
}
if (cells[4] == 'X' && cells[5] == 'X' && cells[3] == ' ')
{
cells[3] = 'O';
Display();
return;
}
// prevent X from 3rd row win
if (cells[6] == 'X' && cells[7] == 'X' && cells[8] == ' ')
{
cells[8] = 'O';
Display();
return;
}
if (cells[6] == 'X' && cells[8] == 'X' && cells[7] == ' ')
{
cells[7] = 'O';
Display();
return;
}
if (cells[7] == 'X' && cells[8] == 'X' && cells[6] == ' ')
{
cells[6] = 'O';
Display();
return;
}
// prevent X from 1st col win
if (cells[0] == 'X' && cells[3] == 'X' && cells[6] == ' ')
{
cells[6] = 'O';
Display();
return;
}
if (cells[0] == 'X' && cells[6] == 'X' && cells[3] == ' ')
{
cells[3] = 'O';
Display();
return;
}
if (cells[3] == 'X' && cells[6] == 'X' && cells[0] == ' ')
{
cells[0] = 'O';
Display();
return;
}
// prevent X from 2nd col win
if (cells[1] == 'X' && cells[4] == 'X' && cells[7] == ' ')
{
cells[7] = 'O';
Display();
return;
}
if (cells[1] == 'X' && cells[7] == 'X' && cells[4] == ' ')
{
cells[4] = 'O';
Display();
return;
}
if (cells[4] == 'X' && cells[7] == 'X' && cells[1] == ' ')
{
cells[1] = 'O';
Display();
return;
}
// prevent X from 3rd col win
if (cells[2] == 'X' && cells[5] == 'X' && cells[8] == ' ')
{
cells[8] = 'O';
Display();
return;
}
if (cells[2] == 'X' && cells[8] == 'X' && cells[5] == ' ')
{
cells[5] = 'O';
Display();
return;
}
if (cells[5] == 'X' && cells[8] == 'X' && cells[2] == ' ')
{
cells[2] = 'O';
Display();
return;
}
// prevent X from diag \ win
if (cells[0] == 'X' && cells[4] == 'X' && cells[8] == ' ')
{
cells[8] = 'O';
Display();
return;
}
if (cells[0] == 'X' && cells[8] == 'X' && cells[4] == ' ')
{
cells[4] = 'O';
Display();
return;
}
if (cells[4] == 'X' && cells[8] == 'X' && cells[0] == ' ')
{
cells[0] = 'O';
Display();
return;
}
// prevent X from diag / win
if (cells[2] == 'X' && cells[4] == 'X' && cells[6] == ' ')
{
cells[6] = 'O';
Display();
return;
}
if (cells[2] == 'X' && cells[6] == 'X' && cells[4] == ' ')
{
cells[4] = 'O';
Display();
return;
}
if (cells[4] == 'X' && cells[6] == 'X' && cells[2] == ' ')
{
cells[2] = 'O';
Display();
return;
}
// win is not imminent for either player at this point
if (cells[4] == 'X') // if center cell is human X then take any available corner cell
{
if (cells[0] == ' ')
{
cells[0] = 'O';
Display();
return;
}
if (cells[2] == ' ')
{
cells[2] = 'O';
Display();
return;
}
if (cells[6] == ' ')
{
cells[6] = 'O';
Display();
return;
}
if (cells[8] == ' ')
{
cells[8] = 'O';
Display();
return;
}
}
else // center cell must be machine O so take any available edge cell
{
if (cells[1] == ' ')
{
cells[1] = 'O';
Display();
return;
}
if (cells[3] == ' ')
{
cells[3] = 'O';
Display();
return;
}
if (cells[5] == ' ')
{
cells[5] = 'O';
Display();
return;
}
if (cells[7] == ' ')
{
cells[7] = 'O';
Display();
return;
}
}
// move to any available square
if (cells[0] == ' ')
{
cells[0] = 'O';
Display();
return;
}
if (cells[1] == ' ')
{
cells[1] = 'O';
Display();
return;
}
if (cells[2] == ' ')
{
cells[2] = 'O';
Display();
return;
}
if (cells[3] == ' ')
{
cells[3] = 'O';
Display();
return;
}
if (cells[4] == ' ')
{
cells[4] = 'O';
Display();
return;
}
if (cells[5] == ' ')
{
cells[5] = 'O';
Display();
return;
}
if (cells[6] == ' ')
{
cells[6] = 'O';
Display();
return;
}
if (cells[7] == ' ')
{
cells[7] = 'O';
Display();
return;
}
if (cells[8] == ' ')
{
cells[8] = 'O';
Display();
return;
}
}
static bool DidHumanWin()
{
if ((cells[0] == 'X' && cells[1] == 'X' && cells[2] == 'X') || // row 1
(cells[3] == 'X' && cells[4] == 'X' && cells[5] == 'X') || // row 2
(cells[6] == 'X' && cells[7] == 'X' && cells[8] == 'X') || // row 3
(cells[0] == 'X' && cells[3] == 'X' && cells[6] == 'X') || // col 1
(cells[1] == 'X' && cells[4] == 'X' && cells[7] == 'X') || // col 2
(cells[2] == 'X' && cells[5] == 'X' && cells[8] == 'X') || // col 3
(cells[0] == 'X' && cells[4] == 'X' && cells[8] == 'X') || // diag \
(cells[6] == 'X' && cells[4] == 'X' && cells[2] == 'X')) // diag /
return true;
return false;
}
static bool DidMachineWin()
{
if ((cells[0] == 'O' && cells[1] == 'O' && cells[2] == 'O') || // row 1
(cells[3] == 'O' && cells[4] == 'O' && cells[5] == 'O') || // row 2
(cells[6] == 'O' && cells[7] == 'O' && cells[8] == 'O') || // row 3
(cells[1] == 'O' && cells[4] == 'O' && cells[7] == 'O') || // col 2
(cells[2] == 'O' && cells[5] == 'O' && cells[8] == 'O') || // col 3
(cells[0] == 'O' && cells[4] == 'O' && cells[8] == 'O') || // diag \
(cells[6] == 'O' && cells[4] == 'O' && cells[2] == 'O')) // diag /
return true;
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment