3.4 KiB
3.4 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. 构建与运行命令
# 本地开发
cd doudizhu-server/app && go mod tidy && go run ./cmd
# Docker部署
cd doudizhu-server && docker compose up -d --build
# 代码格式化
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()
// ...
}
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字段用下划线命名,如
room_id,但尽量用单词
7. 调试
# 查看日志
docker compose logs -f app
# 前端不生效?强制刷新 (Ctrl+F5)