0

2 プレイヤーのターンベースのゲームを処理するために、Erlang で単純なフレームワークを開発しています。コードは次のとおりです。

-module(game).
-export([start_server/0,generate_server/0,add_player/0,remove_player/0]).


generate_server() ->
Table_num = 0,
Player_num = 0,
io:format("Server generated...~n", []),
io:format("The current number of tables is ~w~n", [Table_num]),
io:format("The current number of players is ~w~n", [Player_num]),
receive
    login ->
        io:format("A new player has connected!~n", []),
        New = Player_num + 1,
        io:format("The current number of players is ~w~n", [New]);
    logout ->
        io:format("You have beeen succesfully disconnected~n", [])
end.



start_server() ->
    io:format("Welcome player!~nInitializing game...~n", []),
    io:format("Generating server...~n", []),
    register(server,spawn(game, generate_server, [])).


add_player() ->
    server ! login.


remove_player() ->
    server ! logout.

このコードを実行すると、主な問題が 2 つあります。

  1. add_player() を実行してから remove_player() を実行すると、この 2 番目の関数が例外でクラッシュします。
  2. 1 つのターミナル ウィンドウでプログラムを起動し、2 つ目のターミナル ウィンドウで add_player() を実行すると、エラーが発生します。複数の端末ウィンドウで実行できるようにするにはどうすればよいですか?

どんな助けでも大歓迎です。

4

2 に答える 2

3

1/ サーバーにループはありません。開始すると、いくつかの印刷の後、受信ステートメントを待機します。

ログイン メッセージを受信すると、操作が実行され、サーバー コードが終了します。プロセスは終了し、登録されていません。すべての変数が消え、VM がメモリをクリーンアップします...

そのため、後でサーバーにメッセージを送信するプロセスはクラッシュします。これは、登録されていない名前を使用しているためです。

これを機能させるには、接続されているプレーヤーのリストを (リストなどに) 保持し、このリストをパラメーターとしてサーバー ループを呼び出す必要があります。

generate_server(Tlist,Plist) ->
io:format("The current number of tables is ~w~n", [length(Tlist)]),
io:format("The current number of players is ~w~n", [length(Plist)]),
receive
    {login,Name} ->
        io:format("A new player ~p has connected!~n", [Name]),
        generate_server(Tlist,[Name|Plist]);
    {logout,Name} ->
        io:format("You have beeen succesfully disconnected~n", []),
        generate_server(Tlist,lists:delete(Name,Plist))
end.

そして、generate_server への呼び出しは、

register(server,spawn(game, generate_server, [[],[]]))

2/ 2 つの異なるノード間で erlang メッセージを使用するには、次のことを行う必要があります。

  • 同じアーラン クッキーを共有する
  • ノードを検出します (たとえば、netadm を使用)
  • サーバーの pid を取得するか、golbal の登録名を使用します

http://learnyousomeerlang.com/distribunomicon#alone-in-the-darkで例を参照してください。

于 2012-12-05T20:04:22.200 に答える
1

loopサーバーの本文がありませんでした。サーバーがメッセージを 1 つだけ受信して終了するため、プログラムがクラッシュします。以下のサーバーの別のバージョンを検討してください。

generate_server() ->
    テーブル番号 = 0、
    Player_num = 0、
    io:format("サーバー生成...~n", []),
    io:format("現在のテーブル数は ~w~n", [Table_num]),
    io:format("現在のプレイヤー数は ~w~n", [Player_num]),
    ループ([])。
ループ(プレイヤー)-> 受け取る {From,{login,PlayerId}} -> io:format("新しいプレイヤーが接続しました!~n", []), io:format("現在のプレイヤー数は ~w~n", [新規]), NewPlayers = ケースリスト:member(PlayerId,Players) of 真 -> から !{login_failed,exists}, プレーヤー; 偽 -> から !{login_success,true}, [PlayerId|プレイヤー] 終わり、 ループ (NewPlayers); {From,{logout,PlayerId}} -> NewPlayers = ケースリスト:member(PlayerId,Players) of 真 -> から !{ログアウト、OK}、 プレーヤー -- [PlayerId]; 偽 -> から !{ログアウト、失敗}、 プレイヤー 終了、
ループ (NewPlayers); _ -> ループ(プレイヤー) 終わり。
そこには; それははるかに良く見えます。

于 2012-12-06T05:57:49.047 に答える