浏览代码

ft: 调整

master
SisMaker 1 个月前
父节点
当前提交
401e7155cc
共有 9 个文件被更改,包括 528 次插入4 次删除
  1. +129
    -0
      README.md
  2. +97
    -0
      README_USAGE.md
  3. +13
    -1
      src/ai_player.erl
  4. +34
    -0
      src/ai_supervisor.erl
  5. +8
    -1
      src/cardSrv_sup.erl
  6. +11
    -0
      src/game_core.erl
  7. +72
    -2
      src/game_manager.erl
  8. +123
    -0
      src/player_manager.erl
  9. +41
    -0
      src/start_system.erl

+ 129
- 0
README.md 查看文件

@ -15,6 +15,135 @@ Build
本项目是一个基于Erlang开发的智能斗地主游戏系统,集成了深度学习、并行计算、性能监控和可视化分析等先进功能。系统采用模块化设计,具有高可扩展性和可维护性。
## 系统架构
### 核心模块
1. **游戏核心模块**
- cards.erl: 牌类操作
- card_rules.erl: 游戏规则
- game_server.erl: 游戏服务器
- player.erl: 玩家管理
- game_core.erl: 游戏核心逻辑
- game_logic.erl: 游戏逻辑处理
- card_checker.erl: 牌型检查
2. **AI系统模块**
- ai_core.erl: AI核心引擎
- ai_player.erl: AI玩家实现
- ai_strategy.erl: AI策略基础
- ai_optimizer.erl: AI优化器
- doudizhu_ai_strategy.erl: 斗地主专用AI策略
- auto_player.erl: 自动玩家
3. **系统支持模块**
- room_manager.erl: 房间管理
- game_manager.erl: 游戏管理
- score_system.erl: 积分系统
- optimizer.erl: 系统优化
- system_supervisor.erl: 系统监督
## 功能特性
### 1. 基础游戏功能
- 完整的斗地主规则实现
- 多人游戏支持
- 房间管理系统
- 积分系统
### 2. AI系统
- 多级别AI玩家(简单、普通、困难)
- 深度学习策略
- 自适应游戏策略
- 多种AI性格特征
### 3. 系统性能
#### 3.1 并行计算
- 多核心利用
- 任务分发
- 负载均衡
#### 3.2 性能监控
- 实时性能指标收集
- 自动化性能分析
- 告警系统
- 性能报告生成
## 已实现功能列表
### 游戏核心功能
- [x] 完整的斗地主规则实现
- 支持所有标准牌型(单牌、对子、三张、三带一、三带二、顺子、连对、飞机、炸弹、火箭等)
- 牌型大小比较
- 出牌规则验证
- [x] 多玩家支持
- 支持3人标准斗地主
- 玩家状态管理
- 回合控制
- [x] 房间管理
- 创建房间
- 加入/离开房间
- 房间状态管理
- 房间列表查询
- [x] 积分系统
- 玩家积分记录
- 胜负统计
- 排行榜功能
- 积分奖惩机制
### AI功能
- [x] AI玩家实现
- 基础AI行为
- 多级别难度(简单、普通、困难)
- 思考时间模拟
- AI名称生成
- [x] 多种AI策略
- 角色感知(地主/农民)
- 局势评估
- 手牌价值分析
- 出牌决策
- [x] 自适应学习
- 对手行为分析
- 策略调整
- 胜率预估
- [x] 策略优化
- 手牌组合优化
- 出牌时机控制
- 关键牌保留
### 系统功能
- [x] 游戏服务器
- 游戏创建
- 玩家加入
- 游戏流程控制
- 游戏状态管理
- [x] 并行计算
- AI决策并行化
- 多游戏并行处理
- 资源分配
- [x] 性能监控
- 系统负载监控
- 响应时间统计
- 资源使用率监控
- [x] 可视化分析
- 游戏数据统计
- 玩家行为分析
- AI性能评估
## 待优化功能
1. 分布式系统支持
2. 数据持久化
3. 更多AI算法
4. Web界面
5. 移动端支持
6. 安全性增强
7. 容错机制
8. 日志系统
## 错误处理
系统实现了基本的错误处理机制:
- 游戏异常处理
- AI系统容错
- 并行计算错误恢复
- 性能监控告警

