2026-04-30
基于python做的web端桂林跑牌
项目地址:桂林跑牌
# 桂林跑牌 一个使用 Flask 编写的桂林跑牌网页游戏。项目包含大厅、多人房间、牌桌界面、 出牌规则、局内轮转、自动过牌、跨小局积分和整局结束结算。 ## 功能概览 - 创建 4 位房间号,其他玩家可输入房间号加入。 - 支持 2 到 4 人开局,每名玩家每小局发 13 张牌。 - 支持单张、对子、三张、四张、四连张牌型。 - 按桂林跑牌规则实现“有牌可管必须出”,无牌可管时允许过牌。 - 当前玩家无牌可管时,前端 5 秒后自动过牌,避免牌局卡住。 - 记录最近出牌历史,并展示每名玩家最近出的牌堆。 - 每小局结束后结算剩余牌分数,累计达到 100 分结束整局。 - 房主退出会释放房间;整局结束后房间保留短暂倒计时再释放。 ## 技术栈 - 后端:Python + Flask - 前端:原生 HTML/CSS/JavaScript - 存储:单进程内存存储,无数据库依赖 - 依赖:见 `requirements.txt` ## 目录结构## 本地运行 建议使用虚拟环境运行:. ├── app/ │ ├── __init__.py # Flask 应用工厂 │ ├── cardgame/ │ │ ├── routes.py # 页面路由和 JSON API │ │ ├── store.py # 内存房间、成员、积分和继续投票 │ │ ├── engine.py # 单局牌局状态机 │ │ ├── rules.py # 牌、牌型、大小比较和可出牌枚举 │ │ └── crypto.py # MD4 摘要工具,用于生成短房间号 │ ├── static/ │ │ ├── css/guilin_paopai.css # 大厅、牌桌和响应式样式 │ │ └── js/ │ │ ├── guilin_paopai_lobby.js │ │ └── guilin_paopai.js │ └── templates/ │ ├── guilin_paopai_lobby.html │ └── guilin_paopai.html ├── docs/ │ ├── API.md # 接口说明 │ └── GAME_RULES.md # 详细游戏规则 ├── config.py # Flask 配置 ├── run.py # 本地开发启动入口 └── requirements.txt默认监听地址:python -m venv .venv source .venv/bin/activate pip install -r requirements.txt python run.py`run.py` 使用 `host="0.0.0.0"`,同一局域网设备也可以通过主机 IP 访问:http://127.0.0.1:5001/cardgame/guilin-paopai## 基本玩法流程 1. 打开大厅页,点击“建房”创建房间。 2. 把页面中的 4 位房间号告诉其他玩家。 3. 其他玩家在大厅输入房间号并加入。 4. 房主点击“开始”后进入第一小局。 5. 轮到自己时选择手牌并点击“出牌”;如果无牌可管,可以点击“过牌”。 6. 某名玩家先出完手牌后,本小局结束并展示结算。 7. 所有人点击“继续”后开始下一小局。 8. 任一玩家累计分达到 100 分,整局结束并展示最终积分。 ## 规则摘要 - 人数:2 到 4 人。 - 发牌:每人 13 张,剩余牌保留但当前不会摸牌。 - 首出:每小局随机一名玩家首出。 - 牌型:单张、对子、三张、四张、四连张。 - 大小:单张/对子/三张/四张按 `3 < 4 < ... < K < A < 2`。 - 四连张:最大 `AKQJ`,最小 `432A`;`KA2` 不算连续。 - 管牌:必须同牌型且点数更大;当前实现中四张不跨牌型压制其他牌型。 - 过牌:首出不能过;有牌可管时必须出,只有无牌可管时可以过。 - 直接胜利:起手拿到 4 个 2,或起手全小,立即赢得本小局。 - 小局结束:任一玩家先出完手牌。 - 计分:胜者本局不加分,其他玩家按剩余牌数量和倍率加分。 完整规则见 [docs/GAME_RULES.md](docs/GAME_RULES.md)。 ## 计分方式 | 剩余张数 | 倍率 | | --- | --- | | 0 到 7 张 | x1 | | 8 到 9 张 | x2 | | 10 到 12 张 | x3 | | 13 张 | x4 | 本局加分:http://<你的主机IP>:5001/cardgame/guilin-paopai当前实现把累计分视为剩余牌惩罚分;任一玩家累计达到 100 分时整局结束,界面 保留积分列表供玩家查看最终结果。 ## API 文档 接口说明见 [docs/API.md](docs/API.md)。常用接口包括: - `POST /cardgame/api/guilin-paopai/rooms`:创建房间 - `POST /cardgame/api/guilin-paopai/rooms//join`:加入房间 - `GET /cardgame/api/guilin-paopai/rooms/`:轮询房间状态 - `POST /cardgame/api/guilin-paopai/rooms//start`:房主开始 - `POST /cardgame/api/guilin-paopai/rooms//play`:出牌 - `POST /cardgame/api/guilin-paopai/rooms//pass`:过牌 - `POST /cardgame/api/guilin-paopai/rooms//continue`:继续下一小局 ## 设计说明 - `rules.py` 是纯规则层,不依赖 Flask,也不保存房间状态。 - `engine.py` 管一小局内的发牌、出牌、过牌、轮转和胜负。 - `store.py` 管多人房间、成员、积分、继续投票和房间释放。 - `routes.py` 只做 HTTP 请求解析和错误响应转换。 - 前端通过 `localStorage` 保存 `playerId`,刷新页面后可回到原座位。 - 房间状态通过轮询同步,默认约 1.6 秒请求一次。 ## 开发注意事项 - 当前房间和牌局都存放在 Python 进程内存中,服务重启后全部丢失。 - Flask 开发服务器适合本地调试,不建议直接作为生产服务。 - 如果要多进程或多实例部署,需要把 `_ROOMS`、`_GAMES` 和锁替换为共享存储。 - `config.py` 中的 `SECRET_KEY` 是开发值,正式部署应改为环境变量注入。 - 房主开局当前只要求人数不少于 2 人,不强制所有玩家准备。 ## 基础检查 修改 Python 代码后可以先运行语法检查:胜者:0 其他玩家:剩余张数 * 倍率目前项目没有自动化测试套件;规则层和引擎层已经拆开,后续可优先补充 `rules.py` 和 `engine.py` 的单元测试。python -m compileall app config.py run.py
# 桂林跑牌规则说明 本文档描述当前代码实现的桂林跑牌规则。不同地区规则可能有差异,以下内容以 本项目代码为准。 ## 人数与发牌 - 支持 2 到 4 名玩家。 - 每名玩家每小局发 13 张牌。 - 2 人或 3 人局会有剩余牌,当前实现中剩余牌不参与摸牌,只在状态中保留数量。 - 每小局重新洗牌和发牌,积分跨小局累计。 ## 点数大小 单张、对子、三张、四张都使用同一套点数顺序:花色不参与大小比较,只用于展示和稳定排序。 ## 合法牌型 ### 单张 任意 1 张牌。 示例:3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < J < Q < K < A < 2### 对子 2 张相同点数的牌。 示例:A### 三张 3 张相同点数的牌。 示例:88### 四张 4 张相同点数的牌。 示例:KKK当前实现中四张只是一个普通牌型,只能管更小的四张,不会跨牌型压制单张、对子、 三张或四连张。 ### 四连张 4 个不同点数组成的连续牌型。当前实现支持的四连张从大到小为:2222注意: - `AKQJ` 最大。 - `432A` 最小。 - `KA2` 不算连续。 - 四连张之间只比较上表顺序,不按普通扑克牌顺子规则推导。 ## 出牌与管牌 - 每小局随机一个玩家首出。 - 本轮首出时可以选择任意合法牌型。 - 后续玩家必须出相同牌型,并且大小严格大于桌面当前牌。 - 如果没有牌能管,可以过牌。 - 如果有牌能管,必须出牌,不能主动过牌。 - 当其他玩家都无法管住当前牌时,本轮结束,最后成功出牌的玩家获得下一轮首出权。 ## 起手直接胜利 发牌后会先检查两个直接胜利条件: - 玩家起手拿到 4 个 `2`。 - 玩家起手全小,即手牌中没有 `2`、`A`、`K`、`Q`、`J`。 如果满足条件,本小局立即结束并进入计分。若多人同时满足,当前实现按座位顺序 先检查到的玩家获胜。 ## 小局结束 任意玩家出完最后一张手牌后,本小局结束。界面会展示: - 本局胜者。 - 每名玩家剩余张数。 - 每名玩家倍率。 - 本局加分。 - 累计总分。 ## 计分 胜者本局加 `0` 分。其他玩家按剩余牌数量计算惩罚分:AKQJ KQJ10 QJ109 J1098 10987 9876 8765 7654 6543 5432 432A倍率规则: | 剩余张数 | 倍率 | | --- | --- | | 0 到 7 张 | x1 | | 8 到 9 张 | x2 | | 10 到 12 张 | x3 | | 13 张 | x4 | 任一玩家累计达到 `100` 分时整局结束。当前实现没有额外的排名算法,最终以积分板 展示的累计分作为结果参考;分数来自剩余牌惩罚,通常越低越好。 ## 房间规则 - 房间号为 4 位十六进制字符。 - 房主创建房间后自动进入等待区。 - 玩家加入房间时会自动获得昵称。 - 同一浏览器刷新页面会复用本地 `playerId`,不会重复占座。 - 房主退出会释放房间。 - 普通玩家只能在等待区退出;牌局开始后暂不支持中途退出。 - 每小局结束后,所有玩家都点击“继续”才会开始下一小局。 - 整局结束后房间会保留短暂倒计时,方便查看结算,然后释放。 ## 前端交互规则 - “提示”会选择后端返回的第一手可出牌。 - “出牌”按钮只在轮到自己且已选择手牌时可用。 - “过牌”按钮只在轮到自己且无牌可管时可用。 - 无牌可管时,前端会提示并在 5 秒后自动过牌。 - 手牌和桌面状态通过轮询同步,其他玩家出牌后会自动刷新界面。本局加分 = 剩余张数 * 倍率

