Hi all,
This is my second post. I got some awesome help last time I posted. Thanks.
So for my intro to programming class we had to write a Tic Tac Toe game played against the computer. The computer A.I will just pick randomly until:
1. it's possible to win in one move
2. it's possible to block the user's winning move
3. or continue to pick randomly until one of the above come true
Alright. I got all of this to work just fine. My question to you is:
How would I modify the computerAI() method to work with a larger board?
Basically my A.I does not translate to bigger boards.
I know I can add more &&'s and if statements but that just seems too half ass. I want to be able to just change the constants ROW and COL(declared at the class level) to create a bigger board and have the rest of the code remain unchanged.
Maybe someone has a suggestion on how I could rewrite the computerAI() to be more "portable" or "generic" and less specific to a 3X3 game of Tic Tac Toe.
Hope that makes some sense.
I feel like I'm so close, but I might be missing something very elementary.
BTW I looked into the minimax algorithm a little and it looks daunting to me right now. I do want to take a crack at it once I get this solved.
Thanks for reading.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TicTacToe
{
class Program
{
const int ROWS = 3;
const int COLS = 3;
static void Main(string[] args)
{
string[,] board = new string[ROWS, COLS];/*{{"1","2","3"},
{"4","5","6"},
{"7","8","9"}}*/
setBoard(board);
bool endGame = false;
while (!endGame)
{
playerTurn(board);
endGame = checkForWin(board, "X");
if (endGame)
{
printBoard(board);
Console.WriteLine("You win!");
}
else
{
endGame = checkForTie(board);
if (endGame)
{
printBoard(board);
Console.WriteLine("Tie Game");
}
else
{
endGame = computerTurn(board,"O");
endGame = checkForWin(board, "O");
if (endGame)
{
printBoard(board);
Console.WriteLine("Computer wins");
}
else
{
endGame = checkForTie(board);
if (endGame)
{
printBoard(board);
Console.WriteLine("Tie Game");
}
}
}
}
}
}
static void setBoard(string[,] board)
{
int position = 1;
while (position < ROWS * COLS + 1)
for (int row = 0; row < ROWS; row++)
for (int col = 0; col < COLS; col++)
board[row, col] = Convert.ToString(position++);
}
static void printBoard(string[,] board)
{
Console.Clear();
for (int row = 0; row < ROWS; row++)
{
Console.WriteLine("\n");
for (int col = 0; col < COLS; col++)
{
Console.Write("{0,2}{1,2}", board[row, col], " ");
}
}
Console.WriteLine();
}
static void playerTurn(string[,] board)
{
int pick = 0, row = 0, col = 0;
bool validPick = false;
while (!validPick)
{
try
{
printBoard(board);
Console.WriteLine("\n");
Console.WriteLine("Pick a position # then press Enter");
pick = Convert.ToInt32(Console.ReadLine());
row = (pick - 1) / ROWS;
col = (pick - 1) % COLS;
if (board[row, col] == "X" || board[row, col] == "O")
{
validPick = false;
Console.WriteLine("Position already taken, press enter to pick again");
Console.ReadLine();
}
else
validPick = true;
}
catch (Exception myException)
{
validPick = false;
Console.WriteLine(myException.Message);
Console.WriteLine("Press enter to pick agian");
Console.ReadLine();
}
}
board[row, col] = "X";
}
static bool computerTurn(string[,] board, string mark)
{
bool smartMove = false;
smartMove = computerAI(board,"O");//check for one move win
if (!smartMove)
{
smartMove = computerAI(board, "X");//check for blocking move
}
//If there's no one move win or block move then computer picks randomly
while (!smartMove)
{
Random randNum = new Random();
int pick = 0, row = 0, col = 0;
do
{
pick = randNum.Next(1, ROWS * COLS + 1);
row = (pick - 1) / ROWS;
col = (pick - 1) % COLS;
}
while (board[row, col] == "X" || board[row, col] == "O");
{
board[row, col] = "O";
smartMove = true;
}
}
return smartMove;
}
static bool computerAI(string[,] board, string mark)
{
// computer checks for one move win on first call
//then checks for block move on second call
int row, col;
bool smartMove = false;
if (!smartMove)
{
for (row = 0; row < ROWS; row++)
{
col = 0;
if ((board[row, col] == board[row, col + 1]) && (board[row, col] == mark) &&
(board[row, col + 2] != "X") && (board[row, col + 2] != "O") && smartMove == false)
{
board[row, col + 2] = "O";
smartMove = true;
}
if ((board[row, col + 1] == board[row, col + 2]) && (board[row, col + 1] == mark) &&
(board[row, col] != "X") && (board[row, col] != "O") && (smartMove == false))
{
board[row, col] = "O";
smartMove = true;
}
if ((board[row, col] == board[row, col + 2]) && (board[row, col] == mark) &&
(board[row, col + 1] != "X") && (board[row, col + 1] != "O") && (smartMove == false))
{
board[row, col + 1] = "O"; ;
smartMove = true;
}
}
for (col = 0; col < COLS; col++)
{
row = 0;
if ((board[row, col] == board[row + 1, col]) && (board[row, col] == mark) &&
(board[row + 2, col] != "X") && (board[row + 2, col] != "O") && (smartMove == false))
{
board[row + 2, col] = "O";
smartMove = true;
}
if ((board[row + 1, col] == board[row + 2, col]) && (board[row + 1, col] == mark) &&
(board[row, col] != "X") && (board[row, col] != "O") && (smartMove == false))
{
board[row, col] = "O";
smartMove = true;
}
if ((board[row, col] == board[row + 2, col]) && (board[row, col] == mark) &&
(board[row + 1, col] != "X") && (board[row + 1, col] != "O") && (smartMove == false))
{
board[row + 1, col] = "O";
smartMove = true;
}
}
//first diagonal
row = 0;
col = 0;
if ((board[row, col] == board[row + 1, col + 1]) && (board[row + 1, col + 1] == mark) &&
(board[row + 2, col + 2] != "X") && (board[row + 2 ,col + 2] != "O") && (smartMove == false))
{
board[row + 2, col + 2] = "O";
smartMove = true;
}
if ((board[row + 2, col + 2] == board[row + 1, col + 1]) && (board[row + 1, col + 1] == mark) &&
(board[row, col] != "X") && (board[row, col] != "O") && (smartMove == false))
{
board[row, col] = "O";
smartMove = true;
}
if ((board[row, col] == board[row + 2, col + 2]) && (board[row + 2, col + 2] == mark) &&
(board[row + 1, col + 1] != "X") && (board[row + 1, col + 1] != "O") && (smartMove == false))
{
board[row + 1, col + 1] = "O";
smartMove = true;
}
//second diagonal
if ((board[row + 2, col] == board[row + 1, col + 1]) && (board[row + 1, col + 1] == mark) &&
(board[row, col + 2] != "X") && (board[row, col + 2] != "O") && (smartMove == false))
{
board[row, col + 2] = "O";
smartMove = true;
}
if ((board[row, col + 2] == board[row + 1, col + 1]) && (board[row + 1, col + 1] == mark) &&
(board[row + 2, col] != "X") && (board[row + 2, col] != "O") && (smartMove == false))
{
board[row + 2, col] = "O";
smartMove = true;
}
if ((board[row + 2, col] == board[row,col + 2]) && (board[row, col + 2] == mark) &&
(board[row + 1, col + 1] != "X") && (board[row + 1, col + 1] != "O") && (smartMove == false))
{
board[row + 1, col + 1] = "O";
smartMove = true;
}
}
return smartMove;
}
static bool checkForTie(string[,] board)
{
bool tie = true;
for (int row = 0; row < ROWS; row++)
for (int col = 0; col < COLS; col++)
if (board[row, col] != "X" && board[row, col] != "O")
tie = false;
return tie;
}
static bool checkForWin(string[,] board, string mark)
{
bool win = false;
int row, col;
//check rows for 3 = marks
row = 0;
while (row < ROWS && !win)
{
win = true;
col = 0;
while (col < COLS && win)
{
if (board[row, col] != mark)
win = false;
col++;
}
row++;
}
//check colums for 3 = marks
col = 0;
while (col < COLS && !win)
{
win = true;
row = 0;
while (row < ROWS && win)
{
if (board[row, col] != mark)
{
win = false;
}
row++;
}
col++;
}
if (!win)
{
//check diagonal for 3 = marks
win = true;
row = 0;
while (row < ROWS && win)
{
if (board[row, row] != mark)
{
win = false;
}
row++;
}
}
if (!win)
{
//check other diagonal for 3 = marks
win = true;
row = 0;
while (row < ROWS && win)
{
if (board[row, 2 - row] != mark)
{
win = false;
}
row++;
}
}
return win;
}
}
}