+ 97
- 0
README_USAGE.md 查看文件

@ -0,0 +1,97 @@
# 斗地主AI系统使用指南
## 系统概述
本系统是一个基于Erlang实现的斗地主游戏AI系统,支持AI玩家自动对战。系统包含完整的斗地主规则实现、多玩家支持、房间管理和AI决策引擎。
## 系统启动
### 启动整个系统
在Erlang shell中执行以下命令启动系统:
```erlang
start_system:start().
```
成功启动后,将看到以下输出:
```
Starting cardSrv system...
System started successfully!
{ok,started}
```
### 启动AI游戏
启动系统后,可以创建一个全AI玩家的游戏:
```erlang
start_system:start_ai_game().
```
成功创建AI游戏后,将看到以下输出:
```
Creating an AI-only game...
AI game created successfully with ID: 1
{ok,1}
```
系统会自动创建三个AI玩家并开始游戏。AI玩家会根据游戏规则和策略自动出牌,直到游戏结束。
### 停止系统
要停止系统,执行以下命令:
```erlang
start_system:stop().
```
## 系统组件
系统主要包含以下组件:
1. **游戏核心模块**:实现斗地主游戏规则和逻辑
2. **AI系统模块**:实现AI决策和策略
3. **系统支持模块**:提供房间管理、游戏管理和系统监督
## 开发指南
### 编译系统
在项目根目录执行以下命令编译系统:
```bash
rebar3 compile
```
### 运行测试
执行以下命令运行测试套件:
```erlang
test_suite:run_full_test().
```
### 验证AI性能
要验证AI系统的性能,可以执行:
```erlang
test_suite:validate_ai_performance(ai_core).
```
## 故障排除
如果系统启动失败,请检查:
1. 确保所有依赖模块已正确编译
2. 检查系统日志查看详细错误信息
3. 确保没有端口冲突
## 注意事项
- 系统目前仅支持3人标准斗地主
- AI玩家的决策基于概率和策略,不保证最优解
- 系统仍在开发中,可能存在未知问题

+ 13
- 1
src/ai_player.erl 查看文件

