Proper distribution of cards in terminal based crazy8's game in bash script

When I run the following script at the bottom it say cards remaining=44...It should be=35.
Can anyone tell me what I'm doing wrong. I've spent hours trying to get this to work and I can't go any further until this part works. thank you in advance
Cogiz

#!/bin/bash

# Date="November, 2016"
# Author/Constructor="Steve Sullivan"

###############################
#                             #
#          CRAZY8             #
#                             #
###############################

############# FUNCTIONS ###############

shuffle() #@ USAGE: shuffle
{ #@ TODO: add options for multiple or partial decks
 Deck=$(
   printf "%s\n" {2,3,4,5,6,7,8,9,10,J,Q,K,A}{H,S,D,C} |
    awk '## Seed the random number generator
         BEGIN { srand() }

         ## Put a random number in front of each line
         { printf "%.0f\t%s\n", rand() * 99999, $0 }
    ' |
     sort -n |  ## Sort the lines numerically
      cut -f2  ## Remove the random numbers
  )
}

_deal() #@ USAGE: _deal [N] -- where N is no. of cards; defaults to 1
{       #@ RESULT: stored in $_DEAL
    local num=${1:-1}
    set -- $Deck
    _DEAL=${@:1:$num}
    shift "$num"
    cards_remaining=$#
    Deck=$*
}

deal() #@ USAGE: deal [N]
{     
    _deal "$@"
    echo $_DEAL 
}

_computerdeal() #@ USAGE: _deal [N] -- where N is no. of cards; defaults to 1
{       #@ RESULT: stored in $_COMPUTERDEAL
    local num=${1:-1}
    set -- $Deck
    _COMPUTERDEAL=${@:1:$num}
    shift "$num"
    cards_remaining=$#
    Deck=$*
}

computerdeal() #@ USAGE: deal [N]
{      
    _computerdeal "$@"
    echo $_COMPUTERDEAL | tee /home/cogiz/computerhand.txt
}

randomchoicecomputer() {
echo $RANDOM % 2 + 1 | bc > /home/cogiz/choice.txt 2>&1
}

randomchoiceplayer() {
FD=$(</home/cogiz/choice.txt)
echo
echo
echo "       $name, the computer has secretly chosen between numbers 1 and 2."
echo
echo "       If you choose the same number then you will play first."
echo
echo "       If you choose the wrong number then the computer will play first."
echo
echo "       The computer has chosen: $FD" | sed -r 's/[12]+/*/g'
echo
read -p "       Please choose either 1 or 2: " nbr
echo
if [ "$nbr" -eq "$FD" ]; then
   echo "       $name has chosen: $nbr"
   echo
   echo "       $name, you guessed right, you will play first."
   sleep 3
   echo
else
   echo "       The computer has chosen $FD"
   echo
   echo "       You guessed wrong, the computer will play first."
   sleep 3
   echo
fi 
}

############### MAIN SCRIPT #################

clear
echo
read -p "       What is your Name?: " name
clear
echo
echo "          Hello $name,"
echo
echo "          Let's play some Crazy 8's ..."
sleep 2
clear
randomchoicecomputer
randomchoiceplayer
echo
clear
echo
echo "       Shuffling cards ..."
sleep 2
clear
shuffle
echo
echo "       Dealing hands ..."
sleep 2
clear
tput cup 2 10
echo "     $name's hand: "
echo
tput cup 4 10
deal 8
echo
echo
echo
tput cup 2 40
echo "     The computer's hand: "
echo
tput cup 4 40; 
computerdeal 8 | sed -r 's/[0123456789JQKAHSDC]+/ * /g'
echo
echo
rm /home/cogiz/choice.txt

echo "          The Card in Play is: "$(deal) | tee /home/cogiz/cardinplay.txt
tput cup 24 0
echo "cards remaining="$cards_remaining

The problem is in the two following lines:

computerdeal 8 | sed -r 's/[0123456789JQKAHSDC]+/ * /g'

and

echo "          The Card in Play is: "$(deal) | tee /home/cogiz/cardinplay.txt

