Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

two dice question

by convenientstore (Pilgrim)
on Jul 17, 2007 at 05:43 UTC ( [id://626969]=perlquestion: print w/replies, xml ) Need Help??

convenientstore has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I am back, While studying the perl book I came across one exercise
which ask reader to make a rolling of 2 standard 6 sided dice and prints out the total of the roll and display the faces of each dice rolled.

I am 1000% sure how I have represented the dice is not the most efficient way but it worked to my delight.
However, I don't think I have a firm grasp on few things (from small list of things I know).

1)print $dice3 prints out the shape of dice with 3 dots correctly,
but not when I put them in the array and try to access it by  print $dicearray[$diceone-1] .. it prints the $dice3 , not dice with 3 dots on it as I was hoping it would

2)then again, I put them in foreach loop(but I am sure it is
pretty much same as 1)...

#!/usr/bin/perl -w use strict; my $diceone = int(rand(5)) + 1; my $dicetwo = int(rand(5)) + 1; print "\$diceone is $diceone and \$dicetwo is $dicetwo\n"; my $dice1; my $dice2; my $dice3; my $dice4; my $dice5; my $dice6; $dice1 = <<done; ############## # # # # # # # # # # # ############## done $dice2 = <<done2; ############## # # # # # # # # # # # # ############## done2 $dice3 = <<done3; ############## # # # # # # # # # # # # # ############## done3 $dice4 = <<done4; ############## # # # # # # # # # # # # # # ############## done4 $dice5 = <<done5; ############## # # # # # # # # # # # # # # # ############## done5 $dice6 = <<done6; ############## # # # # # # # # # # # # # # # # ############## done6 my @dicearray = qw/$dice1 $dice2 $dice3 $dice4 $dice5 $dice6/; #print "\$diceone is $diceone\n"; #print "printing \$dice6 is \n $dice6\n"; #print "$dice3\n"; my $dice; print "Rolling first dice resulted in : \n"; my $result1 = $dicearray[$diceone-1]; foreach $dice (@dicearray) { if ( $dice eq $result1) { print "$dice\n"; last; } }

