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')