我正在尝试用bash模拟一个2人游戏。更确切地说,应该有一个中央程序(游戏引擎)和两个玩家程序。游戏引擎应该将游戏信息发送给player1,然后获取player1的输出,然后将游戏信息发送给player2,然后获得player2的输出,然后重复。
如果可能的话,我更喜欢游戏引擎不负责调度其输出,而是依靠bash脚本来安排整个事情。
在阅读了有关命名管道的内容后,我发现它们正是我所需要的,并提出了以下设置:
#!/bin/bash
trap "rm -f $in1 $in2 $out1 $out2 $in $out; kill $pid; kill $pid1; kill $pid2" KILL
in1=/tmp/testpipe_in1
in2=/tmp/testpipe_in2
out1=/tmp/testpipe_out1
out2=/tmp/testpipe_out2
in=/tmp/testpipe_in
out=/tmp/testpipe_out
for p in $in1 $in2 $out1 $out2 $in $out; do
[[ -p $p ]] || mkfifo $p
done
echo 0 > $in
./center.sh < $in > $out &
pid=$!
./player1.sh < $in1 > $out2 &
pid1=$!
./player2.sh < $in2 > $out2 &
pid2=$!
i=0
while true; do
i=$((i+1))
echo "Round $i" >&2
cat < $out > $in1
cat < $out1 > $in
cat < $out > $in2
cat < $out2 > $in
done
我正在使用以下游戏和玩家对此进行测试:
center.sh
:
#!/bin/bash
while true; do
sleep 2
read i
echo "Center : $i $((i+2))" >&2
echo $((i+2))
done
player1.sh
:
#!/bin/bash
while true; do
sleep 1
read i
echo "Player1 : $i $((i-1))" >&2
echo $((i-1))
done
player2.sh
:
#!/bin/bash
while true; do
sleep 1
read i
echo "Player2 : $i $((i+1))" >&2
echo $((i+1))
done
我希望它输出类似
的内容Center : 0 2
Round 1
Player1 : 2 1
Center : 1 3
Player2 : 3 4
Center : 4 6
Round 2
Player1 : 6 5
...
......但当然它不起作用。
相反,我得到:
Round 1
Center : 0 2
Center : 2
Center : 2
...
问题在我的球员中是否显而易见?或者设置这种输入/输出的正确方法是什么?
答案 0 :(得分:1)
以下是一些可能会让您更进一步的变化:
你的第一个剧本中有一个拼写错误。它应该是:
./player1.sh < $in1 > $out1 &
即。 out1不是out2。
在启动玩家后移动echo 0 > $in
。
将最终的while
循环更改为:
while true; do
i=$((i+1))
echo "Round $i" >&2
read <&5; echo "$REPLY" >&6
read <&7; echo "$REPLY" >&8
read <&5; echo "$REPLY" >&9
read <&4; echo "$REPLY" >&8
done 5<$out 6>$in1 7<$out1 8>$in 9>$in2 4<$out2
最初,一个fifo的读者被阻止,直到作家写入
fifo。一旦作者关闭了fifo,读者就会阅读eof但是
不再被阻止所以继续阅读eof直到作者重新打开
fifo再次写道。
您需要检查read
的返回码并重新打开fifo
作为读者,以便再次阻止。
您可以通过以下方式轻松查看:
while sleep 1; do read;echo "$? $REPLY";done <testpipe_out1 &
sleep 5
echo hi >testpipe_out1
读取将阻塞直到“hi”,然后循环返回代码“1”。