Go Fish/PowerShell

From Rosetta Code
Go Fish/PowerShell is part of Go Fish. You may find other members of Go Fish at Category:Go Fish.

My attempt at a user-friendly Go-Fish. When I wrote the PowerShell playing cards as a pre-requisite to this code I didn't understand classes that well. I ended up using a LOT of functions and global variables in that code. When I tried to use it as the base for the Go-Fish game it was gross, unorganized and I felt like I needed a much larger/over-arching parent function... Enter my path to learning the amazing use of classes in PS, simply type GoFish after running this code and you'll be on your way. Tip: Try lying to Bill about whether or not you have a card he asks for.

Class GoFish
{

    [bool]$Part1 = $true
    [bool]$Part2 = $true
    [bool]$IsPlayerTurn = $true
    [bool]$Lies = $false

    $Deck
    
    [Array]$PlayerHand
    [Array]$BillHand

    [int]$PlayerBook
    [int]$BillBook
    [int]$SwitchCounter

    [array]$Pip = @('Ace', 'King', 'Queen',  'Jack', '10', '9', '8', '7', '6', '5', '4', '3', '2')


    GoFish(){}

    [void]CreateDeck()
    {

        [array]$Suit = @(' of Hearts', ' of Spades', ' of Diamonds', ' of Clubs')

        [int]$SuitCounter = 0
        [int]$PipCounter = 0
        [int]$CardValue = 0
        
        $TempDeck = [ordered]@{}
        
        do
        {
            $Card2Add = ($this.Pip[$PipCounter]+$Suit[$SuitCounter])
            $TempDeck.Add($CardValue, $Card2Add)
            $CardValue++
            $PipCounter ++
                if ($PipCounter -eq 13)
                {
                    $SuitCounter++
                    $PipCounter = 0
                }
                else
                {
                    continue
                }
        }
        #52 cards in a deck
        until ($TempDeck.Count -eq 52)

        $this.Deck = (($TempDeck.GetEnumerator() | Get-Random -Count ([int]::MaxValue)))
        }

    [array]DrawFromDeck([string]$Hand, [int]$Quanity) #To be moved to void in final ver code: 004
    {
        [array]$CardsToAdd = $this.Deck[0..(($Quanity -1))]

        $this.Deck = $this.Deck[$Quanity..($this.Deck.Count)]

        return $this.($Hand) = ($this.($Hand) + $CardsToAdd)
    }

    [String]CheckBook([String]$Hand)
    {
        $Checking =@()
        $ToRemove = $null
        $ToPrint = $false


        foreach ($Card in $this.($hand).value)
        {
            $card = $Card.Split(" ",2)[0]
            $Checking = $Checking + $Card
        }
        

        $Checking = $Checking | Group-Object

        foreach ($i in $Checking)
        {
            $test = ($i | select -ExpandProperty count)
            if ($test -eq 4)
            {
                $ToRemove = $i.name
            }
        }

        foreach ($Card2 in $this.($hand).value)
        {
            $Card3 = $Card2.Split(" ",2)[0]

            if ($Card3 -eq $ToRemove)
            {
                $this.($hand) = $this.($hand) | ? {$_.value -ne $Card2}
                $ToPrint = $true
            }
        }

        if ($ToPrint)
        {
            if ($Hand -eq 'PlayerHand')
            {
                $this.PlayerBook++
                return Read-Host("You made a book of $ToRemove"+"'s"+", a point was added to your score.`nYou dis-carded the book from your hand.`nPress ENTER to continue")
            }
            if ($Hand -eq 'BillHand')
            {
                $this.BillBook++
                return Read-Host("Bill made a book of $ToRemove"+"'s"+", a point was added to his score.`nHe dis-carded the book from his hand.`nPress ENTER to continue")
            }
        }

            return "else"
    }

    [String]Zeroed([string]$Hand)
    {
        if($this.($hand).Count -eq 0)
        {
            if($this.Deck.count -gt 0)
            {
                if($Hand -eq 'PlayerHand')
                {
                    $this.DrawFromDeck('PlayerHand', 1)
                    return Read-Host("You ran out of cards.`nPress ENTER to draw a card`n")
                }
                else
                {
                    $this.DrawFromDeck('BillHand', 1)
                    return Read-Host("Bill ran out of cards, he drew one cards from the deck.`nPress ENTER to continue`n")
                }
            }
            else
            {
                if($Hand -eq 'PlayerHand')
                {
                    return Read-Host("You ran out of cards and there are none left in the deck.`nPress ENTER to continue`n")
                    $this.Part1 = $false
                }
                else
                {
                    return Read-Host("Bill ran out of cards and there are none left in the deck.`nPress ENTER to continue`n")
                    $this.Part2 = $false
                }
            }
        }

        return $hand + $this.($hand).count
    }

    [void]StatusCheck()
    {
        
        $this.CheckBook('PlayerHand')
        $this.CheckBook('BillHand')
        $this.Zeroed('PlayerHand')
        $this.Zeroed('BillHand')

    }
    
    [void]AskBill()
    {

        $selections =@()
        $Continue = $true
        $Hascard = $false
        $asked = $null
        $askedS = $null

        $HowManyCardsGiven = 0

        foreach ($Card in $this.PlayerHand.value)
        {
            $card = $card.Split(" ",2)[0]
            $selections += $card
        }

        $Card = $null
        
        do
        {
            foreach ($i in ($selections | sort -Unique))
            {
                Write-Host $i
            }

            Write-Host ""
            $asked = Read-Host("What do you want to ask Bill for?  Enter your selection exactly as listed`n")


            if ($selections -contains($asked))
            {
                Write-Host ("You asked Bill if he had any "+$asked+"'s.")
                
                $Continue = $false
            }
            Else
            {
                $Example = $selections | Get-Random
                Write-host "Please choose what to ask for from the list below, $Example would work."
                write-host ""
            }
        }
        until($Continue -ne $true)

        foreach($Card in  $This.BillHand.value)
        {
            $CardFormated = $Card.Split(" ",2)[0]
            if ($CardFormated -contains($asked))
            {
                $CardToRemove = $CardFormated.name

                $this.PlayerHand = ($this.PlayerHand + ($this.BillHand | ? {$_.value -eq $Card}))
                $this.BillHand = $this.BillHand | ? {$_.value -ne $Card}
                $HowManyCardsGiven++
                $Hascard = $true
            }
        }

        if ($Hascard)
        {
            $this.IsPlayerTurn = $true
            if ($HowManyCardsGiven -gt 1)
            {
                $askedS = ($asked.ToString())+"'s."

            }
            else
            {
                 $askedS = ($asked.ToString())+"."
            }

            Write-host ("Bill gave you "+$HowManyCardsGiven+" "+ $askedS)
            Read-Host "You get another turn, Press Enter to continue"
        }

        else
        {
            $this.IsPlayerTurn = $false
            Write-Host ("Bill didn't have any $asked" + "'s" + ", GO-FISH!")

            if ($this.Deck.Count -gt 0)
            {
                $this.DrawFromDeck('Playerhand', 1)
                Read-Host "You drew one card and now it's Bill's turn, Press ENTER to continue"
            }
            Else
            {
                Read-Host "There are no more cards in the deck, it is Bills's turn, Press ENTER to continue"
            }

            
           
        }
    }
    [void]BillAskPlayer()
    {
        $selections =@()
        $selected = $null
        $thigs = @()
        $counter = $null
        $Hascard = $false

        if($this.Lies -eq $false)
        {
            foreach ($card in $this.BillHand.value)
            {
                $card = $card.Split(" ",2)[0]
                $selections += $card
            }

            foreach ($i in ($selections | Group-Object))
            {
                $thigs += $i
            }
        }
        else
        {
            foreach ($card in $this.PlayerHand.value)
            {
                $card = $card.Split(" ",2)[0]
                $selections += $card
            }

            foreach ($i in ($selections | Group-Object))
            {
                $thigs += $i
            }
        }

        $temp = $thigs | sort -Property count -Descending | select -ExpandProperty values

        Switch ($This.SwitchCounter) {
          '0' { $selected = $temp[$This.switchcounter]
                $This.switchcounter++ }

          '1' { $selected = $temp[$This.switchcounter]
                $This.switchcounter++ }

          '2' { $selected = $temp[$This.switchcounter]
                $This.switchcounter++}

          '3' { $selected = $temp | Get-Random
                $this.switchcounter = 0}

          default { $selected = $temp[0]
                $This.switchcounter = 0 }

                }

                if ($this.pip -cnotcontains($selected)) 
                {
                    $selected = ($this.BillHand.value.split(" ",2)[0])
                    $this.SwitchCounter = 0
                    #Write-host "selected was null"
                }

        $lies? = Read-Host "Bill asked you if you have any $selected's, do you?  Enter y/n"

        foreach($test in  $this.PlayerHand.value)
        {
            $test2 = $test.Split(" ",2)[0]
            if ($test2 -contains($selected))
            {
                $ToRemove = $test.name

                $temp3 = ($this.PlayerHand | ? {$_.value -eq $test})
                $this.BillHand += $temp3
                $this.PlayerHand = $this.PlayerHand | ? {$_.value -ne $test}
                $counter++
                $Hascard = $true
            }
        }
        if ($Hascard)
        {
            if ($counter -gt 1)
            {
                $askedS = ($selected.ToString())+"'s"
            }
            else
            {
                 $askedS = ($selected.ToString())+""
            }

            if ($lies? -match('n') -or $lies? -match('no'))
            {
                Write-Host "LIES!!!! Bill would never lie ot you.`nBecause you lied now Bill is going to cheat!"
                $this.Lies = $true
            }

            $this.IsPlayerTurn = $false
            Write-host "You gave Bill $counter $askedS." -ForegroundColor red
            Read-Host "Bill gets another turn, Press Enter to continue"
        }
        else
        {
            $this.IsPlayerTurn = $true
            Write-Host "You didn't have any $selected's for Bill, he went FISHING!"
            if ($this.Deck.count -gt 0)

            {
                $this.DrawFromDeck('BillHand', 1)
                Read-Host "Bill drew one card and now it's your turn, Press enter to continue"
            }
            Else
            {
                Read-Host "There are no more cards in the deck, it is now your turn, press enter to continue"
            }
        }
    }
}

