I am trying to get in the habit of practicing coding on daily basis. I decided to try do do tic tac toe in powershell. This took my a rediculous amount of hours to finsh. I am glad to be done. Nest projec will be something more useful like automating some stuff I do at work everyday

# tic tac toe game
# by shane lindberg

#the starting point of available moves
$humanmoves = @()
$computermoves = @()
$whosx = 1
$humanwon = 0
$computerwon = 0
$tie = 0


#pristine new board 
$box0  = "                                  "
$box1  = "          XXX         XXX         "
$box2  = "          XXX         XXX         "
$box3  = "     0    XXX    1    XXX    2    "
$box4  = "          XXX         XXX         "
$box5  = "          XXX         XXX         " 
$box6  = " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$box7  = " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$box8  = "          XXX         XXX         "
$box9  = "          XXX         XXX         "
$box10 = "     3    XXX    4    XXX    5    "
$box11 = "          XXX         XXX         "
$box12 = "          XXX         XXX         " 
$box13 = " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$box14 = " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$box15 = "          XXX         XXX         "
$box16 = "          XXX         XXX         "
$box17 = "     6    XXX    7    XXX    8    "
$box18 = "          XXX         XXX         "
$box19 = "          XXX         XXX         "

#this function writes the billy the puppet to the screen
function write-billy {

    #these are the pixels(spaces) that make up the ascii image
    $billy = ('sb8','sl9','nb8','sb6','sl4','sw5','sl4','nb6','sb5','sl3',
    'sw9','sl3','nb5','sb4','sl3','sw11','sl3','nb4','sb3','sl3','sw3','sr3',
    'sw1','sr3','sw3','sl3','nb3','sb3','sl3','sw2','sl1','sr1','sl1','sr1',
    'sw1','sr1','sl1','sr1','sl1','sw2','sl4','nb2','sb2','sl3','sw4','sr3',
    'sw1','sr3','sw4','sl3','nb2','sb2','sl3','sw1','sr1','sw1','sr1','sw7',
    'sr1','sw1','sr1','sw1','sl3','nb2','sb1','sl5','sw1','sr1','sw9','sr1',
    'sw1','sl5','nb1','sb1','sl7','sw1','sr7','sw1','sl7','nb1','sb2','sl6',
    'sw2','sl1','sw3','sl1','sw2','sl6','nb2','sb3','sl4','sr2','sw1','sl1',
    'sw3','sl1','sw1','sr2','sl4','nb3','sb7','sl1','sr9','sl1','nb7','sb5',
    'sl2','sr2','sl2','sw3','sl2','sr2','sl2','nb5','sb3','sl9','sw1','sl9',
    'nb3','sb2','sl21','nb2','sb1','sl23','nb1')

    foreach ($i in $billy){

        #this part determines how many spaces to print
        $manychars = $i.substring(2)

        #this part detemines the color to print
        switch ($i[1]){
            'b' {$color = 'gray'
            }
            'l' {$color = 'black'
            }
            'r' {$color = 'red'
            }
            default {$color = 'white'
            }
        }

        #this line determines if a -nonewline is nessesary
        $newline = ($i[0] -eq 's')


        #this line does the final write host line
        Write-Host (" "*$manychars) -BackgroundColor $color -NoNewline:$newline   
    }
}

#this function takes a string of words and writes them slowly
#you need to give it to arguments: the string and the delay
function write-slow ($text, $delay){
    $textarray = $text.split(" ")
    foreach ($i in $textarray){
        $final = $i + " " 
        Write-Host $final -NoNewline
        Start-Sleep -Milliseconds $delay
    }
    write-host
}

#this starts the introduction of the game
function introduction{
    clear-host
    write-billy
    Write-Host
    write-slow 'Would you like to play a game?' 125
    Write-Host
    write-slow 'Press enter to fulfill your destiny' 125 
    read-host
}

#this prints the board whenever needed
function print-board {
    $boxarrary = ($box0, $box1, $box2, $box3, $box4, $box5, $box6,
    $box7, $box8, $box9 ,$box10, $box11, $box12, $box13, $box14, $box15, 
    $box16, $box17, $box18, $box19)

    foreach ($i in $boxarrary){ 
        Write-Host $i
    }
}

