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;
}
}
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
...
);
| [reply] [d/l] [select] |
|
By the way, you can skip the intermediate vars entirely:
Better (IMO):
my @dicearray = ( <<die1, <<die2, <<die3, <<die4, <<die5, <<die6 );
##############
# #
# #
# # #
# #
# #
##############
die1
##############
# #
# #
# # # #
# #
# #
##############
die2
...
| [reply] [d/l] |
|
my $dice = YAML::Syck::Load( <<'EOT' );
---
- |-
---------
| |
| # |
| |
---------
- |-
---------
| # |
| |
| # |
---------
- |-
---------
| # |
| # |
| # |
---------
- |-
---------
| # # |
| |
| # # |
---------
- |-
---------
| # # |
| # |
| # # |
---------
- |-
---------
| # # |
| # # |
| # # |
---------
EOT
print $dice->[int(rand(@{$dice}))], "\n";
(Using Anonymonk's better looking (IMHO) dice from below)
| [reply] [d/l] |
|
|
|
|
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!
| [reply] [d/l] |
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.
| [reply] [d/l] [select] |
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:
---------
| |
| # |
| |
---------
---------
| # |
| |
| # |
---------
---------
| # |
| # |
| # |
---------
---------
| # # |
| |
| # # |
---------
---------
| # # |
| # |
| # # |
---------
---------
| # # |
| # # |
| # # |
---------
| [reply] [d/l] [select] |
|
#!/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);
| [reply] [d/l] |
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? | [reply] [d/l] |
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,''}
| [reply] [d/l] |
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
| [reply] [d/l] |
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
| [reply] [d/l] |
|
|