简单Elixir游戏服设计-玩法simple_poker

simple_table.ex

测试代码 simple_poker_test.exs

seat.ex

simple_poker_test.exs

葡京游戏网址 1葡京游戏网址 2

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

临时是不管编写了,后续需要再调整。

上回介绍了玩法,现在编制了玩法的简短建模。

台子部分

葡京游戏网址 3葡京游戏网址 4

建模桌子和坐席

成功现在感到目前还尚无动用umbrella的画龙点睛(也许未来会意识必要吗),model 应用完全可以统一到game_server。

座位部分

simple_poker.ex

model 里新建simple_葡京游戏网址,table.ex 和 seat.ex, 项目里新增对应的test.

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_table_test.exs

model 应用新增 simple_poker.ex , 代码不多,做了点简单注释,可以贴下

他日该起游戏过程了。

代码还在https://github.com/rubyist1982/simple 上。

葡京游戏网址 5葡京游戏网址 6

葡京游戏网址 7葡京游戏网址 8

葡京游戏网址 9葡京游戏网址 10

 下回该建模游戏桌了

代码相比较短小,直接贴吧。

defmodule Seat do
    def init(player) do
        %{
            id: player |> Player.get_id,
            player: player,
            score: 0,
        }
    end

    def get_id(seat), do: seat.id

    def update_player(seat, player), do: put_in(seat.player, player)
    def get_player(seat), do: seat.player
    def get_player_id(seat), do: seat.player |> Player.get_id

    def add_score(seat, num) when num >=0 , do: update_in(seat.score, &(&1 + num))
    def sub_score(seat, num) when num >= 0 , do: update_in(seat.score, &(&1 - num))
    def get_score(seat), do: seat.score

end
defmodule SimpleTable do

    def init() do
        %{
            cards: SimplePoker.init_cards,
            creator: nil,
            seat_map: %{},
            seat_order: []
        }
    end

    def seat_count(table), do: table.seat_order |> Enum.count
    def seat_order(table), do: table.seat_order

    def find_seat(table, %{} = player), do: find_seat(table, player |> Player.get_id)
    def find_seat(table, player_id), do: table.seat_map[player_id]

    def add_seat(table, player) do
        seat = Seat.init(player)
        seat_id = seat |> Seat.get_id
        table = put_in(table.seat_map[seat_id], seat)
        add_to_order(table, seat_id)
    end

    def add_to_order(table, seat_id), do: update_in(table.seat_order, &(&1 ++ [seat_id]))

    def remove_seat(table, %{} = player), do: remove_seat(table, player |> Player.get_id)
    def remove_seat(table, player_id) do
        table = update_in(table.seat_map, fn m -> Map.delete(m, player_id) end)
        update_in(table.seat_order, fn o -> List.delete(o, player_id) end)
    end


end
defmodule SeatTest do
  use ExUnit.Case
  doctest Seat

  setup do

    %{seat: Seat.init(Player.init)}
  end

  test "init", %{seat: seat} do
    assert 0 == seat |> Seat.get_score
  end

  test "add_and_remove_score", %{seat: seat} do
    num = 10
    old_score = seat |> Seat.get_score
    add_score_seat = seat |> Seat.add_score(num) 
    assert old_score + num == add_score_seat |> Seat.get_score
    sub_score_seat = seat |> Seat.sub_score(num)
    assert old_score - num == sub_score_seat |> Seat.get_score
  end

end
defmodule SimpleTableTest do
  use ExUnit.Case
  doctest SimpleTable

  def create_player(id), do: Player.init |> Player.set_id(id)

  setup do
    %{
        table: SimpleTable.init,
          player1: create_player(1),
          player2: create_player(2),
          player3: create_player(3),
          player4: create_player(4)
    }
  end

  test "init", %{table: table} do
      assert 0 = table |> SimpleTable.seat_count
  end

  test "add_and_remove_seat", %{table: table, player1: player1, player2: player2, player3: player3, player4: player4} do
        table = table |> SimpleTable.add_seat(player1) 
                        |> SimpleTable.add_seat(player2)
                        |> SimpleTable.add_seat(player3)
                        |> SimpleTable.add_seat(player4)

        assert 4 == SimpleTable.seat_count(table)
        expect_seat_order = [player1 |> Player.get_id,
                player2 |> Player.get_id,
                  player3 |> Player.get_id,
                  player4 |> Player.get_id]
        assert ^expect_seat_order = SimpleTable.seat_order(table)

        new_expect_seat_order = [
                player2 |> Player.get_id,
                  player3 |> Player.get_id,
                  player4 |> Player.get_id
                ]

        table = table |> SimpleTable.remove_seat(player1)
      assert 3 == SimpleTable.seat_count(table)
      assert ^new_expect_seat_order = SimpleTable.seat_order(table)
  end 


end

seat_test.exs

葡京游戏网址 11葡京游戏网址 12