If statement is not following its conditional

2019-03-03 23:04发布

In my code to roll you just write r and then hit enter but it seems not to read that and go to else that restarts the while loop. The only way to get it to roll is by typing something else than r than it is a (standard_in) 1: parse error.

#!/bin/bash
#this is a game that is two player and it is a race to get to 
#100 before the other player

echo "Player 1 name?"
read p1
echo "Player 2 name?"
read p2
echo "Okay $p1 and $p2. $p1 will go first"
p1s=0
p2s=0
pt=1
while [ $pt -eq 1 ]; do
echo "roll or stay"
read choice
if [ $choice == r ]; then

die=$(($RANDOM%6+1))

elif [ $die -eq 1 ]; then
p1s=$(echo "$p1s-$count" |bc)
echo "You rolled a 1. Your score is $p1s"
echo "$p2 turn now."
sleep 1
count=0
pt=2

elif [ $die -gt 1 ]; then
p1s=$(echo "$p1s+$die" |bc)
count=$(echo "$count+$die" |bc)
echo "You rolled a $die. Your score is $p1s"
pt=1

else

if [ $choice == s ]; then
echo "Okay $p1 your score is $p1s"
echo "$p2 turn now"
sleep 1
count=0
pt=2

else
if [ $p1s -gt 99 ]; then
echo "$p1 won. $p2 lost"
echo "would you like to play again?"
read again
elif [ $again  yes ]; then
echo "Okay one second."
sleep 1
clear
bash num.sh
elif [ $again == no ]; then
exit

else

pt=1
fi
fi
fi

done

Don't worry about their not being a second while for the second player. I cut that out because it same exact code just for player two.

Sample input/output

Player 1 name?
guy1
Player 2 name?
guy2
Okay guy1 and guy2. guy1 will go first
roll or stay
r
roll or stay
rr
(standard_in) 1: parse error
You rolled a 5. Your score is 5
roll or stay
roll
(standard_in) 1: parse error
You rolled a 5. Your score is 10
roll or stay
s
(standard_in) 1: parse error
You rolled a 5. Your score is 15
roll or stay

标签: bash shell
2条回答
做自己的国王
2楼-- · 2019-03-03 23:17

Okay, a few comments about your code.

  • This is really hard to read because of the lack of indenting. When nesting things, indent what is nested. With indents, you can see where your loops start and end, what code belongs to which if/else, etc.
  • In bash, you should always quote your variables to avoid accidental expansion. For example, what happens if someone enters an asterisk (*) instead of an "r"? Your if statement will do wondrous and mysterious things.
  • You're using operators wrong. In bash, using single square brackets with if, you compare string equivalency with a single equals (=), not double. And if you want numerical equality, you have -eq. Though you might want to look at bash's extended tests, using double square brackets. (Check the man page for details.)
  • Try not to use external tools for things that bash can do by itself. bc, for example, is not needed for integer arithmetic.

So ... all said, here's a code segment of yours, re-written a bit.

while [ "$pt" -eq 1 ]; do

    read -p "Roll or stay (r/s)? " choice

    if [ "$choice" = r ]; then

        die=$(($RANDOM%6+1))

    elif [ "$die" -eq 1 ]; then

        p1s=$((p1s - count))
        echo "You rolled a 1. Your score is $p1s"
        echo "$p2 turn now."
        sleep 1 
        count=0 
        pt=2    

    elif [ $die -gt 1 ]; then

        p1s=$((p1s + die))
        count=$((count + die))
        echo "You rolled a $die. Your score is $p1s"
        pt=1    

    else

Note that I'm not making any claims about whether your program logic is sound.

And what the heck is num.sh? Is it important?

查看更多
Evening l夕情丶
3楼-- · 2019-03-03 23:36

After looking at the properly indented code (see ghoti's rewritten code segment), I see the top level if-block is

if [ $choice == r ]; then
    die=... #roll the die
elif [ $die -eq 1 ]...
elif [ $die -gt 1 ]...
else
    do something...
fi

Problem is, if [ $choice == r ] is true, you will roll the die and skip the rest of elif-else entries. So you will go to the next iteration without doing anything (except for rolling the die)

One way to fix this is to check $choice and $die as separate if blocks, namely

if [ $choice == r ]; then
    #roll the die
else
    #break or something...
fi

if [ $die -eq 1 ]; then
    #do something
elif the rest of $die-related checks  
查看更多
登录 后发表回答