Skip to content

Commit dd82e56

Browse files
committed
Refactor landlord game flow and state handling
1 parent ae653db commit dd82e56

10 files changed

Lines changed: 2075 additions & 195 deletions

File tree

README.md

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
1-
# 雀阁 · 在线斗地主
1+
# 雀阁 · 纸牌房
22

33
> **Forked from** [laivv/doudizhu](https://github.com/laivv/doudizhu.git)
44
5-
> **Fight the Landlord** — 一桌国风茶馆,三人对坐,落子如雀。
6-
> 基于 Node.js + Vue 2 + Socket.IO 的多人在线斗地主,支持 **真人对战 / AI 陪玩 / 观战 / 智囊推荐 / 国风音画**
5+
> 基于 Node.js + Vue 2 + Socket.IO 的多人在线纸牌房,支持 **动态开房 / 快速匹配 / 好友房号 / 斗地主 / 掼蛋 / 观战 / 国风音画**
76
87

98
---
109

1110
## 特性
1211

13-
- **多桌多人** — 大厅可见所有牌桌,随时入座或离席;同一桌三人到齐自动开局。
14-
- **AI 对手** — 桌内一键「召唤 A I 对手」,自动填空座;真人加入时 AI 自动让座、全员退桌时自动清场。AI 引擎覆盖单/对/三带/顺子/连对/飞机(带单/带对)/4 带 2/炸弹/王炸的完整跟出策略。
12+
- **动态房间** — 玩家可以开公开房、开私密房、输入房号加入好友房,也可以快速入局自动匹配空房。
13+
- **多玩法架构** — 斗地主与掼蛋作为独立玩法接入,后续可继续扩展新的纸牌规则。
14+
- **斗地主** — 三人叫分、底牌、地主/农民阵营、炸弹翻倍、春天结算、AI 陪玩与智囊推荐。
15+
- **掼蛋** — 四人两副牌、对家组队、级牌升级、红桃级牌逢人配、炸弹/同花顺/四王炸、头游队伍升级结算。
16+
- **AI 对手** — 斗地主房内一键「召唤 A I 对手」,自动填空座;真人加入时 AI 自动让座、全员退房时自动清场。
1517
- **观战模式** — 不入座也能旁观对局,棋谱牌势一览无余。
1618
- **智囊推荐** — 自己回合点「智 囊」即可由内置 AI 自动选出最经济的合法跟牌。
1719
- **国风视效** — 玉绿背景、朱漆按钮、鎏金徽印;地主登场金光,农民登场玉色光晕;炸弹/王炸/飞机各自专属字幕特效。
1820
- **Web Audio 音效** — 出牌、不出、叫分、炸弹皆有合成音色,可一键静音。
19-
- **桌面聊天** — 茶馆闲话面板,自由输入或下拉选「快语」短句。
21+
- **房间聊天** — 茶馆闲话面板,自由输入或下拉选「快语」短句。
22+
- **移动端适配** — 大厅、开房、手牌、聊天和操作按钮针对手机竖屏做了响应式布局。
2023
- **可选 SSO** — 内置 JWT 校验入口,便于与 Discuz 等论坛对接(参见 [discuz-sso/README.md](discuz-sso/README.md))。
2124

2225
---
@@ -46,7 +49,12 @@ npm start
4649
http://localhost:8002
4750
```
4851

49-
输入「雅号」后即可进入大厅 → 选桌入座 → 点「准备」或「召唤 A I 对手」开始对局。
52+
输入「雅号」后即可进入大厅:
53+
54+
- 选择「斗地主」或「掼蛋」后点「快速入局」。
55+
- 点「开公开房」等待陌生玩家加入。
56+
- 点「开私密房」后把房号发给朋友。
57+
- 输入好友给你的房号可直接加入。
5058

5159
---
5260

@@ -63,16 +71,25 @@ http://localhost:8002
6371
- **智 囊**:让 AI 自动帮你选牌;若无可压制的牌会提示「建议不出」。
6472
- **不 出**:跳过本轮(仅当上家不是自己时可见)。
6573

66-
### 等待区按钮
74+
### 房间与等待区
6775

6876
- **准 备**:标记自己已就绪;三人全部就绪自动开局。
69-
- **召 唤 A I 对 手**:当桌内有空座时显示,把所有空位填上 AI。
70-
- **请 走 A I**:当桌内有 AI 时显示,清退所有 AI 等真人。
77+
- **召 唤 A I 对 手**:斗地主房内有空座时显示,把所有空位填上 AI。
78+
- **请 走 A I**:斗地主房内有 AI 时显示,清退所有 AI 等真人。
79+
- **房号**:房间顶部显示,私密房可复制房号给好友加入。
7180

7281
### 叫分
7382

7483
听到「叫分」环节时,依次显示可叫分数(1/2/3)和「不叫」按钮,点击即可。
7584

85+
### 掼蛋
86+
87+
- 四人开局,两副牌,每人 27 张。
88+
- 0/2 与 1/3 为固定对家。
89+
- 当前级牌从 2 开始,红桃级牌为逢人配,可参与常规牌型组合。
90+
- 支持单张、对子、三张、三带二、顺子、连对、钢板、炸弹、同花顺、四王炸。
91+
- 头游队伍按名次升级:双下 +3,二三名 +2,其余 +1。
92+
7693
### AI 让座规则
7794

7895
- 真人入座时若该位被 AI 占用且未在游戏中 → AI **拱手让座**
@@ -87,7 +104,7 @@ http://localhost:8002
87104
| --- | --- |
88105
| 服务端 | Node.js · Express · Socket.IO 4 · jsonwebtoken |
89106
| 前端 | Vue 2(CDN 单文件)· jQuery · layer 弹层 |
90-
| 通信 | WebSocket(事件:`SITDOWN` / `PREPARE` / `CALL_SCORE` / `PLAY_CARD` / `USER_MESSAGE` / `SPECTATE` / `ADD_BOTS` / `REMOVE_BOTS` …) |
107+
| 通信 | WebSocket(事件:`CREATE_ROOM` / `JOIN_ROOM` / `QUICK_JOIN` / `SITDOWN` / `PREPARE` / `CALL_SCORE` / `PLAY_CARD` / `USER_MESSAGE` / `SPECTATE` / `ADD_BOTS` / `REMOVE_BOTS` …) |
91108
| 音效 | 原生 Web Audio API(无第三方依赖) |
92109
| 牌型校验 | `static/js/parser.js`(A / AA / AAA / AAAB / AAABB / ABCDE / AABBCC / AAABBB / AAAABC / AAAABBCC / AAAA / KING) |
93110
| AI 决策 | `static/js/ai-suggest.js`(同时供前端「智囊」与服务端「机器人」使用) |
@@ -97,9 +114,10 @@ http://localhost:8002
97114
## 项目结构
98115

99116
```
100-
fight-the-landlord/
117+
quege-card-room/
101118
├── server.js # Express + Socket.IO 入口;含 AI 机器人调度
102119
├── game.js # 游戏状态机(发牌 / 叫分 / 出牌 / 胜负)
120+
├── guandan-game.js # 掼蛋状态机(两副牌 / 级牌 / 逢人配 / 升级)
103121
├── core-ai.js # 服务端 AI 辅助
104122
├── core-validator.js # 服务端牌型校验
105123
├── package.json

discuz-jwt-example.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,14 @@
3131

3232
$issuedAt = time();
3333
$expire = $issuedAt + 60 * 60 * 24; // token valid for 24 hours; tune as needed
34+
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
35+
$host = $_SERVER['HTTP_HOST'] ?? '';
36+
$avatarUrl = $host ? ($scheme . '://' . $host . '/uc_server/avatar.php?uid=' . rawurlencode((string)$uid) . '&size=middle') : '';
3437

3538
$payload = [
3639
'uid' => $uid,
3740
'username' => $username,
41+
'avatarUrl' => $avatarUrl,
3842
'iat' => $issuedAt,
3943
'exp' => $expire,
4044
// you can add more custom claims if needed

discuz-sso/bridge.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,13 @@
143143

144144
// ====== 已登录:签发 JWT 并跳回 ======
145145
$now = time();
146+
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
147+
$host = $_SERVER['HTTP_HOST'] ?? 'zwwx.club';
148+
$avatar = $scheme . '://' . $host . '/uc_server/avatar.php?uid=' . rawurlencode((string)$uid) . '&size=middle';
146149
$payload = [
147150
'uid' => $uid,
148151
'username' => strval($_G['member']['username']),
152+
'avatarUrl' => $avatar,
149153
'iat' => $now,
150154
'exp' => $now + SSO_JWT_TTL,
151155
];

discuz-sso/sso.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ function doudizhu_set_jwt_cookie($uid, $username, $ttl = 86400) {
4343
if (!$uid || !$username) return false;
4444
$issuedAt = time();
4545
$expire = $issuedAt + intval($ttl);
46+
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
47+
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
48+
$avatarUrl = $host ? ($scheme . '://' . $host . '/uc_server/avatar.php?uid=' . rawurlencode((string)$uid) . '&size=middle') : '';
4649
$payload = [
4750
'uid' => intval($uid),
4851
'username' => strval($username),
52+
'avatarUrl' => $avatarUrl,
4953
'iat' => $issuedAt,
5054
'exp' => $expire,
5155
];

0 commit comments

Comments
 (0)