@ -2,7 +2,7 @@
-behaviour(gen_server).
-export([start_link/1, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([create_ai_player/1, play_turn/1]).
-export([create_ai_player/1, play_turn/1, init/1]).
-record(state, {
name,
@ -31,6 +31,18 @@ create_ai_player(Difficulty) ->
play_turn(AiPid) ->
gen_server:cast(AiPid, play_turn).
%% AI玩家
init(Type) ->
Name = generate_ai_name(),
{ok, Pid} = start_link(Name),
Difficulty = case Type of
basic -> normal;
advanced -> hard;
_ -> normal
end,
gen_server:cast(Pid, {set_difficulty, Difficulty}),
Pid.
%% Callbacks
init([Name]) ->
{ok, #state{name = Name}}.

+ 34
- 0
src/ai_supervisor.erl 查看文件

@ -0,0 +1,34 @@
-module(ai_supervisor).
-behaviour(supervisor).
-export([start_link/0, init/1]).
-export([start_ai/1, stop_ai/1]).
%% API
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%% AI玩家
start_ai(Difficulty) ->
supervisor:start_child(?MODULE, [Difficulty]).
%% AI玩家
stop_ai(AiPid) ->
supervisor:terminate_child(?MODULE, AiPid).
%% Callbacks
init([]) ->
SupFlags = #{strategy => simple_one_for_one,
intensity => 10,
period => 60},
ChildSpecs = [
#{id => ai_player,
start => {ai_player, create_ai_player, []},
restart => temporary,
shutdown => 5000,
type => worker,
modules => [ai_player]}
],
{ok, {SupFlags, ChildSpecs}}.

+ 8
- 1
src/cardSrv_sup.erl 查看文件

@ -29,7 +29,14 @@ init([]) ->
SupFlags = #{strategy => one_for_all,
intensity => 0,
period => 1},
ChildSpecs = [],
ChildSpecs = [
#{id => system_supervisor,
start => {system_supervisor, start_link, []},
restart => permanent,
shutdown => 5000,
type => supervisor,
modules => [system_supervisor]}
],
{ok, {SupFlags, ChildSpecs}}.
%% internal functions

+ 11
- 0
src/game_core.erl 查看文件

@ -104,6 +104,17 @@ analyze_complex_pattern(Cards) ->
get_game_state(GameId) ->
%
{ok, #game_state{}}.
%%
init_game_state() ->
%
#game_state{
players = [],
current_player = undefined,
last_play = [],
played_cards = [],
stage = waiting,
landlord_cards = []
}.
%%
is_valid_play(Cards, LastPlay) ->

+ 72
- 2
src/game_manager.erl 查看文件

@ -1,8 +1,18 @@
-module(game_manager).
-export([start_game/3, handle_play/2, end_game/1]).
-behaviour(gen_server).
-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([start_game/3, handle_play/2, end_game/1, create_ai_game/0]).
-include("../include/game_records.hrl").
%% API
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
%% AI玩家的游戏
create_ai_game() ->
gen_server:call(?MODULE, create_ai_game).
% 使include文件中定义的game_manager_state记录
start_game(Player1, Player2, Player3) ->
@ -188,4 +198,64 @@ get_ai_play(AIPlayer, GameManagerState) ->
%% AI知识
update_ai_knowledge(AIPlayer, Play) ->
% AI对游戏的认知
ai_core:update_knowledge(AIPlayer, Play).
ai_core:update_knowledge(AIPlayer, Play).
%% Callbacks
init([]) ->
%
{ok, #{active_games => #{}, game_count => 0}}.
handle_call(create_ai_game, _From, State = #{active_games := Games, game_count := Count}) ->
% AI玩家
{ok, AI1} = ai_player:create_ai_player(normal),
{ok, AI2} = ai_player:create_ai_player(normal),
{ok, AI3} = ai_player:create_ai_player(hard),
%
GameState = start_game(AI1, AI2, AI3),
GameId = Count + 1,
%
NewGames = maps:put(GameId, GameState, Games),
%
spawn(fun() -> auto_game_loop(GameId, GameState) end),
{reply, {ok, GameId}, State#{active_games => NewGames, game_count => GameId}};
handle_call(_Request, _From, State) ->
{reply, {error, unknown_call}, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%
auto_game_loop(GameId, GameState) ->
%
case is_game_over(GameState#game_manager_state.current_state) of
true ->
%
end_game(GameState);
false ->
%
CurrentPlayer = get_current_player(GameState),
% AI自动出牌
AIPlay = get_ai_play(CurrentPlayer, GameState),
NewState = handle_play(GameState, AIPlay),
% 使
timer:sleep(500),
%
auto_game_loop(GameId, NewState)
end.

+ 123
- 0
src/player_manager.erl 查看文件

@ -0,0 +1,123 @@
-module(player_manager).
-behaviour(gen_server).
-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([create_player/1, delete_player/1, get_player/1, list_players/0]).
-record(state, {
players = #{} % Map: PlayerId -> PlayerInfo
}).
-record(player_info, {
id,
name,
score = 0,
games_played = 0,
wins = 0,
losses = 0,
status = offline % offline | online | in_game
}).
%% API
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
create_player(Name) ->
gen_server:call(?MODULE, {create_player, Name}).
delete_player(PlayerId) ->
gen_server:call(?MODULE, {delete_player, PlayerId}).
get_player(PlayerId) ->
gen_server:call(?MODULE, {get_player, PlayerId}).
list_players() ->
gen_server:call(?MODULE, list_players).
%% Callbacks
init([]) ->
{ok, #state{}}.
handle_call({create_player, Name}, _From, State = #state{players = Players}) ->
PlayerId = generate_player_id(),
PlayerInfo = #player_info{
id = PlayerId,
name = Name,
status = online
},
NewPlayers = maps:put(PlayerId, PlayerInfo, Players),
{reply, {ok, PlayerId}, State#state{players = NewPlayers}};
handle_call({delete_player, PlayerId}, _From, State = #state{players = Players}) ->
case maps:is_key(PlayerId, Players) of
true ->
NewPlayers = maps:remove(PlayerId, Players),
{reply, ok, State#state{players = NewPlayers}};
false ->
{reply, {error, player_not_found}, State}
end;
handle_call({get_player, PlayerId}, _From, State = #state{players = Players}) ->
case maps:find(PlayerId, Players) of
{ok, PlayerInfo} ->
{reply, {ok, PlayerInfo}, State};
error ->
{reply, {error, player_not_found}, State}
end;
handle_call(list_players, _From, State = #state{players = Players}) ->
PlayerList = maps:values(Players),
{reply, {ok, PlayerList}, State};
handle_call(_Request, _From, State) ->
{reply, {error, unknown_call}, State}.
handle_cast({update_player_status, PlayerId, Status}, State = #state{players = Players}) ->
NewPlayers = case maps:find(PlayerId, Players) of
{ok, PlayerInfo} ->
maps:put(PlayerId, PlayerInfo#player_info{status = Status}, Players);
error ->
Players
end,
{noreply, State#state{players = NewPlayers}};
handle_cast({update_player_stats, PlayerId, GameResult}, State = #state{players = Players}) ->
NewPlayers = case maps:find(PlayerId, Players) of
{ok, PlayerInfo = #player_info{games_played = GamesPlayed, wins = Wins, score = Score}} ->
NewGamesPlayed = GamesPlayed + 1,
{NewWins, NewScore} = case GameResult of
win -> {Wins + 1, Score + 10};
loss -> {Wins, Score - 5};
draw -> {Wins, Score + 2}
end,
maps:put(PlayerId, PlayerInfo#player_info{
games_played = NewGamesPlayed,
wins = NewWins,
score = NewScore
}, Players);
error ->
Players
end,
{noreply, State#state{players = NewPlayers}};
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%
%% ID
generate_player_id() ->
% 使ID
{{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(),
Random = rand:uniform(1000),
list_to_binary(io_lib:format("player_~4..0B~2..0B~2..0B~2..0B~2..0B~2..0B~4..0B",
[Year, Month, Day, Hour, Minute, Second, Random])).

+ 41
- 0
src/start_system.erl 查看文件

@ -0,0 +1,41 @@
-module(start_system).
-export([start/0, start_ai_game/0, stop/0]).
%%
start() ->
io:format("Starting cardSrv system...~n"),
%
case application:ensure_all_started(cardSrv) of
{ok, _} ->
io:format("System started successfully!~n"),
{ok, started};
{error, Reason} ->
io:format("Failed to start system: ~p~n", [Reason]),
{error, Reason}
end.
%% AI玩家的游戏
start_ai_game() ->
io:format("Creating an AI-only game...~n"),
%
case start() of
{ok, _} ->
% AI游戏
case game_manager:create_ai_game() of
{ok, GameId} ->
io:format("AI game created successfully with ID: ~p~n", [GameId]),
{ok, GameId};
{error, Reason} ->
io:format("Failed to create AI game: ~p~n", [Reason]),
{error, Reason}
end;
{error, Reason} ->
{error, Reason}
end.
%%
stop() ->
io:format("Stopping cardSrv system...~n"),
application:stop(cardSrv),
io:format("System stopped.~n"),
ok.

正在加载...
取消
保存