In both cases the deal and computerdeal function are executed in a subshell, in the first case as the left hand side of a pipe, in the second case as part of a command substitution. The global variables that are set inside those functions are local to that subshell. When the subshell finishes, those variables and their values will be lost...

By contrast the first time the deal function is called:

deal 8

it is done in the current shell itself and the value of global variable cards_remaining that gets set inside that function is the value that gets printed at the end..

So instead you could run those functions in the current shell and then use the global variables that are being set inside them...

1 Like

Thank you very much for your very helpful suggestion. I have solved that particular problem by adjusting my script as follows:

#!/bin/bash

# Date="November, 2016"
# Author/Constructor="Steve Sullivan"

###############################
#                             #
#          CRAZY8             #
#                             #
###############################

############# FUNCTIONS ###############

shuffle() #@ USAGE: shuffle
{ #@ TODO: add options for multiple or partial decks
 Deck=$(
   printf "%s\n" {2,3,4,5,6,7,8,9,10,J,Q,K,A}{H,S,D,C} |
    awk '## Seed the random number generator
         BEGIN { srand() }

         ## Put a random number in front of each line
         { printf "%.0f\t%s\n", rand() * 99999, $0 }
    ' |
     sort -n |  ## Sort the lines numerically
      cut -f2  ## Remove the random numbers
  )
}

_deal() #@ USAGE: _deal [N] -- where N is no. of cards; defaults to 1
{       #@ RESULT: stored in $_DEAL
    local num=${1:-1}
    set -- $Deck
    _DEAL=${@:1:$num}
    shift "$num"
    cards_remaining=$#
    Deck=$*
}

deal() #@ USAGE: deal [N]
{     
    _deal "$@"
    echo $_DEAL 
}

randomchoicecomputer() {
echo $RANDOM % 2 + 1 | bc > /home/cogiz/choice.txt 2>&1
}

randomchoiceplayer() {
FD=$(</home/cogiz/choice.txt)
echo
echo
echo "       $name, the computer has secretly chosen between numbers 1 and 2."
echo
echo "       If you choose the same number then you will play first."
echo
echo "       If you choose the wrong number then the computer will play first."
echo
echo "       The computer has chosen: $FD" | sed -r 's/[12]+/*/g'
echo
read -p "       Please choose either 1 or 2: " nbr
echo
if [ "$nbr" -eq "$FD" ]; then
   echo "       $name has chosen: $nbr"
   echo
   echo "       $name, you guessed right, you will play first."
   sleep 3
   echo
else
   echo "       The computer has chosen $FD"
   echo
   echo "       You guessed wrong, the computer will play first."
   sleep 3
   echo
fi 
}

############### MAIN SCRIPT #################

# This section decides which player will play first

clear
echo
read -p "       What is your Name?: " name
clear
echo
echo "          Hello $name,"
echo
echo "          Let's play some Crazy 8's ..."
sleep 2
clear
randomchoicecomputer
randomchoiceplayer
echo
clear
echo
echo "       Shuffling cards ..."
sleep 2
clear
shuffle
echo
echo "       Dealing hands ..."
sleep 2
clear

# This is the actual dealing of hands

tput cup 2 9
echo "     $name's hand: "
echo
tput cup 4 9
deal 8
echo
echo
echo
tput cup 2 40
echo "     The computer's hand: "
echo

deal 8 > /home/cogiz/computerhand.txt 
CH=()
computerhand=$(</home/cogiz/computerhand.txt)
for i in computerhand; do
   CH+=${computerhand
[*]}
done
tput cup 4 40
echo $CH | sed -r 's/[0123456789JQKAHSDC]+/ * /g'

rm /home/cogiz/choice.txt

deal 1 > /home/cogiz/topcardinplay.txt 
TCIP=()
card=$(</home/cogiz/topcardinplay.txt)
for i in card; do
   TCIP+=${card
[*]}
done
tput cup 8 36
echo $TCIP
tput cup 10 22
echo "     The Top Card in Play"

# Running total of cards remaining in the Deck

tput cup 24 0
echo "cards remaining="$cards_remaining