1. 牌型识别: 新增三带一对、飞机、飞机带单/带对、四带二、四带两对 2. 获胜显示: 先显示最后出牌1秒后再弹出获胜对话框 3. 出牌区布局: 横向排列并换行 4. 移动端重连: 切回前台时自动重连WebSocket 5. 更新文档: README.md和API.md补充新增牌型
448 lines
7.0 KiB
Markdown
448 lines
7.0 KiB
Markdown
# 斗地主残局版 API 文档
|
||
|
||
## 基础信息
|
||
|
||
- 基础URL: `http://<host>/api`
|
||
- 响应格式: JSON
|
||
|
||
## 响应格式
|
||
|
||
所有API响应遵循统一格式:
|
||
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"code": 0,
|
||
"message": "success",
|
||
"data": { ... }
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| status | int | HTTP状态码 |
|
||
| code | int | 业务状态码 (0=成功, 1=失败) |
|
||
| message | string | 提示信息 |
|
||
| data | object | 实际业务数据 |
|
||
|
||
---
|
||
|
||
## 认证相关 API
|
||
|
||
### 获取验证码
|
||
|
||
**GET** `/api/auth/captcha`
|
||
|
||
响应:
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"code": 0,
|
||
"message": "success",
|
||
"data": {
|
||
"captchaId": "abc123",
|
||
"image": "data:image/png;base64,..."
|
||
}
|
||
}
|
||
```
|
||
|
||
### 用户注册
|
||
|
||
**POST** `/api/auth/register`
|
||
|
||
请求体:
|
||
```json
|
||
{
|
||
"username": "testuser",
|
||
"password": "123456",
|
||
"nickname": "测试玩家",
|
||
"captcha": "ABCD",
|
||
"captchaId": "abc123"
|
||
}
|
||
```
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| username | string | 是 | 用户名,3-20字符 |
|
||
| password | string | 是 | 密码,至少6位 |
|
||
| nickname | string | 是 | 昵称 |
|
||
| captcha | string | 是 | 验证码 |
|
||
| captchaId | string | 是 | 验证码ID |
|
||
|
||
响应:
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"code": 0,
|
||
"message": "success",
|
||
"data": {
|
||
"token": "xxx",
|
||
"userId": "xxx",
|
||
"username": "testuser",
|
||
"nickname": "测试玩家"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 用户登录
|
||
|
||
**POST** `/api/auth/login`
|
||
|
||
请求体:
|
||
```json
|
||
{
|
||
"username": "testuser",
|
||
"password": "123456",
|
||
"captcha": "ABCD",
|
||
"captchaId": "abc123"
|
||
}
|
||
```
|
||
|
||
响应: 同注册
|
||
|
||
### 验证Token
|
||
|
||
**GET** `/api/auth/validate`
|
||
|
||
请求头: `Authorization: Bearer {token}`
|
||
|
||
响应:
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"code": 0,
|
||
"message": "success",
|
||
"data": {
|
||
"userId": "xxx",
|
||
"username": "testuser",
|
||
"nickname": "测试玩家"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 退出登录
|
||
|
||
**POST** `/api/auth/logout`
|
||
|
||
请求头: `Authorization: Bearer {token}`
|
||
|
||
---
|
||
|
||
## 房间相关 API
|
||
|
||
> 注意: 所有房间相关 API 需要在请求头中携带 `Authorization: Bearer {token}`
|
||
|
||
### 创建房间
|
||
|
||
**POST** `/api/rooms`
|
||
|
||
请求体:
|
||
```json
|
||
{
|
||
"playerName": "玩家昵称",
|
||
"maxPlayers": 4
|
||
}
|
||
```
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| playerName | string | 是 | 玩家昵称 |
|
||
| maxPlayers | int | 否 | 最大玩家数,默认4,范围2-10 |
|
||
|
||
响应:
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"code": 0,
|
||
"message": "success",
|
||
"data": {
|
||
"roomId": "a1b2c3d4e5f6g7h8",
|
||
"playerId": "i9j0k1l2m3n4o5p6"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 加入房间
|
||
|
||
**POST** `/api/rooms/{roomId}/join`
|
||
|
||
请求体:
|
||
```json
|
||
{
|
||
"playerName": "玩家昵称"
|
||
}
|
||
```
|
||
|
||
响应:
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"code": 0,
|
||
"message": "success",
|
||
"data": {
|
||
"roomId": "a1b2c3d4e5f6g7h8",
|
||
"playerId": "q7r8s9t0u1v2w3x4"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 离开房间
|
||
|
||
**POST** `/api/rooms/leave`
|
||
|
||
请求头: `Authorization: Bearer {token}`
|
||
|
||
响应:
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"code": 0,
|
||
"message": "success",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 获取当前房间
|
||
|
||
**GET** `/api/rooms/current`
|
||
|
||
请求头: `Authorization: Bearer {token}`
|
||
|
||
用于检查用户当前是否在房间中。如果用户之前创建了房间但未离开,可以获取房间信息并自动重新连接。
|
||
|
||
响应(在房间中):
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"code": 0,
|
||
"message": "success",
|
||
"data": {
|
||
"roomId": "a1b2c3d4",
|
||
"playerId": "i9j0k1l2"
|
||
}
|
||
}
|
||
```
|
||
|
||
响应(不在房间中):
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"code": 0,
|
||
"message": "success",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 错误响应示例
|
||
|
||
```json
|
||
{
|
||
"status": 400,
|
||
"code": 1,
|
||
"message": "room not found",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## WebSocket API
|
||
|
||
**连接地址**: `ws://<host>/api/ws?roomId={roomId}&playerId={playerId}`
|
||
|
||
### 消息格式
|
||
|
||
所有消息为JSON格式:
|
||
|
||
```json
|
||
{
|
||
"type": "消息类型",
|
||
"playerId": "玩家ID",
|
||
"roomId": "房间ID",
|
||
"data": { ... },
|
||
"timestamp": 1708123456
|
||
}
|
||
```
|
||
|
||
### 消息类型
|
||
|
||
| 类型 | 方向 | 说明 |
|
||
|------|------|------|
|
||
| ready | 客户端→服务器 | 准备/取消准备 |
|
||
| play | 客户端→服务器 | 出牌 |
|
||
| pass | 客户端→服务器 | 不出 |
|
||
| chat | 双向 | 聊天消息 |
|
||
| state | 服务器→客户端 | 游戏状态更新 |
|
||
| gameOver | 服务器→客户端 | 游戏结束 |
|
||
| leave | 服务器→客户端 | 玩家离开房间 |
|
||
| error | 服务器→客户端 | 错误消息 |
|
||
|
||
### 准备
|
||
|
||
```json
|
||
{
|
||
"type": "ready",
|
||
"playerId": "xxx",
|
||
"roomId": "xxx",
|
||
"data": { "ready": true }
|
||
}
|
||
```
|
||
|
||
当所有玩家都准备后,游戏自动开始。
|
||
|
||
### 出牌
|
||
|
||
```json
|
||
{
|
||
"type": "play",
|
||
"playerId": "xxx",
|
||
"roomId": "xxx",
|
||
"data": {
|
||
"cards": [
|
||
{ "suit": 0, "value": 14 },
|
||
{ "suit": 1, "value": 14 }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 不出
|
||
|
||
```json
|
||
{
|
||
"type": "pass",
|
||
"playerId": "xxx",
|
||
"roomId": "xxx"
|
||
}
|
||
```
|
||
|
||
注意: 只能在上家出牌后才能"不出",自己最后出牌时不能"不出"。
|
||
|
||
### 聊天
|
||
|
||
客户端发送:
|
||
```json
|
||
{
|
||
"type": "chat",
|
||
"playerId": "xxx",
|
||
"roomId": "xxx",
|
||
"data": "消息内容"
|
||
}
|
||
```
|
||
|
||
服务器推送:
|
||
```json
|
||
{
|
||
"type": "chat",
|
||
"data": {
|
||
"playerId": "xxx",
|
||
"playerName": "玩家昵称",
|
||
"message": "消息内容"
|
||
},
|
||
"timestamp": 1708123456
|
||
}
|
||
```
|
||
|
||
### 游戏状态 (服务器推送)
|
||
|
||
```json
|
||
{
|
||
"type": "state",
|
||
"data": {
|
||
"id": "a1b2c3d4e5f6g7h8",
|
||
"players": [
|
||
{
|
||
"id": "xxx",
|
||
"name": "玩家1",
|
||
"cards": [...],
|
||
"cardCount": 5,
|
||
"isReady": true,
|
||
"isOnline": true
|
||
}
|
||
],
|
||
"currentTurn": 0,
|
||
"state": 1,
|
||
"lastPlay": {
|
||
"playerId": "xxx",
|
||
"cards": [...],
|
||
"cardType": 2
|
||
},
|
||
"roundCount": 1,
|
||
"maxPlayers": 4
|
||
},
|
||
"timestamp": 1708123456
|
||
}
|
||
```
|
||
|
||
注意: 只有当前玩家能看到自己的手牌(cards),其他玩家只能看到牌数(cardCount)。
|
||
|
||
### 游戏结束 (服务器推送)
|
||
|
||
```json
|
||
{
|
||
"type": "gameOver",
|
||
"data": {
|
||
"winnerId": "xxx"
|
||
},
|
||
"timestamp": 1708123456
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 数据类型
|
||
|
||
### Card (牌)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| suit | int | 花色 |
|
||
| value | int | 点数 |
|
||
|
||
花色值:
|
||
- 0: 红桃 ♥
|
||
- 1: 方块 ♦
|
||
- 2: 梅花 ♣
|
||
- 3: 黑桃 ♠
|
||
- 4: 王 (Joker)
|
||
- 5: 超人强 (Super)
|
||
|
||
点数值:
|
||
- 3-10: 对应点数
|
||
- 11: J
|
||
- 12: Q
|
||
- 13: K
|
||
- 14: A
|
||
- 15: 2
|
||
- 16: 小王
|
||
- 17: 大王
|
||
- 18: 超人强
|
||
|
||
### CardType (牌型)
|
||
|
||
| 值 | 说明 |
|
||
|----|------|
|
||
| 0 | 无效 |
|
||
| 1 | 单牌 |
|
||
| 2 | 对子 |
|
||
| 3 | 三张 (未使用) |
|
||
| 4 | 三带一 |
|
||
| 5 | 三带一对 |
|
||
| 6 | 顺子 |
|
||
| 7 | 连对 |
|
||
| 8 | 炸弹 |
|
||
| 9 | 火箭 |
|
||
| 10 | 飞机 |
|
||
| 11 | 飞机带单 |
|
||
| 12 | 飞机带对 |
|
||
| 13 | 四带二 |
|
||
| 14 | 四带两对 |
|
||
|
||
### RoomState (房间状态)
|
||
|
||
| 值 | 说明 |
|
||
|----|------|
|
||
| 0 | 等待中 |
|
||
| 1 | 游戏中 |
|
||
| 2 | 已结束 |
|