#this is the fucntion which draws to the board.It needs input as 
#starting with a letter and also include the grid coordinate 
function writexo ( $player,$move ) {
    clear-host
    $letter = $player+$move
    switch ($letter){
        #x  position 0
        ('x0') {$script:box1 =           "  __  __ " + $box1.Substring(9)
                $script:box2 =           "  \ \/ / " + $box2.Substring(9)
                $script:box3 = $box3[0] + "  >  <  " + $box3.Substring(9)
                $script:box4 =           "  /_/\_\ " + $box4.Substring(9)
                $script:box5 =           "         " + $box5.Substring(9)
        }

        #o position 0
        ('o0') {$script:box1 =           "    ___  " + $box1.Substring(9)
                $script:box2 =           "   / _ \ " + $box2.Substring(9)
                $script:box3 = $box3[0] + " | (_) |" + $box3.Substring(9)
                $script:box4 =           "   \___/ " + $box4.Substring(9)
                $script:box5 =           "         " + $box5.Substring(9)
        }

        #x position 3
        ('x3') {$script:box8  =           "  __  __ " + $box8.Substring(9)
                $script:box9  =           "  \ \/ / " + $box9.Substring(9)
                $script:box10 = $box10[0]+ "  >  <  " + $box10.Substring(9)
                $script:box11 =           "  /_/\_\ " + $box11.Substring(9)
                $script:box12 =           "         " + $box12.Substring(9)
        }

        #o position 3
        ('o3'){$script:box8  =           "    ___  " + $box8.Substring(9)
               $script:box9  =           "   / _ \ " + $box9.Substring(9)
               $script:box10 = $box10[0]+ " | (_) |" + $box10.Substring(9)
               $script:box11 =           "   \___/ " + $box11.Substring(9)
               $script:box12 =           "         " + $box12.Substring(9)
        }

        #x position 6
        ('x6'){$script:box15 =           "  __  __ " + $box15.Substring(9)
               $script:box16 =           "  \ \/ / " + $box16.Substring(9)
               $script:box17 = $box17[0] +"  >  <  " + $box17.Substring(9)
               $script:box18 =           "  /_/\_\ " + $box18.Substring(9)
               $script:box19 =           "         " + $box19.Substring(9)}

        #o position 6
        ('o6'){$script:box15 =           "    ___  " + $box15.Substring(9)
               $script:box16 =           "   / _ \ " + $box16.Substring(9)
               $script:box17 = $box17[0] +" | (_) |" + $box17.Substring(9)
               $script:box18 =           "   \___/ " + $box18.Substring(9)
               $script:box19 =           "         " + $box19.Substring(9)
        }

        #x position 1
        ('x1'){$script:box1 = $box1.Substring(0,13) + "  __  __ " + $box1.Substring(22)
               $script:box2 = $box2.Substring(0,13) + "  \ \/ / " + $box2.Substring(22)
               $script:box3 = $box3.Substring(0,13) + "   >  <  " + $box3.Substring(22)
               $script:box4 = $box4.Substring(0,13) + "  /_/\_\ " + $box4.Substring(22)
               $script:box5 = $box5.Substring(0,13) + "         " + $box5.Substring(22)
        } 

        #o position 1
        ('o1'){$script:box1 = $box1.Substring(0,13) + "   ___   " + $box1.Substring(22)
               $script:box2 = $box2.Substring(0,13) + "  / _ \  " + $box2.Substring(22)
               $script:box3 = $box3.Substring(0,13) + " | (_) | " + $box3.Substring(22)
               $script:box4 = $box4.Substring(0,13) + "  \___/  " + $box4.Substring(22)
               $script:box5 = $box5.Substring(0,13) + "         " + $box5.Substring(22)
        }

        #x position 4
        ('x4'){$script:box8  = $box8.Substring(0,13) +  "  __  __ " + $box8.Substring(22)
               $script:box9  = $box9.Substring(0,13) +  "  \ \/ / " + $box9.Substring(22)
               $script:box10 = $box10.Substring(0,13) + "   >  <  " + $box10.Substring(22)
               $script:box11 = $box11.Substring(0,13) + "  /_/\_\ " + $box11.Substring(22)
               $script:box12 = $box12.Substring(0,13) + "         " + $box12.Substring(22)
        }

        #o position 4
        ('o4'){$script:box8  = $box8.Substring(0,13) +  "   ___   " + $box8.Substring(22)
               $script:box9  = $box9.Substring(0,13) +  "  / _ \  " + $box9.Substring(22)
               $script:box10 = $box10.Substring(0,13) + " | (_) | " + $box10.Substring(22)
               $script:box11 = $box11.Substring(0,13) + "  \___/  " + $box11.Substring(22)
               $script:box12 = $box12.Substring(0,13) + "         " + $box12.Substring(22)
        }

        #x position 7
        ('x7'){$script:box15 = $box15.Substring(0,13) + "  __  __ " + $box15.Substring(22)
               $script:box16 = $box16.Substring(0,13) + "  \ \/ / " + $box16.Substring(22)
               $script:box17 = $box17.Substring(0,13) + "   >  <  " + $box17.Substring(22)
               $script:box18 = $box18.Substring(0,13) + "  /_/\_\ " + $box18.Substring(22)
               $script:box19 = $box19.Substring(0,13) + "         " + $box19.Substring(22)
        }

        #o position 7{
        ('o7'){$script:box15 = $box15.Substring(0,13) + "   ___   " + $box15.Substring(22)
               $script:box16 = $box16.Substring(0,13) + "  / _ \  " + $box16.Substring(22)
               $script:box17 = $box17.Substring(0,13) + " | (_) | " + $box17.Substring(22)
               $script:box18 = $box18.Substring(0,13) + "  \___/  " + $box18.Substring(22)
               $script:box19 = $box19.Substring(0,13) + "         " + $box19.Substring(22)
        }

        #x position 2
        ('x2'){$script:box1 = $box1.Substring(0,25) + "  __  __ "
               $script:box2 = $box2.Substring(0,25) + "  \ \/ / "
               $script:box3 = $box3.Substring(0,25) + "   >  <  "
               $script:box4 = $box4.Substring(0,25) + "  /_/\_\ "
               $script:box5 = $box5.Substring(0,25) + "         "
        }          

        #o position 2
        ('o2'){$script:box1 = $box1.Substring(0,25) + "   ___   "
               $script:box2 = $box2.Substring(0,25) + "  / _ \  "
               $script:box3 = $box3.Substring(0,25) + " | (_) | "
               $script:box4 = $box4.Substring(0,25) + "  \___/  "
               $script:box5 = $box5.Substring(0,25) + "         "
        }

        #x position 5
        ('x5'){$script:box8  = $box8.Substring(0,25) +  "  __  __ "
               $script:box9  = $box9.Substring(0,25) +  "  \ \/ / "
               $script:box10 = $box10.Substring(0,25) + "   >  <  "
               $script:box11 = $box11.Substring(0,25) + "  /_/\_\ "
               $script:box12 = $box12.Substring(0,25) + "         "
        }

        #o position 5
        ('o5'){$script:box8  = $box8.Substring(0,25) +  "   ___   "
               $script:box9  = $box9.Substring(0,25) +  "  / _ \  "
               $script:box10 = $box10.Substring(0,25) + " | (_) | "
               $script:box11 = $box11.Substring(0,25) + "  \___/  "
               $script:box12 = $box12.Substring(0,25) + "         "
        }

        #x position 8
        ('x8'){$script:box15 = $box15.Substring(0,25) + "  __  __ "
               $script:box16 = $box16.Substring(0,25) + "  \ \/ / "
               $script:box17 = $box17.Substring(0,25) + "   >  <  "
               $script:box18 = $box18.Substring(0,25) + "  /_/\_\ "
               $script:box19 = $box19.Substring(0,25) + "         "
        }

        #o position 8
        ('o8'){$script:box15 = $box15.Substring(0,25) + "   ___   "
               $script:box16 = $box16.Substring(0,25) + "  / _ \  "
               $script:box17 = $box17.Substring(0,25) + " | (_) | "
               $script:box18 = $box18.Substring(0,25) + "  \___/  "
               $script:box19 = $box19.Substring(0,25) + "         "
        }
    }
}

