LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 08-16-2013, 09:19 PM   #1
Lucien Lachance
Member
 
Registered: May 2013
Posts: 82

Rep: Reputation: Disabled
Bash Random Keys


I've declared an associative array in bash and I need to be able to assign a random key to a variable called opponent. In Python, I can do this like so:
Code:
# /usr/bin/env python

 moves = [('r', "rock"), ('p', "paper"), ('s', "scissor")]

opponent = random.choice(moves)[0]
How can I accomplish this with bash?
 
Old 08-17-2013, 12:33 AM   #2
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,153

Rep: Reputation: 331Reputation: 331Reputation: 331Reputation: 331
Note the use of the ${!<var_name>} in the code below
Code:
#!/bin/bash
random_move()
{
  local -i k=$(shuf -i 1-$# -n 1)
  echo ${!k}
}
####
declare -A moves
moves=(['r']="rock" ['p']="paper" ['s']="scissors")
for ((i=0;i<10;++i))
do
  key=$(random_move ${!moves[@]})
  echo key=${key}
  echo "move ${i} = ${moves[${key}]}"
done
Which produces
Code:
$ ./lucian 
key=p
move 0 = paper
key=s
move 1 = scissors
key=r
move 2 = rock
key=s
move 3 = scissors
key=s
move 4 = scissors
key=s
move 5 = scissors
key=p
move 6 = paper
key=p
move 7 = paper
key=p
move 8 = paper
key=s
move 9 = scissors
 
Old 08-17-2013, 12:40 PM   #3
Lucien Lachance
Member
 
Registered: May 2013
Posts: 82

Original Poster
Rep: Reputation: Disabled
Hmm, is there perhaps another of doing this without shuf? I don't have that command unfortunately.
 
Old 08-18-2013, 10:17 AM   #4
mina86
Member
 
Registered: Aug 2008
Distribution: Slackware
Posts: 406

Rep: Reputation: 171Reputation: 171
Bash has a $RANDOM variable which produces a random number every time it is referenced, so:
Code:
moves=(rock paper scissors)
echo "${moves[$(($RANDOM % ${#moves[@]}))]}"
But since it's not in POSIX, do not put “#!/bin/sh” at the beginning of your script.
 
Old 08-18-2013, 11:56 AM   #5
Lucien Lachance
Member
 
Registered: May 2013
Posts: 82

Original Poster
Rep: Reputation: Disabled
I have an associative array called move_set, how can I just get 'r' 'p' 's' at random?

Code:
declare -A move_set=(['r']="rock" ['p']="paper" ['s']="scissors")
 
Old 08-18-2013, 12:06 PM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 2,525

Rep: Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872
Using PTrenholme's code, replace
Code:
$(shuf -i 1-$# -n 1)
with
Code:
$((RANDOM % $# + 1))
 
Old 08-18-2013, 01:46 PM   #7
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,153

Rep: Reputation: 331Reputation: 331Reputation: 331Reputation: 331
To clarify, ${move_set[*]} is the list of the values in move_set, and ${!move_set[*]} is the list of the key values. See "info bash" in the "Parameter Expansion" section in the "Basic Shell Features" group for details.
 
Old 08-18-2013, 03:55 PM   #8
konsolebox
Senior Member
 
Registered: Oct 2005
Distribution: Gentoo, Slackware, LFS
Posts: 2,245
Blog Entries: 15

Rep: Reputation: 233Reputation: 233Reputation: 233
Quote:
Originally Posted by mina86 View Post
Code:
moves=(rock paper scissors)
echo "${moves[$(($RANDOM % ${#moves[@]}))]}"
This could also be simplified as:
Code:
echo "${moves[RANDOM % ${#moves[@]}]}"
 
Old 08-18-2013, 06:58 PM   #9
Lucien Lachance
Member
 
Registered: May 2013
Posts: 82

Original Poster
Rep: Reputation: Disabled
So far I've come up with this:
I'll try out your solutions in just a minute..

Code:
main() {
  local play_again='y'
  local player opponent
  declare -A move_set=(['r']='Rock' ['p']='Paper' ['s']='Scissors')
  while [[ $play_again == 'y' ]]; do
    print_moves "$(declare -p move_set)"
    read -p 'Enter a move: ' player
    read -p 'Play again? (y/n): ' play_again
    play_again=$(echo $play_again | awk '{ print tolower($0) }')
  done
}
 
Old 08-18-2013, 09:16 PM   #10
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,648

Rep: Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961
Nearly, the awk is an overkill for something bash can already do:
Code:
while [[ ${play_again,} == 'y' ]]; do
You can then delete the awk line. Of course, there is no error checking so they could enter different characters, for that matter i would also change your read to be:
Code:
read -n 1 -p 'Play again? (y/n): ' play_again
I would also change your other read as you are only expecting the user to enter a single letter.
 
Old 08-19-2013, 03:46 PM   #11
Lucien Lachance
Member
 
Registered: May 2013
Posts: 82

Original Poster
Rep: Reputation: Disabled
Could you explain what
Code:
 while [[ ${play_again,} == 'y' ]]; do
does exactly? Does it convert to lowercase? And I'm still having trouble pulling out a random key from move_set.
 
Old 08-19-2013, 07:10 PM   #12
konsolebox
Senior Member
 
Registered: Oct 2005
Distribution: Gentoo, Slackware, LFS
Posts: 2,245
Blog Entries: 15

Rep: Reputation: 233Reputation: 233Reputation: 233
Also how come you ask for a move then ask immediately if a player should play again?

Code:
    read -p 'Enter a move: ' player
    read -p 'Play again? (y/n): ' play_again
 
Old 08-19-2013, 07:51 PM   #13
Lucien Lachance
Member
 
Registered: May 2013
Posts: 82

Original Poster
Rep: Reputation: Disabled
Oh, because I initially coded the while loop to just get the structure of the game setup. It's almost like a roadmap, I can't go anywhere unless I know how the game will be setup. Now I'm going to add things in between where I'm receiving a move from player. After that I'll validate the move and see if it's a key of move_set and so forth.. Sorry for leaving that out. I originally just wrote this in Python and thought it would be fun to port it to Bash.
 
Old 08-19-2013, 09:09 PM   #14
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,648

Rep: Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961Reputation: 1961
Yes a comma converts the first / single character to lower case, see here for further details.

Quote:
And I'm still having trouble pulling out a random key from move_set.
You might have to explain further what trouble you are referring to?
 
Old 08-19-2013, 10:38 PM   #15
Lucien Lachance
Member
 
Registered: May 2013
Posts: 82

Original Poster
Rep: Reputation: Disabled
@grail in Python it was really simple to pick out a key from a list tuple. However, I'm working with an associative array in Bash. Here I've made a function that gets a move from player and opponent makes a random decision of either 'r', 'p', or 's'. For some reason I'm not understanding how to do this same thing in bash.

Code:
#!/usr/bin/env python

def main():
    """Illustrate the concept of assigning a random key value."""
    moves = [('r', "rock"), ('p', "paper"), ('s', "scissor")]

    player = get_move()

    opponent = random.choice(moves)[0]

Last edited by Lucien Lachance; 08-19-2013 at 10:40 PM.
 
  


Reply

Tags
bash, linux, shell scripting


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
BASH Script and $RANDOM lupusarcanus Programming 2 03-15-2011 03:24 AM
[SOLVED] Bash Problems - Random Headers when starting bash in X androidd Slackware 3 01-13-2011 05:29 PM
random sticky keys and mouse clicks in X Bogus8 Linux - Laptop and Netbook 2 01-21-2007 12:46 AM
random keys not working walden Slackware 4 02-16-2005 06:55 PM
bash random function NSKL Programming 6 02-02-2003 02:39 PM


All times are GMT -5. The time now is 10:45 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration