# 斗地主残局版 - 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. 构建与运行命令 ```bash # 本地开发(需先启动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规范 ```go import ( "encoding/json" // 标准库 "net/http" "github.com/gorilla/websocket" // 第三方库 "doudizhu-server/internal/game" // 本地包 "doudizhu-server/internal/models" ) ``` ### 错误处理 使用哨兵错误模式: ```go // 定义 (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 } } ``` ### 并发安全 ```go 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行 - 保持函数单一职责,提高可读性和可维护性 ### 代码优雅性 1. **空行规范**:不同逻辑块之间空一行 2. **运算符空格**:双目运算符(`+`, `=`, `==` 等)两端必须加空格 3. **禁止多行合并**:禁止使用分号将多行代码合并到一行 ### 介词命名规范(用于函数名) | 介词 | 用法 | | ------ | -------------------------------------------------------------------- | | by | 表示动作的执行者或方式,如 `formatByLocale`、`calculateByDate` | | from | 表示数据来源、起点或类型转换源,如 `parseFromJson` | | to | 指明目标位置、接收方或变换终点,如 `sendToServer`、`uploadToCloud` | | with | 说明附加参数或属性,如 `buildWithOptions`、`createWithDefaults` | | in | 描述在某个上下文/环境中执行的动作,如 `runInBackground` | | on | 与事件相关的处理器或触发点,如 `handleOnClick`、`listenOnChange` | | for | 指定目标受众、用途或适用范围,如 `renderForAdmin`、`queryForUser` | ## 4. HTTP API响应格式 ```go 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. 开发注意事项 1. **代码变动后同步更新文档**:README.md 和 API.md 2. **后端API路由必须在 `/api` 下** 3. **WebSocket路径**:`/api/ws?roomId=xxx&playerId=xxx` 4. **前端不使用npm/react**,采用HTML+CSS+JS 5. **JSON字段用camelCase命名**,如 `roomId`、`playerId`、`cardCount` 6. **Go版本**:Go 1.21 ## 7. 调试 ```bash # 查看日志 docker compose logs -f app # 前端不生效?强制刷新 (Ctrl+F5) ```