function GUI()
{
    Clear-Host

    $counter2 = 0
    $ShowPlayerCards = @()
    $temp=$null
        
    foreach ($card in ($icards.PlayerHand.Value | sort))
    {
        if($counter2 -eq 0)
        {
            $counter2++
            $temp = $card[0]
            $ShowPlayerCards += $card
            continue
        }
        elseif($temp -eq $card[0])
        {          
            $temp = $card[0] 
        }
        else
        {
            $temp = $card[0]
            $ShowPlayerCards += '--'               
        }

        $ShowPlayerCards += $card
    }

    $cards = 0
        
    foreach ($i in $ShowPlayerCards)
    {
        if ($i[0] -ne '-')
        {
            $cards++
        }
    }

    Write-output "===================== Go Fish ======================"
    Write-output "        Welcome, you will be playing against  "
    Write-output " Bill the AI.  To win you must have the most 'Books'"
    Write-output "        (sets of 4) by the end of the deck."
    Write-output "                     Have fun!"
    Write-output "================== Your Hand ($cards) ==================="
    $ShowPlayerCards
    Write-output "====================================================="
    Write-host "Your books = " $icards.PlayerBook "     Bill's Books = " $icards.BillBook
    Write-output ""
    Write-host "Cards in deck = "$icards.Deck.count
    Write-output ""
    Write-Host ""

}

function GoFish
{
    $iCards = [GoFish]::new()
    $iCards.CreateDeck()

    do
    {
        $iCards.DrawFromDeck('PlayerHand', 1)
        $iCards.DrawFromDeck('BillHand',1)
    }
    until($iCards.BillHand.Count -eq 9)

    while (($iCards.PlayerBook + $iCards.BillBook) -lt 13)
    {
        if ($iCards.isplayerturn)
        {
            gui
            $iCards.StatusCheck()
            $iCards.AskBill()
            $iCards.StatusCheck()
            continue
        }
        else
        {
            gui
            $iCards.StatusCheck()
            gui
            $iCards.BillAskPlayer()
            $iCards.StatusCheck()
            continue
        }
    }
    Write-Host "end of game"

    if ($iCards.playerbook -gt $iCards.BillBook)
    {
        Write-Host "YOU WON!"
    }
    else
    {
        Write-Host "Bill WON!"
    }

}