1. 程式人生 > >簡單Elixir遊戲服設計-玩法simple_poker

簡單Elixir遊戲服設計-玩法simple_poker

server log nor serve isp point cond model rem

上回介紹了玩法,現在編寫了玩法的簡單建模。

做到現在感覺目前還沒有使用umbrella的必要(也許以後會發現必要吧),model 應用完全可以合並到game_server。

代碼還在https://github.com/rubyist1982/simple 上。

model 應用新增 simple_poker.ex , 代碼不多,做了點簡單註釋,可以貼下

技術分享
defmodule SimplePoker do
    @cards  for i <- 1..4, j<- 1..13, do: {i, j}
    @ten 10
    @ace 1
    @tian_gong [
8,9] @ignore 0 def init_cards, do: @cards # 洗牌 def shuffle(cards), do: cards |> Enum.shuffle # 初始發牌 def init_deal(cards, seat_num) do {cs, left} = cards |> Enum.split(seat_num * 2) {:ok, Enum.chunk_every(cs, 2), left} end # 補單張 def
deal([card| left]), do: {:ok, card, left} def single_point({_, p}) when p < @ten, do: p def single_point(_), do: @ten def normal_power(cards) do sum = cards |> Enum.map( &single_point(&1) ) |> Enum.sum rem(sum, @ten) end # 牌力計算, 需參考是否開牌
def power([_a, _b] = cards, is_open) do p = normal_power(cards) cond do p in @tian_gong and is_open -> {:tian_gong, p} true ->{:normal, p} end end def power(cards, false) do cond do is_flush_straight?(cards) -> {:flush_straight, @ignore} is_three?(cards) -> {:three, @ignore} is_flush?(cards) -> {:flush, @ignore} is_straight?(cards) -> {:straight, @ignore} true -> {:normal, normal_power(cards)} end end # a 是否贏 b # 都是天公,比點數 def win?({:tian_gong, p1}, {:tian_gong, p2}), do: p1 > p2 # 天公比其他都大 def win?({:tian_gong, _}, _), do: true def win?(_, {:tian_gong, _}), do: false # 非普通牌,通牌型一樣大 def win?({same, _}, {same, _}) when same != :normal, do: false # 同花順比余下都大, 以下類推 def win?({:flush_straight, _}, _), do: true def win?(_, {:flush_straight, _}), do: false def win?({:three, _}, _), do: true def win?(_, {:three, _}), do: false def win?({:flush, _}, _), do: true def win?(_, {:flush, _}), do: false def win?({:straight, _}, _), do: true def win?(_, {:straight, _}), do: false # 普通牌需要比較點數 def win?({:normal, p1}, {:normal, p2}), do: p1 > p2 # 贏多少倍 def multiply({:tian_gong, _}), do: 1 def multiply({:flush_straight, _}), do: 16 def multiply({:three, _}), do: 8 def multiply({:flush, _}), do: 4 def multiply({:straight, _}), do: 2 def multiply({:normal, _}), do: 1 def is_flush?([{s, _}, {s, _}, {s, _}]), do: true def is_flush?(_), do: false def is_straight?([{_, p1}, {_, p2}, {_, p3}]) do [n1, n2, n3] = [p1, p2, p3] |> Enum.sort cond do n1 + 1 == n2 and n2 + 1 == n3 -> true n1 == @ace and n2 + 1 == n3 -> true n1 == @ace and n2 + 2 == n3 -> true true -> false end end def is_three?([{_, p}, {_, p}, {_, p}]), do: true def is_three?([{_, p1}, {_, p2}, {_, p3}]) do case [p1, p2, p3] |> Enum.sort do [@ace, @ace, _] -> true [@ace, n, n] -> true _other -> false end end def is_flush_straight?(cards), do: is_flush?(cards) and is_straight?(cards) end # SimplePoker.init_cards |> SimplePoker.shuffle |> IO.inspect # SimplePoker.init_cards |> SimplePoker.init_deal(2) |> IO.inspect
simple_poker.ex

測試代碼 simple_poker_test.exs

