最简单的方法是交错打印东手和西手的代码行(并从每对中的第一行 print() 中删除换行符)。
print "\x{2660} "; print $deck{$_}," " foreach (sort {$a <=> $b} @ws);
print "\t\t\t\t\x{2660} "; print $deck{$_}," " foreach (sort {$a <=> $b} @es); print "\n";
print "\x{2665} "; print $deck{$_}," " foreach (sort {$a <=> $b} @wh);
print "\t\t\t\t\x{2665} "; print $deck{$_}," " foreach (sort {$a <=> $b} @eh); print "\n";
print "\x{2666} "; print $deck{$_}," " foreach (sort {$a <=> $b} @wd);
print "\t\t\t\t\x{2666} "; print $deck{$_}," " foreach (sort {$a <=> $b} @ed); print "\n";
print "\x{2663} "; print $deck{$_}," " foreach (sort {$a <=> $b} @wc);
print "\t\t\t\t\x{2663} "; print $deck{$_}," " foreach (sort {$a <=> $b} @ec); print "\n";
第一次运行时,我得到了很好地说明问题的结果:
♠ 9 3 2 ♠ A K Q J 7 6
♥ 9 6 5 4 ♥ Q 7
♦ 10 8 ♦ A 3
♣ 9 8 3 2 ♣ K 10 5
因为西方只有两颗心,所以东方的心印在左边太远了。我们可以解决这个问题,但最好先简化一下代码。让我们编写一个名为suit_hand() 的子例程,它接受您的一张卡片数组并返回我们需要打印的字符串。
sub suit_hand {
my $symbol = shift;
my @positions = sort { $a <=> $b} @_;
my @cards = map { $deck{$_} } @positions;
return "$symbol " . join ' ', @cards;
}
然后我们可以从您的程序中删除大量重复代码。
print "\t\t\t", suit_hand("\x{2660}", @ns), "\n";
print "\t\t\t", suit_hand("\x{2665}", @nh), "\n";
print "\t\t\t", suit_hand("\x{2666}", @nd), "\n";
print "\t\t\t", suit_hand("\x{2663}", @nc), "\n";
print suit_hand("\x{2660}", @ws), "\t\t\t\t", suit_hand("\x{2660}", @es), "\n";
print suit_hand("\x{2665}", @wh), "\t\t\t\t", suit_hand("\x{2665}", @eh), "\n";
print suit_hand("\x{2666}", @wd), "\t\t\t\t", suit_hand("\x{2666}", @ed), "\n";
print suit_hand("\x{2663}", @wc), "\t\t\t\t", suit_hand("\x{2663}", @ec), "\n";
print "\t\t\t", suit_hand("\x{2660}", @ss), "\n";
print "\t\t\t", suit_hand("\x{2665}", @sh), "\n";
print "\t\t\t", suit_hand("\x{2666}", @sd), "\n";
print "\t\t\t", suit_hand("\x{2663}", @sc), "\n";
输出中没有任何变化,我们只是让代码更易于使用。
所以中间的四行是打印东西方指针的行。这就是我们当前的问题所在。准确地说,是这些行中间的一串制表符导致了问题。我们希望摆脱这些并用更好的格式化输出的方式替换它们。
这就是printf() 给我们的。这是一个“格式化的print()”函数。我们可以这样称呼它:
printf "%-40s %s\n", suit_hand("\x{2660}", @ws), suit_hand("\x{2660}", @es);
第一个参数 ("%-40s %s\n") 是格式字符串。 %s 表示“在此处插入一个字符串”,第一个字符串位置的-40 表示“将此字符串格式化为左对齐且长度为 40 个字符”——这意味着我们的第二个字符串将始终从第 41 个位置开始。
在格式字符串之后,第二个和第三个参数就是我们想要插入到输出中的字符串。在本例中,这只是我们两次调用 suit_hand() 返回的字符串。
所以我们的代码变成了这样:
print "\t\t\t", suit_hand("\x{2660}", @ns), "\n";
print "\t\t\t", suit_hand("\x{2665}", @nh), "\n";
print "\t\t\t", suit_hand("\x{2666}", @nd), "\n";
print "\t\t\t", suit_hand("\x{2663}", @nc), "\n";
printf "%-40s %s\n", suit_hand("\x{2660}", @ws), suit_hand("\x{2660}", @es);
printf "%-40s %s\n", suit_hand("\x{2665}", @wh), suit_hand("\x{2665}", @eh);
printf "%-40s %s\n", suit_hand("\x{2666}", @wd), suit_hand("\x{2666}", @ed);
printf "%-40s %s\n", suit_hand("\x{2663}", @wc), suit_hand("\x{2663}", @ec);
print "\t\t\t", suit_hand("\x{2660}", @ss), "\n";
print "\t\t\t", suit_hand("\x{2665}", @sh), "\n";
print "\t\t\t", suit_hand("\x{2666}", @sd), "\n";
print "\t\t\t", suit_hand("\x{2663}", @sc), "\n";
这是一些示例输出:
♠ 8 5
♥ 5
♦ K Q 9 7 5
♣ Q 8 4 3 2
♠ K Q 10 9 ♠ A 4
♥ 10 9 8 3 ♥ Q 4 2
♦ A J 8 4 ♦ 6 3 2
♣ A ♣ K 10 9 7 6
♠ J 7 6 3 2
♥ A K J 7 6
♦ 10
♣ J 5
请注意,这样做是正确的,即使韦斯特手里只有一把铁锹。
显然,您可以将 printf() 调用中的数字 40 更改为您认为最合适的任何值。
更新:因为午餐有点无聊,我写了一个你的程序版本,展示了我将如何解决这个问题:
#!/usr/bin/perl
use strict;
use warnings;
use List::Util 'shuffle';
binmode STDOUT, ':utf8';
my @suits = qw[spades hearts diamonds clubs];
my %suit = (
spades => "\x{2660}",
hearts => "\x{2665}",
diamonds => "\x{2666}",
clubs => "\x{2663}",
);
my @deck;
for my $s (keys %suit) {
for my $c (2 .. 14) {
push @deck, [$s, $c];
}
}
@deck = shuffle @deck;
my %hand;
for (1 .. 13) {
for my $p (qw[s w n e]) {
my $card = shift @deck;
push @{ $hand{$p}{$card->[0]} }, $card->[1];
}
}
show1hand($hand{n});
show2hands($hand{w}, $hand{e});
show1hand($hand{s});
sub show1hand {
my $hand = shift;
for (@suits) {
print "\t\t\t", suit_hand($_, $hand->{$_}), "\n";
}
}
sub show2hands {
my ($hand1, $hand2) = @_;
for (@suits) {
printf "%-40s %s\n",
suit_hand($_, $hand1->{$_}),
suit_hand($_, $hand2->{$_});
}
}
sub suit_hand {
my ($suit, $cards) = @_;
my %display = (11 => 'J', 12 => 'Q', 13 => 'K', 14 => 'A');
my $card_str = join ' ',
map { $display{$_} // $_ }
sort { $b <=> $a } @$cards;
return "$suit{$suit} $card_str";
}