【问题标题】:Pipe looping in shell scriptshell脚本中的管道循环
【发布时间】:2014-09-07 00:52:23
【问题描述】:

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

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

在与 BASH 不同的设置中,这种构造有哪些选项?我不认为它是普遍需要的,但它可能有用,甚至有点有趣!

【问题讨论】:

  • 我手边没有它,但是在 Exploring Expect 一书中有一个例子,它为两个计算机玩家下棋编程。听起来很适合这个问题描述。
  • 是的,就是这样 - 将两台计算机相互操纵。我相信有人用受过公共培训的聊天机器人尝试过,然后他们开始互相辱骂!

标签: shell powershell


【解决方案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()
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-13
    • 2018-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-05-17
    • 1970-01-01
    相关资源
    最近更新 更多