Shell 技巧 - 007 最喜欢的游戏:“百家乐”?
我最近在看皇家赌场,并思考詹姆斯·邦德系列电影,特别是肖恩·康纳利饰演的邦德比丹尼尔·克雷格饰演的更成熟。康纳利更加温文尔雅,他展示这一点的方式之一是在蒙特卡洛的赌场里,被一群美女环绕着玩一种神秘的高 stakes 游戏,叫做百家乐。
好吧,我无法用 shell 脚本创建一个赌场,我当然也无法创建一个特工或一位美女助手,但我可以用 shell 脚本创建一个百家乐游戏。 哎,这可能是第一个有人尝试做这件事!
如果您从一开始就是本专栏的忠实读者,您就会知道大约两年前,我们开始编写一个 二十一点 游戏作为 shell 脚本。这是一个冗长的过程(我不是故意这么说的,对吧?),但作为项目的一部分,我们创建了一种简单的方法来模拟一副牌,“洗牌”(也就是说,将它们置于准随机顺序),甚至将 1-52 的数值转换为花色和点数。
我们将使用它作为创建我们的 百家乐 游戏的起点,这样我们就可以专注于复杂的规则。让我们从那里开始。
百家乐 自 15 世纪中期就已出现,我将要编写的变体 Punto Banco 完全基于规则,不涉及任何技巧。向玩家和庄家各发两张牌,根据这些牌,可能会向其中一方或双方再发第三张牌。人头牌价值为零,数字牌按面值计算。您将一手牌的价值相加,其最终价值是该值模 10 的结果。点数较高者获胜,如果点数相同,则为平局。
例如,如果玩家拿到一张 7H 和一张 3C,则价值为零 (7 + 3 = 10 % 10 = 0)。6S 和 2D 更好;价值 8。最后,9 + 3 + J = 2。明白了吗?最好的手牌价值 9 点。
如果庄家或玩家任何一方拥有 8 或 9 点,则不再向任何一方发牌,游戏结束,庄家或玩家获胜或平局。如果玩家的初始总分为 0-5 分,则玩家可以再抽一张牌。
庄家此时的出牌非常复杂,我将在下一期再解释。现在,我们先来看看如何编写 百家乐 的这些基本规则。
准备好了吗,邦德先生?
第一个难题非常简单——一个 shell 函数,它为给定的牌序列(整数 1-52)返回一个 百家乐 值
function handValue { handvalue=0 # initialize for cardvalue do if [ $cardvalue -ge 0 ] ; then rankvalue=$(( $cardvalue % 13 )) case $rankvalue in 0|11|12 ) rankvalue=0 ;; 1 ) rankvalue=11 ;; esac handvalue=$(( $handvalue + $rankvalue )) fi done handvalue=$(( $handvalue % 10 )) }
此函数使计算一手牌的价值变得容易——无论它将有两张牌还是三张牌。这是一个典型的调用
handValue ${player[1]} ${player[2]}
结果作为全局变量 handvalue 返回,该变量是通过将每张牌的 individual rankvalue 相加计算出来的。
发牌是通过初始化事物来完成的
initializeDeck shuffleDeck
然后,这里实际上是将牌从 newdeck 发到玩家和庄家数组中
player[1]=${newdeck[1]} player[2]=${newdeck[3]} nextplayercard=3 dealer[1]=${newdeck[2]} dealer[2]=${newdeck[4]} nextdealercard=3
实际上,如果是洗过的牌,将前两张牌发给玩家,接下来的两张牌发给庄家,结果是相同的,但由于我们试图模拟 百家乐 游戏中的实际事件顺序,我将第 1 张和第 3 张牌发给玩家,第 2 张和第 4 张牌发给庄家。
下一步是计算玩家和庄家手牌的价值,这可以使用 handValue 函数完成
handValue ${player[1]} ${player[2]} playerhandvalue=$handvalue handValue ${dealer[1]} ${dealer[2]} dealerhandvalue=$handvalue
现在,让我们测试看看我们是否完成了这手牌,因为玩家或庄家的手牌价值为 8 或 9
if [ $playerhandvalue -ge 8 -o $dealerhandvalue -ge 8 ] ; then echo -n "Play is complete. " showResult exit 0 fi
showResult 函数只是计算(并显示)谁赢了
function showResult { if [ $dealerhandvalue -gt $playerhandvalue ] ; then echo "Dealer wins" result=1 elif [ $dealerhandvalue -lt $playerhandvalue ] ; then echo "Player wins" result=2 else echo "Tie" result=3 fi }
我将在此处停止,但在下一专栏中,我将继续探讨如何测试玩家是否应该获得第三张牌。然后,我们将真正深入研究庄家的规则,并开始进行一些游戏!
注意:我大量借鉴了维基百科关于 百家乐 的游戏规则和历史信息 (en.wikipedia.org/wiki/Baccarat)。我专注于所谓的 Punto Banco,即所谓的北美规则 百家乐。如果您像邦德一样,更喜欢 百家乐 Chemin de Fer 或 百家乐 Banque,您可以根据需要进行调整。
Dave Taylor 是一位拥有 26 年 UNIX 经验的资深人士,The Elm Mail System 的创建者,也是畅销书 Wicked Cool Shell Scripts 和 Teach Yourself Unix in 24 Hours 的作者,他著有 16 本技术书籍。他的主要网站是 www.intuitive.com,他还提供技术支持,网址为 AskDaveTaylor.com。