在shell脚本中循环管道

时间:2014-09-07 00:52:23

标签: shell powershell

我很好奇在shell管道中形成循环的可能性。我特意使用Windows Power Shell。如果我有一个游戏AI,比如GNU Go,是否可以将它们的两个副本链接在一起并让它们互相播放?管道循环是我的想法。

我看到了一些限制。 A)程序必须输出与用户通常输入相同的命令,以便第二个实例理解第一个,反之亦然。这使得几乎所有的CLI游戏都不合适,因为它们基于文本的视觉反馈。 B)在玩游戏时需要有一个Tee来检查管道,这可能稍微难以使用。我还阅读了using named pipes to create a loop并看到了保持管道畅通的问题。

在BASH的不同设置中,这种构造有哪些选择?我不认为这通常是需要的,但它可能有用,甚至有点娱乐!

1 个答案:

答案 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()
}