Replies are listed 'Best First'.
Re: two dice question
by ikegami (Patriarch) on Jul 17, 2007 at 05:57 UTC
    my @dicearray = qw/$dice1 $dice2 $dice3 $dice4 $dice5 $dice6/;

    means

    my @dicearray = ('$dice1', '$dice2', '$dice3', '$dice4', '$dice5', '$d +ice6');

    You want

    my @dicearray = ($dice1, $dice2, $dice3, $dice4, $dice5, $dice6);

    By the way, you can skip the intermediate vars entirely:

    my @dicearray = ( <<done, ############## # # # # # # # # # # # ############## done <<done, ############## # # # # # # # # # # # # ############## done ... );
      By the way, you can skip the intermediate vars entirely:
      Better (IMO):
      my @dicearray = ( <<die1, <<die2, <<die3, <<die4, <<die5, <<die6 ); ############## # # # # # # # # # # # ############## die1 ############## # # # # # # # # # # # # ############## die2 ...

        Or (with modular help) skip the multiple heredocs:

        my $dice = YAML::Syck::Load( <<'EOT' ); --- - |- --------- | | | # | | | --------- - |- --------- | # | | | | # | --------- - |- --------- | # | | # | | # | --------- - |- --------- | # # | | | | # # | --------- - |- --------- | # # | | # | | # # | --------- - |- --------- | # # | | # # | | # # | --------- EOT print $dice->[int(rand(@{$dice}))], "\n";

        (Using Anonymonk's better looking (IMHO) dice from below)

        I really like that syntax, I didn't know you could do that, but it looks good and reads well!

        I'd stick a 'no value yet' die into the first position in the array. For these graphic representations, it is often useful to have an image to represent "unknown". And, in this case, placing the unknown at index 0 aligns the die value with the index for the appropriate image.

        In fact, if an array is not fully populated, but there is a "natural" numerical index, I will often align the elements in the array based on the natural index. If the array becomes 'sparse enough', then I use a hash instead. What constitutes sparse enough depends on a number of issues, like comparative memory usage, etc.

        my @dicearray = ( <<unknown_die, <<die1, <<die2, <<die3, <<die4, <<die +5, <<die6 ); ############## # # # ? ? ? ? ? # # # # ? ? ? ? ? # # # ############## unknown_die ############## # # # # # # # # # # # ############## die1 ############## # # # # # # # # # # # # ############## die2 ... print $dicearray[$die_value]; # no pesky manipulation of the index he +re!


        TGI says moo

Re: two dice question
by quester (Vicar) on Jul 17, 2007 at 06:01 UTC
    A couple of quick observations:

    my $diceone = int(rand(5)) + 1; my $dicetwo = int(rand(5)) + 1;
    These should have rand(6), rather than rand(5). You need numbers between 1.000... and 6.999... in order for int(rand...) to return numbers between 1 and 6.

    I would initialize @dicearray more like this:

    my @dicearray = ($dice1,$dice2,$dice3,$dice4,$dice5,$dice6);
    so it contains the values you need and not the names of variables.

    That way you can print the selected dice with

    print "Rolling first die resulted in : \n"; print $dicearray[$diceone-1]; print "Rolling second die resulted in : \n"; print $dicearray[$dicetwo-1];
    instead of the odd foreach loop.
Re: two dice question
by Anonymous Monk on Jul 17, 2007 at 08:30 UTC
    I just had a play and came up with this.
    #!/usr/bin/perl use strict; use warnings; for (1..6){ print_dice($_); }; sub print_dice{ my $value = shift or die $!; my %diceHash = ( 1 => [0,2,0], 2 => [4,0,1], 3 => [4,2,1], 4 => [5,0,5], 5 => [5,2,5], 6 => [5,5,5] ); print "---------\n"; foreach my $face ($diceHash{$value}){ foreach my $line (@{$face}){ print '| '; my @map = split //, sprintf("%03b",$line); foreach my $dot (@map){ print $dot ? "#":" "," "; } print "|\n"; } } print "---------\n"; };
    Output is:
    --------- | | | # | | | --------- --------- | # | | | | # | --------- --------- | # | | # | | # | --------- --------- | # # | | | | # # | --------- --------- | # # | | # | | # # | --------- --------- | # # | | # # | | # # | ---------

      I wanted to learn some Moose so here is an OO version.

      #!/usr/bin/perl use strict; { package Dice; use Moose; has sides => (is => 'rw', default => 6); has value => (is => 'ro'); my %diceHash = ( 1 => [0,2,0], 2 => [4,0,1], 3 => [4,2,1], 4 => [5,0,5], 5 => [5,2,5], 6 => [5,5,5] ); sub roll { my $self = shift; $self->{value} = int(rand() * $self->sides) + 1 ; return $self; } sub display { my $self = shift; my $out; $out .= "---------\n"; my $face = $diceHash{$self->value()}; foreach my $line (@{$face}){ $out .= '| '; my @map = split //, sprintf("%03b",$line); foreach my $dot (@map){ $out .= ($dot ? "#" : " ") . " "; } $out .= "|\n"; } $out .= "---------\n"; return $out; } } my $d6 = new Dice(); print $d6->roll()->display() for (1..10);

      ___________
      Eric Hodges
Re: two dice question
by ysth (Canon) on Jul 17, 2007 at 06:12 UTC
    As pointed out, you don't want to use qw// to assemble your array. qw stands for "quote words" and is useful for specifying a list of whitespace-separated constant strings without bothering with quotes around each and commas between.

    Also, I don't understand the point of your loop:

    foreach $dice (@dicearray) { if ( $dice eq $result1) { print "$dice\n"; last; } }
    Why aren't you just printing $result1?
Re: two dice question (fu)
by tye (Sage) on Jul 17, 2007 at 22:36 UTC
    print$.+(map{(1)x$_}/./g),":\n",dice()for join$,,map$_+1,map {$_%6,0|$_/6}rand 36;sub dice{@d=/./g;$:=$".'-'x9;join$/,$:x @d,(map{$s=$_;join$,,map{$d=$_;$_=$s;$d&1&&s/0/ @/;s/0/ /;s /\d/$&<$d?' @':' '/ge;" |$_ |"}@c=@d}173,505,371),$:x@d,''}

    - tye        

Re: two dice question
by NetWallah (Canon) on Jul 18, 2007 at 19:57 UTC
    Here is a micro-optimized, version of AnonyMonk's code (just because it was fun).
    #!/usr/bin/perl use strict; use warnings; for (1..6){ print_dice2($_); }; #------------------------------ sub print_dice2{ my $value = shift or die $!; my @DICE = ( 0, 0x020, # Use 3 bits per hex digit, and 3 hex digits 0x401, # to represent one printed line 0x421, # of the die face. 0x505, 0x525, 0x555 ); print "---------\n"; for (8,4,0) { #Choose each Hex digit, Left-to-right my $line = $DICE[$value] >> $_; # Low 4-bits now contain the inf +o print '| ', # Now, pick each bit, L-to-R, and print map({$line & 1 << $_ ? "#" : " "," " } (2,1,0) ), "|\n"; } print "---------\n"; };

         "An undefined problem has an infinite number of solutions." - Robert A. Humphrey         "If you're not part of the solution, you're part of the precipitate." - Henry J. Tillman

Re: two dice question
by Scott7477 (Chaplain) on Jul 19, 2007 at 15:38 UTC
    Here is my iteration of this functionality; I am not so interested in seeing the graphic image of the dice, but rather just getting roll results. quester's suggestions were appreciated. For what it's worth:

    use strict; my $diceone = int(rand(6)) + 1; my $dicetwo = int(rand(6)) + 1; print "Rolling first die resulted in: "; print $diceone-1; print "\n"; print "Rolling second die resulted in: "; print $dicetwo-1; print "\n";


    yields this result:

    Rolling first die resulted in: 3
    Rolling second die resulted in: 5

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://626969]
Approved by ikegami
Front-paged by naikonta
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-26 07:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found