经常有兄弟加我微信上来就问:“B哥,我就想给家里人搭个能打麻将斗地主的网页,不用下载App那种,有没有办法?” 答案是肯定的。今天这篇棋牌游戏网站搭建教程,我就直接上代码,咱们从前端牌桌渲染、到后端出牌逻辑、再到房间管理数据库,完整撸一遍。全程用的是纯HTML5 + Node.js + WebSocket,不依赖任何重型框架,跑在宝塔上资源占用极小。
在开始前还是要啰嗦一句:以下代码仅供技术学习与亲友娱乐,严禁用于任何违规运营,咱不碰红线。
一、牌桌画面的前端骨架
玩家打开网站第一个看到的就是游戏大厅和牌桌,这块我们用 Canvas 来画,别用DOM一个个摞,性能扛不住。先搭一个最简单的斗地主三人桌,牌面素材我用的猫情怀那套扑克SVG,视觉上比传统扑克更亲和。
// game-table.js 核心渲染片段 const canvas = document.getElementById('table-canvas'); const ctx = canvas.getContext('2d'); function drawTable() { // 铺绿色桌面 ctx.fillStyle = '#2d5a27'; ctx.fillRect(0, 0, 1000, 600); // 绘制三个玩家手牌区域 const positions = [ {x: 200, y: 500, angle: 0}, // 本家 {x: 100, y: 100, angle: -0.2}, // 上家 {x: 700, y: 100, angle: 0.2} // 下家 ]; positions.forEach((p, idx) => { drawHandArea(ctx, p.x, p.y, p.angle, idx); }); // 绘制底牌区 ctx.strokeStyle = '#c8a96e'; ctx.lineWidth = 2; ctx.strokeRect(430, 250, 140, 80); }
这只是静态画面,要让牌动起来,需要接入WebSocket做实时同步。
二、后端出牌判定与房间心跳
后端我直接用Node.js一把梭,WebSocket库选的ws。棋牌游戏最吃逻辑的就是出牌规则判定,这里贴一段判断顺子的函数,这是斗地主里最容易写出bug的地方。处理不好,飞机带翅膀直接变成散牌。
// game-logic.js 顺子判定 function isValidStraight(cards) { if (cards.length < 5) return false; const values = cards.map(c => c.value).sort((a,b) => a - b); // 不能含2和王 if (values.some(v => v >= 15)) return false; // 连续判定 for (let i = 1; i < values.length; i++) { if (values[i] !== values[i-1] + 1) return false; } return true; }
除了出牌,房间管理这块我踩过一个深坑:有人用HTTP短轮询做房间状态同步,结果一桌四个人,三个都掉线卡死。正确做法是用WebSocket维持长连接,同时给每个房间加心跳检测,超时自动踢人并释放内存。
// room-manager.js 心跳与掉线处理 const HEARTBEAT_INTERVAL = 5000; ws.on('pong', () => { player.lastAlive = Date.now(); }); setInterval(() => { rooms.forEach(room => { room.players.forEach(p => { if (Date.now() - p.lastAlive > 15000) { handleDisconnect(room, p); } }); }); }, HEARTBEAT_INTERVAL);
三、房卡模式数据库表设计
猫情怀房卡模式的核心是什么?就是一卡一房,消耗型道具。所以数据库里最关键的三张表是:用户表、房卡记录表、房间日志表。表结构不设计好,后面查流水对账能把你逼疯。
-- 核心表结构(MySQL 8.0) CREATE TABLE `users` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `openid` varchar(64) NOT NULL COMMENT '微信openid', `nickname` varchar(32) DEFAULT '牌友', `room_cards` int unsigned DEFAULT 0 COMMENT '剩余房卡数', `created_at` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_openid` (`openid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `room_records` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `room_code` char(6) NOT NULL COMMENT '六位房间码', `creator_id` int unsigned NOT NULL, `game_type` tinyint DEFAULT 1 COMMENT '1斗地主2麻将3牛牛', `consume_card` tinyint DEFAULT 1 COMMENT '消耗房卡数', `status` tinyint DEFAULT 0 COMMENT '0进行中1已结束', `start_time` datetime, `end_time` datetime, PRIMARY KEY (`id`), KEY `idx_creator` (`creator_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
当玩家创建房间时,后端先检查房卡余额,扣除成功后返回六位随机房间码。房间码生成别用简单的自增ID,会被遍历撞房,我用的是一段加权随机算法,去掉了容易混淆的0和O。
所有代码我都在宝塔上实际跑通了,一个1核2G的轻量云服务器,带个十来桌亲友对战完全没压力。部署时记得在宝塔安全里放行WebSocket端口,并在Nginx配置里加上反向代理,否则wss协议连不上。
这篇棋牌游戏网站搭建教程,基本把前端渲染、后端逻辑和数据库都串了一遍。代码都是可直接复用的精简版,拿去改改UI就能当个家庭麻将馆用。当然,完整的一套东西细节还很多,像机器人托管、回放复盘这些,今天篇幅实在塞不下。
如果你正打算自己动手搭一套,或者手头已经有服务器但源码一直跑不起来,随时可以来问我。
扫描下方二维码,添加微信,备注“猫情怀”。