#this just prints the initial instructions
function introduction2{
    Clear-Host
    write-host "`t`tWelcome to the game of tic tac toe"
    write-host "`t`t--a game of man against machine--`n"
    read-host "`n`npress enter to continue"

}

#this function determines if the player wants to be X's or O's 
#then alters the variable $whosx to set it
function x-or-o {
    $choices = ("first","second")
    do{
        clear-host
        Write-Host "would you like to go first or second?"
        $answer = Read-Host "`nplease type 'first' or 'second' and then press enter"
        clear-host
    }until ($answer -in $choices)

    if ($answer -eq 'first'){
        write-slow "you chose to go first, you will be X's" 125
        $Script:Whosx = 1
        Start-Sleep -Milliseconds 1500
    }
    else {
        write-slow "you chose to go second, you must feel brave to" 125
        write-slow "give the computer the advantage. you will be O's" 125
        $Script:Whosx = 0
        Start-Sleep -Milliseconds 1500
    }
}

#this fucntion gets moves from player
#updates human moves 
#calls writexo to write moves to the board

function human-move {
    if ($whosx -eq 1){
        $player = "x"    
    }
    else {
        $player = 'o'
    }

    do{
        Clear-Host
        print-board
        $move = Read-Host "`nplease enter the move you want corresponding to the number on the board"
    }until (($move -notin ($computermoves + $humanmoves))-and ($move -in ('0','1','2','3','4','5','6','7','8')))
    writexo $player $move
    print-board
    [System.Media.SystemSounds]::Exclamation.Play()
    $Script:humanmoves += $move 
    Start-Sleep -Seconds 2

}

