初始化斗地主残局版项目
This commit is contained in:
150
AGENTS.md
Normal file
150
AGENTS.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# 斗地主残局版 - 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
|
||||
# 本地开发
|
||||
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规范
|
||||
|
||||
```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()
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 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字段用下划线命名**,如 `room_id`,但尽量用单词
|
||||
|
||||
## 7. 调试
|
||||
|
||||
```bash
|
||||
# 查看日志
|
||||
docker compose logs -f app
|
||||
|
||||
# 前端不生效?强制刷新 (Ctrl+F5)
|
||||
```
|
||||
Reference in New Issue
Block a user