技術分享
defmodule SimplePokerTest do
  use ExUnit.Case
  doctest SimplePoker

  setup do
      %{
          s_ace: {1,1},   # 黑桃A
          h_ace:  {2, 1}, # 紅桃A,
          c_ace: {3, 1},  # 梅花A
          s_two: {1, 2},  # 黑桃2
          h_two: {2, 2},  # 紅桃2
          c_two: {3, 2},  # 梅花2
          s_three: {1, 3},  # 黑桃3
          h_three: {2, 3}, # 紅桃3
          s_four: {1, 4},  # 黑桃4
          h_four: {2, 4},  # 紅桃4
          s_five: {1, 5}, # 黑桃5
          s_eight: {1, 8}, # 黑桃8
          s_nine: {1, 9}, # 黑桃9
          s_ten: {1, 10}, # 黑桃10
          s_jack: {1, 11}

      }
  end  


  test "同花: 黑桃A,黑桃2, 黑桃3 ", cards do
      flush_cards = [cards.s_ace, cards.s_two, cards.s_three]
      assert SimplePoker.is_flush?(flush_cards)
  end

  test "非同花: 黑桃A, 紅桃A, 黑桃2 ", cards do
      not_flush_cards = [cards.s_ace, cards.h_ace, cards.s_two]
      refute SimplePoker.is_flush?(not_flush_cards) 
  end

  test "三條: 普通", cards do
      normal_three = [cards.s_two, cards.h_two, cards.c_two]
      assert SimplePoker.is_three?(normal_three)
  end

  test "三條:1張A + 1對 ", cards do
    one_ace_and_one_pair = [cards.s_two, cards.h_two, cards.s_ace]
    assert SimplePoker.is_three?(one_ace_and_one_pair)
  end

  test "三條: 2張A + 1張2 ", cards do
    two_ace_and_one = [cards.s_ace, cards.h_ace, cards.s_two]    
    assert SimplePoker.is_three?(two_ace_and_one)
  end

  test "非三條: A, 2, 3", cards do
      not_three = [cards.s_ace, cards.s_two, cards.s_three]
      refute SimplePoker.is_three?(not_three)
  end

  test "順子: 普通 黑桃2, 黑桃3, 紅桃4", cards do
      normal_straight = [cards.s_two, cards.s_three, cards.h_four]
      assert SimplePoker.is_straight?(normal_straight)
  end

  test "順子: 普通 黑桃A, 黑桃2, 紅桃3", cards do
      one_ace_normal_straight = [cards.s_ace, cards.s_two, cards.h_three]
      assert SimplePoker.is_straight?(one_ace_normal_straight)
  end

  test "順子: 普通 黑桃A, 黑桃2, 紅桃4", cards do
      one_ace_normal_straight = [cards.s_ace, cards.s_two, cards.h_four]
      assert SimplePoker.is_straight?(one_ace_normal_straight)
  end

  test "非順子: 黑桃A, 黑桃2, 紅桃2", cards do
      not_straight = [cards.s_ace, cards.s_two, cards.h_two]
      refute SimplePoker.is_straight?(not_straight)
  end

  test "同花順: 普通", cards do
      normal_flush_straight = [cards.s_two, cards.s_three, cards.s_four]
      assert SimplePoker.is_flush_straight?(normal_flush_straight)    
  end

  test "普通三張", cards do
      normal = [cards.s_two, cards.s_two, cards.h_three]
      assert {:normal, _} = SimplePoker.power(normal, false)
  end

  test "天公9點", cards do
      assert {:tian_gong, 9} = [cards.s_ace, cards.s_eight] |> SimplePoker.power(true) 
      assert {:tian_gong, 9} = [cards.s_four, cards.s_five] |> SimplePoker.power(true)
  end

  test "普通9點", cards do
      assert {:normal, 9} = [cards.s_ace, cards.s_eight] |> SimplePoker.power(false)
  end

  test "single_point", cards do
       assert  1 == cards.s_ace |> SimplePoker.single_point
       assert 10 == cards.s_ten |> SimplePoker.single_point 
       assert 10 == cards.s_jack |> SimplePoker.single_point
  end
  
  test "win?" do
      tian_gong_9 = {:tian_gong, 9}
      tian_gong_8 = {:tian_gong, 8}
      flush_straight = {:flush_straight, 0}
    three = {:three, 0}
    flush = {:flush, 0}
    straight = {:straight, 0}
    normal_9 = {:normal, 9}
    normal_8 = {:normal, 8}

    assert SimplePoker.win?(tian_gong_9, tian_gong_8) 
    refute SimplePoker.win?(tian_gong_9, tian_gong_9)
    refute SimplePoker.win?(tian_gong_8, tian_gong_9)
    assert SimplePoker.win?(tian_gong_9, flush_straight)
    refute SimplePoker.win?(flush_straight, tian_gong_9)

    refute SimplePoker.win?(flush_straight, flush_straight)
    assert SimplePoker.win?(flush_straight, three)
    refute SimplePoker.win?(three, flush_straight)

    assert SimplePoker.win?(three, flush)
    refute SimplePoker.win?(flush, three)

    assert SimplePoker.win?(flush, straight)
    refute SimplePoker.win?(straight, flush)

    assert SimplePoker.win?(straight, normal_9)
    refute SimplePoker.win?(normal_9, straight)

    assert SimplePoker.win?(normal_9, normal_8)
    refute SimplePoker.win?(normal_9, normal_9)
    refute SimplePoker.win?(normal_8, normal_9)
  end

end
simple_poker_test.exs

簡單Elixir遊戲服設計-玩法simple_poker