我很好奇在shell管道中形成循环的可能性。我特意使用Windows Power Shell。如果我有一个游戏AI,比如GNU Go,是否可以将它们的两个副本链接在一起并让它们互相播放?管道循环是我的想法。
我看到了一些限制。 A)程序必须输出与用户通常输入相同的命令,以便第二个实例理解第一个,反之亦然。这使得几乎所有的CLI游戏都不合适,因为它们基于文本的视觉反馈。 B)在玩游戏时需要有一个Tee来检查管道,这可能稍微难以使用。我还阅读了using named pipes to create a loop并看到了保持管道畅通的问题。
在BASH的不同设置中,这种构造有哪些选择?我不认为这通常是需要的,但它可能有用,甚至有点娱乐!
答案 0 :(得分:1)
我不确定在单个PowerShell管道中执行此操作,但肯定可以将两个PowerShell会话链接在一起来玩游戏。这是一个使用命名管道的BlackJack脑死亡版本。如果你错误地呼吸它可能会失败,但我能够经历几场比赛 - 扮演经销商。
BlackJackDealer.ps1
-------------------
$suits = 'Clubs','Diamonds','Hearts','Spades'
$ranks = 'Ace','2','3','4','5','6','7','8','9','10','Jack','Queen','King'
function GetShuffledDeck {
$deck = 0..3 | Foreach {$suit = $_; 0..12 | Foreach {
$num = if ($_ -eq 0) {11} elseif ($_ -ge 10) {10} else {$_ + 1}
[pscustomobject]@{Suit=$suits[$suit];Rank=$ranks[$_];Value=$num}}
}
for($i = $deck.Length - 1; $i -gt 0; --$i) {
$rndNdx = Get-Random -Maximum ($i+1)
$temp = $deck[$i]
$deck[$i] = $deck[$rndNdx]
$deck[$rndNdx] = $temp
}
$deck
}
function GetValueOfHand($hand) {
$sum = ($hand | Measure-Object Value -Sum).Sum
if ($sum -gt 21) {
$sum = ($hand | Foreach {if ($_.Value -eq 11) {1} else {$_.Value}} | Measure-Object -Sum).Sum
}
$sum
}
function IsHandBust($hand) {
(GetValueOfHand $hand) -gt 21
}
function IsHandBlackJack($hand) {
if ($hand.Length -ne 2) { return $false }
(GetValueOfHand $hand) -eq 21
}
function DumpHand($hand) {
$cards = $hand | Foreach {DumpCard $_}
$OFS = ", "
"$cards"
}
function DumpCard($card) {
"$($card.Rank) of $($card.Suit)"
}
$npipeServer = new-object System.IO.Pipes.NamedPipeServerStream('BlackJack', [System.IO.Pipes.PipeDirection]::InOut)
try {
"BlackJack dealer started"
"Waiting for client connection"
$npipeServer.WaitForConnection()
"Connection established"
$pipeReader = new-object System.IO.StreamReader($npipeServer)
$pipeWriter = new-object System.IO.StreamWriter($npipeServer)
$pipeWriter.AutoFlush = $true
$msg = $pipeReader.ReadLine()
"Receive msg $msg"
$command,$playerName = $msg -split ' '
if ($command -eq 'EXIT') { break }
"Connected to $playerName. Starting new game. "
$deck = GetShuffledDeck
$cardNdx = $deck.Length - 1
$playerHand = @($deck[$cardNdx--])
$dealerHand = @($deck[$cardNdx--])
$playerHand += $deck[$cardNdx--]
$dealerHand += $deck[$cardNdx--]
"Dealer's hand is $(DumpHand $dealerHand)"
"Player's hand is $(DumpHand $playerHand)"
if (IsHandBlackJack $playerHand) {
$pipeWriter.WriteLine("$playerName gets BLACKJACK $(DumpHand $playerHand)")
}
elseif (IsHandBlackJack $dealerHand) {
$pipeWriter.WriteLine("Dealer gets BLACKJACK $(DumpHand $dealerHand)")
}
else {
$pipeWriter.WriteLine("Dealer's cards are: $(DumpHand $dealerHand)")
$pipeWriter.WriteLine("Your cards are: $(DumpHand $playerHand)")
$dealerStands = $false
$playerStands = $false
while (1) {
$pipeWriter.WriteLine("YOURTURN")
$command = $pipeReader.ReadLine()
switch ($command) {
'HITME' {}
'STAND' {$playerStands = $true}
default {
$msg = "Sorry $playerName, didn't recognize command: '$command'"
$msg
$pipeWriter.WriteLine($msg)
continue
}
}
# Player's turn
if ($playerStands) {
"$playerName stands with hand $(DumpHand $playerHand)"
}
else {
$newCard = $deck[$cardNdx--]
"$playerName requests hit, draws $(DumpCard $newCard)"
$playerHand += $newCard
if (IsHandBust $playerHand) {
"$playerName busts, Dealer wins"
$pipeWriter.WriteLine("You bust with hand $(DumpHand $playerHand)")
break
}
else {
$pipeWriter.WriteLine("You drew a card, updated hand $(DumpHand $playerHand)")
}
}
# Dealer's turn
if ($dealerStands -or (GetValueOfHand $dealerHand) -ge 17) {
$dealerStands = $true
$msg = "DEALER stands with $(DumpHand $dealerHand)"
$msg
$pipeWriter.WriteLine($msg)
}
else {
do {
$newCard = $deck[$cardNdx--]
$dealerHand += $newCard
$msg = "Dealer draws $(DumpCard $newCard), updated hand $(DumpHand $dealerHand)"
$msg
$pipeWriter.WriteLine($msg)
$dealerSum = GetValueOfHand $dealerHand
if ($dealerSum -gt 21) {
$msg = "DEALER busts with $(DumpHand $dealerHand)"
$msg
$pipeWriter.WriteLine($msg)
break;
}
elseif ($dealerSum -ge 17) {
$dealerStands = $true;
$msg = "DEALER stands with $(DumpHand $dealerHand)"
$msg
$pipeWriter.WriteLine($msg)
}
Start-Sleep -Seconds 1
} while (!$dealerStands -and $playerStands)
}
if ($playerStands -and $dealerStands) {
$dealerSum = GetValueOfHand $dealerHand
$playerSum = GetValueOfHand $playerHand
if ($dealerSum -gt $playerSum) {
$msg = "DEALER wins with $(DumpHand $dealerHand)"
}
elseif ($playerSum -gt $dealerSum) {
$msg = "$playerName wins with $(DumpHand $playerHand)"
}
else {
$msg = "The game is a push"
}
$msg
$pipeWriter.WriteLine($msg)
break
}
}
}
"Instructing client to close connection"
$pipeWriter.WriteLine("EXITING")
Start-Sleep -Seconds 2
}
finally {
"Game exiting"
$npipeServer.Dispose()
}
以及其他脚本:
BlackJackPlayer.ps1
-------------------
$npipeClient = new-object System.IO.Pipes.NamedPipeClientStream('.', 'BlackJack', [System.IO.Pipes.PipeDirection]::InOut)
$pipeReader = $pipeWriter = $null
try {
$playerName = Read-Host "Enter your name"
"BlackJack player connecting to dealer"
$npipeClient.Connect()
"Connected to dealer"
$pipeReader = new-object System.IO.StreamReader($npipeClient)
$pipeWriter = new-object System.IO.StreamWriter($npipeClient)
$pipeWriter.AutoFlush = $true
$pipeWriter.WriteLine("STARTGAME $playerName")
while (1) {
while (($msg = $pipeReader.ReadLine()) -notmatch "EXITING|YOURTURN") {
$msg
}
if ($msg -match 'EXITING') { break }
$command = Read-Host "Enter HITME or STAND"
$pipeWriter.WriteLine($command)
if ($command -eq 'STAND') {
while (($msg = $pipeReader.ReadLine()) -notmatch "EXITING") {
$msg
}
break;
}
}
}
finally {
"Game exiting"
$npipeClient.Dispose()
}