My code:
enum GameStatus{
WIN
ONGOING
DRAW
}
Function Get-StateOfTicTacToe() {
<#
.SYNOPSIS
Implement a program that determines the state of a tic-tac-toe game.
.DESCRIPTION
The games is played on a 3×3 grid represent by an array of 3 strings.
Players take turns to place `X`s and `O`s on the grid.
The game ends:
- when one player has won by placing three of marks in a row, column, or along a diagonal of the grid
- when the entire grid is filled up
In this exercise, we will assume that `X` always starts first.
.PARAMETER Board
An array of 3 strings represeting the board in the form of 3x3 grid.
.EXAMPLE
$board = @(
"XXO",
"X ",
"X "
)
Get-StateOfTicTacToe -Board $board
Returns: [GameStatus]::WIN
#>
[CmdletBinding()]
Param(
[string[]]$Board
)
function CheckTurnOrder {
$xCount = 0
$oCount = 0
foreach ($row in $Board) {
foreach ($char in $row.ToCharArray()) {
if ($char -eq 'X') {
$xCount++
} elseif ($char -eq 'O') {
$oCount++
}
}
}
if ($oCount -gt $xCount) {
throw "Wrong turn order: O started"
}
if ($xCount - $oCount -eq 2) {
throw "Wrong turn order: X went twice"
}
if ($oCount - $xCount -eq 2) {
throw "Wrong turn order: O went twice"
}
}
function CheckWin($Player) {
if ($Player -ne 'X' -and $Player -ne 'O') {
throw "error"
}
# Rows and columns
for ($i = 0; $i -lt 3; $i++) {
if (($Board[$i][0] -eq $Player) -and
($Board[$i][1] -eq $Player) -and
($Board[$i][2] -eq $Player)) {
return $true
}
if (($Board[0][$i] -eq $Player) -and
($Board[1][$i] -eq $Player) -and
($Board[2][$i] -eq $Player)) {
return $true
}
}
# Diagonals
if (($Board[0][0] -eq $Player) -and
($Board[1][1] -eq $Player) -and
($Board[2][2] -eq $Player)) {
return $true
}
if (($Board[0][2] -eq $Player) -and
($Board[1][1] -eq $Player) -and
($Board[2][0] -eq $Player)) {
return $true
}
return $false
}
# Continued playing after win
if (CheckWin('O') -and CheckWin('X')) {
throw "Impossible board: game should have ended after the game was won"
}
CheckTurnOrder
Write-Host "CheckWin('X') = $(CheckWin 'X')"
Write-Host "CheckWin('O') = $(CheckWin 'O')"
Write-Host "CheckWin('O') -or CheckWin('X') = $((CheckWin 'O') -or (CheckWin 'X'))"
Write-Host "CheckWin('X') -or CheckWin('O') = $((CheckWin 'X') -or (CheckWin 'O'))"
if (CheckWin('O') -or CheckWin('X')) {
Write-Host "CASE1"
return [GameStatus]::WIN
}
if (CheckWin('X') -or CheckWin('O')) {
Write-Host "CASE2"
return [GameStatus]::WIN
}
return [GameStatus]::ONGOING
}
$grid = @("XOO",
"X ",
"X ")
$got = Get-StateOfTicTacToe -Board $grid
echo $got
The output:
CheckWin('X') = True
CheckWin('O') = False
CheckWin('O') -or CheckWin('X') = True
CheckWin('X') -or CheckWin('O') = True
CASE2
WIN
(CheckWin 'X') -or (CheckWin 'O')
and (CheckWin 'O') -or (CheckWin 'X')
should be logically equivalent, but why CASE1
is not reached?