4.7 KiB
4.7 KiB
斗地主残局版 - AGENTS.md
1. 项目结构
doudizhu-server/
├── app/ # Go后端
│ ├── cmd/main.go # 程序入口
│ ├── internal/
│ │ ├── models/ # 数据模型(Card, Room, Player等)
│ │ ├── game/ # 游戏逻辑(牌型判断、对局管理)
│ │ ├── handlers/ # HTTP API处理器
│ │ └── ws/ # WebSocket处理
│ ├── Dockerfile
│ └── go.mod
├── nginx/nginx.conf # Nginx反向代理配置
├── nginx/html/ # 静态文件(HTML/CSS/JS)
├── compose.yaml
├── README.md
└── API.md
2. 构建与运行命令
# 本地开发(需先启动Redis)
docker run -d --name redis -p 6379:6379 redis:7-alpine
cd doudizhu-server/app && go mod tidy && go run ./cmd
# Docker部署
cd doudizhu-server && docker compose up -d --build
# 代码格式化(自动格式化所有Go文件)
gofmt -w ./app
# 静态检查
go vet ./app/...
# 测试(当前项目暂无测试文件,以下为参考命令)
# go test ./app/...
# go test ./app/internal/game/...
# go test ./app/internal/game/... -run TestCardType
# go test ./app/... -cover
3. Go代码风格规范
命名规范
- 导出:大驼峰命名,如
GameManager、NewCardLogic - 模块内:小驼峰命名,如
userId、cardKey - 模块名:全小写,如
game、handlers、ws - 常量:全大写下划线命名
Import规范
import (
"encoding/json" // 标准库
"net/http"
"github.com/gorilla/websocket" // 第三方库
"doudizhu-server/internal/game" // 本地包
"doudizhu-server/internal/models"
)
错误处理
使用哨兵错误模式:
// 定义 (internal/game/errors.go)
var (
ErrRoomNotFound = errors.New("room not found")
ErrNotYourTurn = errors.New("not your turn")
)
// 使用:早返回
func (h *Handler) CreateRoom(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
h.writeError(w, http.StatusBadRequest, "invalid request")
return
}
}
并发安全
type GameManager struct {
rooms map[string]*models.Room
mu sync.RWMutex
}
// 读操作用RLock
func (gm *GameManager) GetRoom(id string) (*models.Room, error) {
gm.mu.RLock()
defer gm.mu.RUnlock()
// ...
}
// 写操作用Lock
func (gm *GameManager) CreateRoom(...) {
gm.mu.Lock()
defer gm.mu.Unlock()
// ...
}
函数长度
- 禁止超过150行,不宜超过50行
- 保持函数单一职责,提高可读性和可维护性
代码优雅性
- 空行规范:不同逻辑块之间空一行
- 运算符空格:双目运算符(
+,=,==等)两端必须加空格 - 禁止多行合并:禁止使用分号将多行代码合并到一行
介词命名规范(用于函数名)
| 介词 | 用法 |
|---|---|
| by | 表示动作的执行者或方式,如 formatByLocale、calculateByDate |
| from | 表示数据来源、起点或类型转换源,如 parseFromJson |
| to | 指明目标位置、接收方或变换终点,如 sendToServer、uploadToCloud |
| with | 说明附加参数或属性,如 buildWithOptions、createWithDefaults |
| in | 描述在某个上下文/环境中执行的动作,如 runInBackground |
| on | 与事件相关的处理器或触发点,如 handleOnClick、listenOnChange |
| for | 指定目标受众、用途或适用范围,如 renderForAdmin、queryForUser |
4. HTTP API响应格式
type ApiResponse struct {
Status int `json:"status"` // HTTP状态码
Code int `json:"code"` // 0=成功, 1=失败
Message string `json:"message"`
Data interface{} `json:"data"`
}
5. 游戏规则要点
- 超人强:第55张牌,最大单牌,可管一切
- 简化牌型:三张可成顺子/炸弹,两对可成连对
- 发牌:每人初始5张,一轮后摸1张
- 无地主:上一轮获胜者先出
6. 开发注意事项
- 代码变动后同步更新文档:README.md 和 API.md
- 后端API路由必须在
/api下 - WebSocket路径:
/api/ws?roomId=xxx&playerId=xxx - 前端不使用npm/react,采用HTML+CSS+JS
- JSON字段用camelCase命名,如
roomId、playerId、cardCount - Go版本:Go 1.21
7. 调试
# 查看日志
docker compose logs -f app
# 前端不生效?强制刷新 (Ctrl+F5)