一种傻纸牌游戏的Erlang实现

阅读更多

小时候,曾经玩一种2人的纸牌优秀,洗牌之后,一人一半,然后轮流出1张牌,压在牌桌上,越压越高,如果有人出的牌和前面某张相同的点,就把这两张牌中间的牌一起赢取,收回到自己的牌下面。这样下去直到有一方手中无牌认输。

其实,洗牌之后,就已经注定输赢了。

 

 

-module(cards).
-export([shuffle/0]).
-include("card.hrl").

rand_list(L1, L2)->
    case length(L2) of
    0 -> L1;
    N-> 
        Nth = random:uniform(N),
        Elem = lists:nth(Nth,L2),
        L3 = lists:delete(Elem,L2),
        rand_list([Elem|L1], L3)
    end.
    
create_rand_list()->
    L0 = lists:seq(1,4*13,1),
    random:seed(),
    rand_list([],L0).
    
create_times4_list(L)->
    lists:map(fun (X)->lists:map(fun(Y)->#card{value=X,suit=Y} end,?suit_set) end, L).

make_deck([H|Lpos],L2)->
    if 
    length(Lpos) == 0  ->[lists:nth(H, L2)];
    true->[lists:nth(H, L2)|make_deck(Lpos, L2)]
    end.
        
shuffle()->
    L0 = lists:seq(1,13,1),
    L1 = create_times4_list(L0),    
    L2 = lists:flatten(L1),
    L3=create_rand_list(),
    make_deck(L3,L2).

 

 

-module(game).
-export([play_game/0,dealer/0,player/2]).
-include("card.hrl").

play_game() ->
    P0=spawn(game, dealer, []),
    io:format("spawn dealer ~p~n",[P0]).

dealer() ->
    random:seed(now()),                   
    DealerPid = self(),              
    Deck = cards:shuffle(),
    {P1Cards, P2Cards} = lists:split(trunc(length(Deck) / 2), Deck),
    P1 = spawn(game, player, [DealerPid, P1Cards]),
    io:format("spawn player ~p with ~p~n",[P1, P1Cards]), 
    P2 = spawn(game, player, [DealerPid, P2Cards]),
    io:format("spawn player ~p with ~p~n",[P2, P2Cards]),
    P2!{show_card}, 
    dealer([P1, P2], await_card, P2, []). 

loc(Card, [H|NCards]) ->
    if 
        Card#card.value ==  H#card.value -> 1;
        length(NCards) == 0 ->  
            error_logger:warning_msg("no same card!~n"),
            -1024;
        true  -> loc(Card, NCards) + 1
    end.
    
win_card(H,NCards) ->
    Nth = loc(H, NCards),
    if 
        Nth > 0 ->
            {First, Second} = lists:split(Nth, NCards),
            {[H|First], Second};
        true -> []
    end.

opponent(Pids, Pid)->
    [P1, P2] = Pids,
    if 
        P1 == Pid -> P2;
        true -> P1
    end.
               
dealer(Pids, State, Pid, NCards) ->
    io:format("~p ~p~n",[State, NCards]),
    case State of
        await_card ->          
            receive
                {accept, Pid, Card} ->
                    dealer(Pids, check_cards, Pid, [Card|NCards]);
                {give_up, Pid} ->
                    io:format("~p give up! ~p is the winner~n", [Pid, opponent(Pids, Pid)]),
                    end_game(Pids)
            after 2000 ->
                    io:format("~p timeout! ~p is the winner~n", [Pid, opponent(Pids, Pid)]),
                    end_game(Pids)                                      
            end;
        check_cards ->
            [TopCard|RemCards] =  NCards,
            case lists:member(TopCard#card.value, lists:map(fun(X)->X#card.value end,RemCards)) of
                true ->
                    {WinnedCards, RemtainedCards} = win_card(TopCard, RemCards),
                    Pid ! {give_card, WinnedCards},
                    dealer(Pids, await_card, Pid, RemtainedCards);        
                false ->
                    opponent(Pids,Pid)! {show_card},
                    dealer(Pids, await_card, opponent(Pids,Pid), NCards)
            end
    end.
    
end_game(Pids) ->
    lists:foreach(fun(Process) -> exit(Process, kill) end, Pids),
    io:format("Game finished.~n").


player(Dealer, Cards) ->
    receive
        {show_card} ->
            if length(Cards) =< 0 ->         
                Dealer!{give_up, self()};
                true ->
                [H|RemCards] = Cards,                  
                Dealer!{accept, self(), H},
                player(Dealer, RemCards)
            end;
        {give_card, GivenCards} ->
            [H|RemCards] = Cards++GivenCards,
            Dealer!{accept, self(), H},
            player(Dealer, RemCards)
    end. 

 

card.hrl:

 

-define(suit_set, ["Clubs","Diamonds","Hearts","Spades"]).
-record(card, {value, suit}).
 

 

 

>erlc cards.erl

>erlc games.erl

>erl

game:play_game().

 

<0.322.0> give up! <0.323.0> is the winner

Game finished

 

    

 

  • card-game.zip (1.8 KB)
  • 下载次数: 1

你可能感兴趣的:(Erlang,纸牌)