ok, 我们有两个地方需要开始计时
第一个是游戏开始的时候,
第二个是 turn 结束的时候。
def init(game) do
Process.send_after(self(), {:times_up, :host, 1, 1}, 3000) # 游戏开始的时候,开始倒数
Process.send_after(self(), {:times_up, :guest, 1, 1}, 3000) # 一人一个
{:ok, game}
end
Process.send_after/3
的第一个变数是收 pid,
我们可以用 self()
来得到目前执行这个地方本身的 pid。
为了等一下好测试,我们先用 3 秒,而不是原本要的 30
再来是时间到了之後要执行的 handle_info :times_up
执行的时候要做的事情有
我直接按照列表直接做,变超长的,我把项目标示在下方注解里
def handle_info(
{:times_up, player, round, turn},
%{round: current_round, turn: current_turn} = game
)
when round == current_round and turn == current_turn do
# 这个 guard 用来实现 1.检查目前的游戏状态还是不是同个回合
# 2.随机抽牌
card =
game
|> Map.get(player)
|> Map.get(:hand)
|> Enum.random()
# 我们暂时在这边用 IO.puts 来印出讯息,待会在 iex 跑的时候比较知道在跑啥
IO.puts("time's up, play #{card} for #{player}")
# 3.代替玩家出牌
# 这个是直接从原本的出牌方法 handle_cast :play_card 复制过来的
game =
game
|> play_card_for(player, card)
|> end_turn()
|> add_wins()
|> end_round()
|> end_game()
# 4. 出牌後,为新回合执行出牌倒数
# 这边判断如果 游戏还在进行,而且这次出牌有导致 换到新的 turn
if game.status == :start && current_turn != game.turn do
Process.send_after(self(), {:times_up, :host, game.round, game.turn}, 3000)
Process.send_after(self(), {:times_up, :guest, game.round, game.turn}, 3000)
end
{:noreply, game}
end
# 如果玩家有出过牌了,就忽略
def handle_info({:times_up, _player, _round, _turn}, game), do: {:noreply, game}
完成了,使用 GenServer 真的让这件事情简单很多
除了上面在帮玩家出牌的时候有印出 帮谁出什麽牌之外
在 add_wins 方法,我也暂时用 IO.puts 显示谁赢一局,与目前比数
defp add_wins(%{turn: turn, round: round, host: host, guest: guest} = game) when turn > 3 do
range_start = (round - 1) * 3
range = range_start..(range_start + 2)
host_desk = Enum.slice(host.desk, range)
guest_desk = Enum.slice(guest.desk, range)
if apply_reverse(
get_score(host_desk) > get_score(guest_desk),
reverse?(host_desk ++ guest_desk)
) do
IO.puts("? Host win this round, host: #{host.wins + 1}, guest: #{guest.wins}") # 显示该局结果
assign_to_player(game, :host, :wins, game.host.wins + 1)
else
IO.puts("? Guest win this round, host: #{host.wins}, guest: #{guest.wins + 1}") # 显示该局结果
assign_to_player(game, :guest, :wins, game.guest.wins + 1)
end
end
还有结束游戏的地方也加上通知
defp end_game(%{guest: %{wins: 2}} = game) do
IO.puts "? winner is Guest"
Map.replace(game, :status, :guest_win)
end
defp end_game(%{host: %{wins: 2}} = game) do
IO.puts "? winner is Host"
Map.replace(game, :status, :host_win)
end
defp end_game(game), do: game
来跑跑看吧,这次只要打一行,因为我们暂时把出牌时间设定成 3 秒,就好像游戏自动玩一样
iex(1)> Game.start
{:ok, #PID<0.112.0>}
time's up, play 3 for host
time's up, play reverse for guest
time's up, play 6 for host
time's up, play 3 for guest
time's up, play reverse for host
time's up, play 3 for guest
? Host win this round, host: 1, guest: 0
time's up, play reverse for host
time's up, play 1 for guest
time's up, play 5 for host
time's up, play reverse for guest
time's up, play 1 for host
time's up, play 5 for guest
? Host win this round, host: 2, guest: 0
? winner is Host
执行动图
>>: 每日挑战,从Javascript面试题目了解一些你可能忽略的概念 - Day13
上一篇成功将 Nestjs 部属到 heroku 上面,不过我们使用的是免费方案,免费方案有几个限制...
Shioaji 是一个建构在永丰金证券上所开发的API,让原本是用人操作的App功能,独立出来让程...
前面几篇我们提到过 DOM API 节点,但貌似没有讨论到什麽是 API;到了今天这个主题,好像确实...
本篇重点 官方说明文件:https://sinotrade.github.io/tutor/adva...
是说在社群到处都在爆雷的《鱿鱼游戏》,我进度第一集,好想弃赛来追剧(我就废 然後谢谢没看鱿鱼游戏,...