#this function is the ai for the computer 
#updates $computermoves variable
#it also calls writexo
function computer-move {

    $bestmoves = ( 0,8,2,6,4,1,3,7,5 )


    $win = ((0,1,2),(0,4,8),(0,3,6),(2,4,6),(2,5,8),(1,4,7),(3,4,5),(6,7,8))


    if ($whosx -eq 1){
        $player = "o"    
    }
    else {
        $player = "x"
    }


    #this first part checks if the computer can go for a win
    #if the win is possible it returns that data
    foreach ($i in $win){
        $check=@()
        if ($i[0] -in $computermoves){
            $check+=$i[0]
        }
        if ($i[1] -in $computermoves){
            $check+=$i[1]
        }
        if ($i[2] -in $computermoves){
            $check+=$i[2]
        }
        if ($check.count -eq 2){
            foreach ($k in $i){
                if (($k -notin $computermoves) -and ($k -notin $humanmoves)){
                    $Script:computermoves += $k
                    writexo $player $k
                    [System.Media.SystemSounds]::Hand.Play()
                    print-board
                    return
                }
            }
        }
    }
    #the second most important move is to block any wins.
    #this checks for any near wins by the opponent and blocks them

    foreach ($i in $win){
        $check = @()
        if ($i[0] -in $humanmoves){
            $check+=$i[0]
        }
        if ($i[1] -in $humanmoves){
            $check+=$i[1] 
        }
        if ($i[2] -in $humanmoves){
            $check+=$i[2] 
        }
        if ($check.count -eq 2){
            foreach ($k in $i){
                if (($k -notin $humanmoves) -and ($k -notin $computermoves)){
                    $Script:computermoves += $k
                    writexo $player $k
                    [System.Media.SystemSounds]::Hand.Play()
                    print-board
                    return  
                }       
            }
        }
    }
    #if the computer can't win or does not need to block a win it will 
    #pick its best move by starting with the center, then corners, then sides

    if ((($humanmoves + $computermoves).Count -eq 1) -and (0 -in $humanmoves)){
        $k = Get-Random(3,5)
        $Script:computermoves += $k 
        writexo $player $k
        [System.Media.SystemSounds]::Hand.Play()
        print-board
        return
    }
    if ((($humanmoves + $computermoves).Count -eq 1) -and (2 -in $humanmoves)){
        $k = Get-Random(3,5)
        $Script:computermoves += $k 
        writexo $player $k
        [System.Media.SystemSounds]::Hand.Play()
        print-board
        return
    }
    if ((($humanmoves + $computermoves).Count -eq 1) -and (6 -in $humanmoves)){
        $k = Get-Random(1,7)
        $Script:computermoves += $k 
        writexo $player $k
        [System.Media.SystemSounds]::Hand.Play()
        print-board
        return
    }
    if ((($humanmoves + $computermoves).Count -eq 1) -and (8 -in $humanmoves)){
        $k = Get-Random(1,7)
        $Script:computermoves += $k 
        writexo $player $k
        [System.Media.SystemSounds]::Hand.Play()
        print-board
        return
    }

    foreach ($i in $bestmoves){
        if ($i -notin ($computermoves + $humanmoves)){
            $Script:computermoves += $i
            writexo $player $i
            [System.Media.SystemSounds]::Hand.Play()
            print-board
            return
        } 
    }
    start-sleep -Seconds 1
}



    if ($whosx = 1){
        $bestmoves = ( 4,0,2,6,8,1,3,7,5 )
    }
    else {
        $bestmoves = ( 0,8,2,6,4,1,3,7,5 )
    }

    $win = ((0,1,2),(0,4,8),(0,3,6),(2,4,6),(2,5,8),(1,4,7),(3,4,5),(6,7,8))


    if ($whosx -eq 1){
        $player = "o"    
    }
    else {
        $player = "x"
    }




