文档章节

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

ljzn
 ljzn
发布于 2016/10/06 21:59
字数 435
阅读 170
收藏 0

#程序员薪资揭榜#你做程序员几年了?月薪多少?发量还在么?>>>

sockets 和 channels 是Phoenix中用来实现实时效果的两大工具。

Sockets

socket是用来连接客户端与服务器的,它使用endpoint来声明:

defmodule GenPoker.Endpoint do
  use Phoenix.Endpoint, otp_app: :gen_poker

  socket "/socket", GenPoker.PlayerSocket
end

Channels

客户端只有加入了channel之后才能发送消息。

defmodule GenPoker.PlayerSocket do
  use Phoenix.Socket

  channel "tables:*", GenPoker.TableChannel
end

创建socket

defmodule GenPoker.PlayerSocket do
  use Phoenix.Socket

  transport :websocket, Phoenix.Transports.WebSocket

  def connect(%{"playerId" => player_id}, socket) do
    {:ok, assign(socket, :player_id, player_id)}
  end

  def id(socket) do 
    "players_socket:#{socket.assigns.player_id}"
  end
end

注册进程

defmodule Poker.Table do
  use GenServer

  def start_link(table_name, sup, storage, num_seats) do
    GenServer.start_link(
      __MODULE__, 
      [table_name, sup, storage, num_seats], 
      name: via_tuple(table_name)
    )
  end

  defp via_tuple(table) do 
    {:via, :gproc, {:n, :l, {:table, table}}}
  end

  def whereis(table) do
    :gproc.whereis_name({:n, :l, {:table, table}})
  end
end

我们使用了gproc库来注册进程,这样就可以使用一个term而不仅仅是atom作为名字。让我们来定义Channel:

module GenPoker.TableChannel do
  use GenPoker.Web, :channel
  alias Poker.Table

  def join("tables:" <> table, _payload, socket) do
    {:ok, assign(socket, :table, table)}
  end

  def handle_in(command, payload, socket) 
    when command in ~w(sit leave buy_in cash_out deal) 
  do
    table = Table.whereis(socket.assigns.table)
    arguments = [table, socket.assigns.player_id] ++ payload
    result = apply(Table, String.to_atom(command), arguments)
    if result == :ok do
      broadcast! socket, "update", Table.get_state(table)
    end
    {:reply, result, socket}
  end
end

对于客户端的join请求,我们有不同的回复。在JavaScript中可以这样写:

channel.push("message", arguments)
  .receive("ok", (msg) => console.log("Got OK!"))
  .receive("error", (msg) => console.log("Oops!"))

发送初始的state

def join("tables:" <> table, _payload, socket) do
  state = table |> Table.whereis |> Table.get_state
  push socket, "update", state
  {:ok, assign(socket, :table, table)}
end

使用handle_info

def join("tables:" <> table, _payload, socket) do
  send self, :after_join
  {:ok, assign(socket, :table, table)}
end

def handle_info(:after_join, socket) do
  state = socket.assigns.table |> Table.whereis |> Table.get_state
  push socket, "update", state
  {:noreply, socket}
end

def handle_info(_, socket) do
  {:noreply, socket}
end

拦截消息

def handle_out("update", state, socket) do
  push socket, "update", hide_other_hands(state, socket)
  {:noreply, socket}
end

defp hide_other_hands(state, socket) do
  player_id = socket.assigns.player_id
  hide_hand_if_current_player = fn
    %{id: ^player_id} = player -> player
    player -> Map.delete(player, :hand)
  end

  update_in(state.players, fn players ->
    Enum.map(players, hide_hand_if_current_player)
  end)
end

完整代码

© 著作权归作者所有

ljzn
粉丝 30
博文 69
码字总数 96245
作品 0
南平
程序员
私信 提问
加载中

评论(0)

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

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

ljzn
2016/10/03
629
2
(整理)用Elixir做一个多人扑克游戏 2

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

ljzn
2016/10/04
69
0
(整理)用Elixir做一个多人扑克游戏 3

今天我们将为德州扑克游戏添加故障恢复能力。 OTP为我们准备好了构建容错程序所需要的工具。我们只需要定义正确的behavior 行为。 Supervisor 有了Supervisor,我们就只需要关心当进程崩溃时...

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

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

雷锋字幕组
2017/12/05
0
0
AI攻陷多人德扑再登Science,训练成本150美元,每小时赢1000刀

在无限制德州扑克六人对决的比赛中,德扑 AI Pluribus 成功战胜了五名专家级人类玩家。Pluribus 由 Facebook 与卡耐基梅隆大学(CMU)共同开发,实现了前辈 Libratus(冷扑大师)未能完成的任...

Cashcow
2019/07/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Kubernetes Ingress简单入门

本文转载自Rancher Labs 不知道你是否注意到一个奇怪的现象,尽管Kubernetes Ingress API仍然处于beta状态,但是已经有许多公司使用它来暴露Kubernetes服务。从事相关项目的工程师表示,Kub...

osc_slfjdpj6
41分钟前
21
0
ACCDB MDB Explorer for mac(数据库查看器)

想要更加直观的查看大数据,小编推荐使用mac数据查看工具ACCDB MDB Explorer Mac版,该软件能够将导入的数据库导出为XML,XLS,CSV和TXT格式的文件简便高效请添加链接描述,功能强大,需要的...

osc_63i522q0
43分钟前
14
0
二 javanio中的Channel transfer 内容

java nio中channel操作 分散 将channel中读取的数据分散写入多个buffer中 聚集 将多个buffer写入数据到同一个channel 应用 将消息头和消息体放入到不同buffer,便于分类处理应用 将消息头和消...

writeademo
43分钟前
26
0
如何更好的盘活和用好数据资产,企业如何构建数据竞争力的关键在这里!

在今年4月公布的《中共中央国务院关于构建更加完善的要素市场化配置体系机制的意见》中,“数据”首次作为一种新型生产要素写入中央文件中,与土地、劳动力、资本、技术等传统要素并列成为要...

osc_5asswvor
44分钟前
30
0
如何更好的盘活和用好数据资产,企业如何构建数据竞争力的关键在这里!

在今年4月公布的《中共中央国务院关于构建更加完善的要素市场化配置体系机制的意见》中,“数据”首次作为一种新型生产要素写入中央文件中,与土地、劳动力、资本、技术等传统要素并列成为要...

osc_e7clsgkf
45分钟前
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部