文档章节

(整理)用Elixir做一个多人扑克游戏 3

ljzn
 ljzn
发布于 2016/10/05 21:07
字数 639
阅读 48
收藏 0
点赞 0
评论 0

今天我们将为德州扑克游戏添加故障恢复能力。

OTP为我们准备好了构建容错程序所需要的工具。我们只需要定义正确的behavior 行为。

Supervisor

有了Supervisor,我们就只需要关心当进程崩溃时如何反应。首先,我们使用顶层的Supervisor——Application:

defmodule GenPoker do
  use Application

  def start(_type, _args) do
    import Supervisor.Spec

    children = [
      worker(Poker.Bank, [])
    ]

    opts = [strategy: :one_for_one, name: GenPoker.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

在mix.exs中注册我们的应用模块:

def application do
  [mod: {GenPoker, []}]
end

当工作中的进程崩溃后,会新建一个新的进程,打开 iex -S mix 测试一下:

iex(1)> Process.whereis(Poker.Bank)      
#PID<0.93.0>
iex(2)> Process.whereis(Poker.Bank) |> Process.exit(:kill)
true
iex(3)> Process.whereis(Poker.Bank)                       
#PID<0.97.0>

The Table Supervisor

我们可以把牌桌和牌局进程放在同一个Supervisor下:

defmodule Poker.Table.Supervisor do
  use Supervisor

  def start_link(table_name, num_players) do
    Supervisor.start_link(__MODULE__, [table_name, num_players])
  end

  def init([table_name, num_players]) do
    children = [
      worker(Poker.Table, [table_name, num_players])
    ]

    supervise children, strategy: :one_for_one
  end
end

把这个Supervisor添加到顶层的Supervisor下:

def start(_type, _args) do
  import Supervisor.Spec

  children = [
    worker(Poker.Bank, []),
    supervisor(Poker.Table.Supervisor, [:table_one, 6])
  ]

  opts = [strategy: :one_for_one, name: GenPoker.Supervisor]
  Supervisor.start_link(children, opts)
end

添加hand 牌局

我们不希望牌局在玩家准备好之前自动启动,也不希望在牌局结束之后重启。首先,向 Table Supervisor 中添加一个函数:

def start_hand(supervisor, table, players, config \\ []) do
  Supervisor.start_child(supervisor,
    supervisor(Poker.Hand.Supervisor, 
      [table, players, config], restart: :transient, id: :hand_sup
    )
  )
end

我们使用了 transient 暂时策略,也就是它不会在普通的退出之后被重启。子进程是牌局的Supervisor:

defmodule Poker.Hand.Supervisor do
  use Supervisor

  def start_link(table, players, config) do
    Supervisor.start_link(__MODULE__, [table, players, config])
  end

  def init([table, players, config]) do
    hand_name = String.to_atom("#{table}_hand")
    children = [
      worker(Poker.Hand, [table, players, config, [name: hand_name]], restart: :transient)
    ]

    supervise children, strategy: :one_for_one
  end
end

之后我们会解释多加这一层Supervisor的原因。我们需要对Table Supervisor的init稍作修改:

def init([table_name, num_players]) do
  children = [
    worker(Poker.Table, [self, table_name, num_players])
  ]

  supervise children, strategy: :one_for_one
end

以及对deal 发牌消息的 handle_call:

def handle_call(:deal, _from, state = %{hand_sup: nil}) do
  players = get_players(state) |> Enum.map(&(&1.id))

  case Poker.Table.Supervisor.start_hand(
    state.sup, state.table_name, players
  ) do
    {:ok, hand_sup} ->
      Process.monitor(hand_sup)
      {:reply, {:ok, hand_sup}, %{state | hand_sup: hand_sup}}
    error ->
      {:reply, error, state}
  end
end

我们在收到deal消息后启动hand牌局,并使用之前创建的Hand Supervisor 来监控。

现在我们的Supervisor 树已经有了雏形,但我们的state 状态信息无法保存,它会在进程崩溃时消失。所以我们需要 ETS 来保存state。当崩溃次数达到一定限度,Supervisor就会放弃,并由上一级Supervisor来重启。

下一篇中,我们将把已有的程序导入Phoenix Channel 中。

© 著作权归作者所有

共有 人打赏支持
ljzn
粉丝 29
博文 69
码字总数 96245
作品 0
南平
程序员
(整理)用Elixir做一个多人扑克游戏 2

原文 现在我们已经做好了牌面大小的比较,游戏的流程,但还没有做玩家登陆,人数限制,甚至没有将奖金发送给赢家。接下来,让我们来完成它们。 玩家需要兑换游戏中的筹码才能开始游戏,在当不...

ljzn ⋅ 2016/10/04 ⋅ 0

(整理)用Elixir做一个多人扑克游戏 1

原文 学习一门新的语言或框架,最好的方法就是做一些小项目。Elixir和Phoenix很适合用来做扑克应用。 洗牌 我们要做的是德州扑克,首先,需要牌组: 我们定义了一个能够给出一套洗好了的52张...

ljzn ⋅ 2016/10/03 ⋅ 2

(整理)用Elixir做一个多人扑克游戏 4

sockets 和 channels 是Phoenix中用来实现实时效果的两大工具。 Sockets socket是用来连接客户端与服务器的,它使用endpoint来声明: Channels 客户端只有加入了channel之后才能发送消息。 ...

ljzn ⋅ 2016/10/06 ⋅ 0

独家首发 | NIPS 最佳论文视频解读!德州扑克背后的不完全信息博弈

美国时间, 2017 年 12 月 4 日 8:00。 全球机器学习顶级会议 NIPS 在美国长滩开幕了。 本年度 NIPS 将持续一周,你现在才想参加肯定来不及,因为票早就卖光了。 为了让你隔着太平洋都能跟上...

雷锋字幕组 ⋅ 2017/12/05 ⋅ 0

(译)循序渐进学习Elixir

——Chris Bell Learning Elixir at Made by Many 在今年奥兰多的Elixir大会上演讲之后,就经常有人问我:你们团队是如何学习Elixir和OTP的? 和学习其他语言一样,学习Elixir也需要付出时间...

ljzn ⋅ 2016/09/29 ⋅ 0

17年的人工智能承包了我们所有的游戏?!

  【IT168 资讯】在20世纪的大部分时间里,国际象棋博弈都是人工智能研究人员的基准。约翰・麦卡锡(John McCarthy)在20世纪50年代早期创造了“人工智能”一词,曾经把国际象棋称为“人工智...

it168网站 ⋅ 01/05 ⋅ 0

Pokerth

PokerTH是一个用C++/QT4写的单用户的扑克游戏。你能和最多六个电脑对手玩流行的"Texas Hold'em"扑克。这个扑克引擎是开源和在Linux, Windows和MacOSX上可用的。 开始网络游戏 网络游戏多达七...

匿名 ⋅ 2008/11/14 ⋅ 1

从不做线上推广,这家棋牌公司用线下比赛月入百万

  近年来,随着移动互联网的兴起和移动支付的普及,棋牌类智力运动的用户量大幅提升。据伽马数据统计,2016年中国棋牌游戏用户规模达到2.58亿,也就是说在中国,平均每5个人中就有一个棋牌...

网狐棋牌开发 ⋅ 2017/11/29 ⋅ 0

德扑AI之父解答Libratus的13个疑问:没有用到任何深度学习,DL远非AI的全部

雷锋网 AI 科技评论按:昨天晚上,卡耐基梅隆大学计算机系在读博士生 Noam Brown 和计算机系教授 Tuomas Sandholm 来到 reddit 的机器学习分版,和网友们一起来了一场「你问我答」(ask me ...

杨晓凡 ⋅ 2017/12/20 ⋅ 0

德扑 AI 之父解答 Libratus 的13个疑问:没有用到任何深度学习,DL 远非 AI 的全部

width="auto" class=" " src="http://ss.csdn.net/p?http://mmbiz.qpic.cn/mmbizjpg/vJe7ErxcLmg1KLkLdggoTAVAB3Rs2TJsJwxAiaaQ2bsfLe4hrW5qIktwXDTr1bnBGQBWoIG4E154vHqYMyBdCicQ/?wxfrom=5......

w9JLwB ⋅ 2017/12/20 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

知乎Java数据结构

作者:匿名用户 链接:https://www.zhihu.com/question/35947829/answer/66113038 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 感觉知乎上嘲讽题主简...

颖伙虫 ⋅ 今天 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部