#this determines a win. it needs its input as an array 
#it returns a '1' for a wind and a '0' for no win
function Check-win ($moves) {
    $win = ((0,1,2),(0,4,8),(0,3,6),(2,4,6),(2,5,8),(1,4,7),(3,4,5),(6,7,8))
    $won = 0
    foreach ($a in $win){
        if (($a[0] -in $moves) -and ($a[1] -in $moves) -and ($a[2] -in $moves)){
            return 1
        }
    }
    return 0   
}

introduction
instructions



#this is the main function
do {

    x-or-o
    Clear-Host

    #this sets the bit do let the correct player start and also to 
    #keeps track of who won, loss, and controls game play
    if ($whosx -eq 1){
        $flow = 1
    }
    else{
        $flow = 2
    }

    #this here is where the game loop starts   
    do {
        If ($flow -eq 1){
            human-move
            $flow = 2

            if (($computermoves + $humanmoves).count -eq 9){
                $flow = 3
                $tie++
            }
            if ((Check-win $humanmoves) -eq 1){
                $flow = 4
                $humanwon++
            }
        }
        if ($flow -eq 2){
            computer-move
            $flow = 1
            }
            write-host $whosx
            if ((($computermoves + $humanmoves).count -eq 9) -and ($whosx -eq 0)){
                $flow = 3 
                $tie++   
            }
            if ((Check-win $computermoves) -eq 1){
                 $flow = 5
                 $computerwon++
        }   

    } until ($flow -gt 2)
    #this last part says who won
    clear-host
    print-board

    switch ($flow){
        (4) {
            write-host "`nyou won human. next time you will not be so lucky"
        }
        (5) {
            Write-Host "`nyou lose. it is just a matter of time until the humans serve us"
        }
        (3) {
            write-host "`nit was a tie. maybe we should play again to determine who is better"
        }
    }
    read-host "`npress enter to continue"
    #this last part tallies the wins and losses
    clear-host
    Write-Host "`n`t`tyou won $humanwon game(s)"
    Write-Host "`t`tthe computer won $computerwon game(s)"
    Write-Host "`t`tthere were $tie ties"
    read-host "`npress enter to continue"
    clear-host

    #this asks player if they want to play again or quit

    Write-Host "`n"
    write-slow "would you like to play again?" 125

    do {
        $quit = ""
        $quit = read-host "`npress '1' and enter to play again or press '2' and enter to quit"
    } until ($quit -in ('1','2'))

    if ($quit -eq 1){
        $x = "keep playing"
        #assuming they want to play again we need to reset many variables
        $humanmoves = @()
        $computermoves = @()
        $whosx = 1
        $box0  = "                                  "
        $box1  = "          XXX         XXX         "
        $box2  = "          XXX         XXX         "
        $box3  = "     0    XXX    1    XXX    2    "
        $box4  = "          XXX         XXX         "
        $box5  = "          XXX         XXX         " 
        $box6  = " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
        $box7  = " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
        $box8  = "          XXX         XXX         "
        $box9  = "          XXX         XXX         "
        $box10 = "     3    XXX    4    XXX    5    "
        $box11 = "          XXX         XXX         "
        $box12 = "          XXX         XXX         " 
        $box13 = " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
        $box14 = " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
        $box15 = "          XXX         XXX         "
        $box16 = "          XXX         XXX         "
        $box17 = "     6    XXX    7    XXX    8    "
        $box18 = "          XXX         XXX         "
        $box19 = "          XXX         XXX         "
    }
    else {
        $x = "quit"
    }


}until ($x -eq 'quit')

There is a block of code in lines 440 to 455 that is not part of a function. Is that what you wanted? It is usually best to put all the code outside functions in one block at the beginning or the end, rather than setup between your functions.

What version of PowerShell are you using for this? When I try to run it on PowerShell 2.0, I get errors in that -in and -notin are not recognized operators. -contains and -notcontains are what is in this version, with reversed arguments.

Edited 1 Year Ago by Nutster: Grammar fix.

This article has been dead for over six months. Start a new discussion instead.