JAVA德州扑克小酒馆小程序开发|源码搭建与功能实现方案
JAVA德州扑克小酒馆小程序|源码搭建与功能实现方案
一、项目概述
将德州扑克游戏+小酒馆点餐/消费融合为一个微信小程序,用户可以在线组局、玩德州扑克,同时享受酒馆消费(点酒、点餐、存酒等)。后端采用SpringBoot + MySQL,前端采用UniApp(可编译为微信小程序)或原生微信小程序。
二、技术架构选型
| 层次 | 技术选型 | 说明 |
|---|---|---|
| 后端框架 | SpringBoot 2.7+ / 3.x | RESTful API,快速开发 |
| 数据库 | MySQL 5.7+ | 核心业务数据存储 |
| 缓存/实时 | Redis | 游戏房间状态、在线用户、WebSocket推送 |
| 实时通信 | WebSocket (Spring WebSocket) | 牌局实时同步、下注推送 |
| 前端小程序 | UniApp (Vue3) → 微信小程序 | 一套代码多端运行 |
| 管理后台 | Vue3 + Element Plus | 运营管理、房间管理、用户管理 |
| 支付 | 微信支付SDK | 充值、购买筹码、点餐支付 |
| 部署 | Docker + Nginx | 生产环境部署 |
三、系统功能模块设计
🃏 核心:德州扑克游戏模块
游戏大厅 ├── 快速匹配(根据等级/盲注自动匹配) ├── 创建私密房间(邀请码/好友加入) ├── 房间列表(实时显示在线房间、盲注、人数) │ 牌局流程 ├── 发牌(每人2张底牌) ├── 翻牌前(Pre-Flop) → 翻牌(Flop) → 转牌(Turn) → 河牌(River) ├── 每轮下注(跟注/加注/弃牌/全押All-in) ├── 比牌判定(皇家同花顺 > 同花顺 > 四条 > 葫芦 > 同花 > 顺子 > 三条 > 两对 > 一对 > 高牌) ├── 筹码结算 → 胜负记录 │ 游戏工具 ├── 记分牌(记录每人输赢、手数) ├── 胜率计算器(输入手牌计算胜率) ├── 抽位置功能 └── 历史记录(战绩、盈亏曲线)🍺 小酒馆消费模块
首页 ├── 酒馆风采(轮播图、环境展示) ├── 扫码点餐 / 搜索菜品 │ 点餐系统 ├── 菜品分类(酒水、小吃、套餐) ├── 菜品详情 → 加入购物车 → 下单 ├── 桌台绑定(扫桌台码自动关联) ├── 购物车 → 确认订单 → 微信支付 │ 我的 ├── 个人资料 / 头像 / 昵称 ├── 存酒管理(存酒记录、取酒) ├── 优惠券 ├── 订单列表(点餐订单 + 游戏充值订单) ├── 充值中心(微信支付充值筹码) └── 游戏战绩(盈亏统计、胜率折线图)🔧 管理后台模块
| 模块 | 功能 |
|---|---|
| 用户管理 | 注册用户列表、封号、等级管理 |
| 房间管理 | 房间审核、盲注设置、最大人数 |
| 订单管理 | 点餐订单、充值订单、退款处理 |
| 商品管理 | 酒水/菜品增删改查、库存管理 |
| 数据统计 | DAU、收入、游戏局数、胜率分布 |
| 系统配置 | 轮播图、公告、微信支付配置 |
四、数据库核心表设计
sql
-- 用户表 CREATE TABLE `user` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `openid` VARCHAR(64) UNIQUE COMMENT '微信openid', `nickname` VARCHAR(50), `avatar` VARCHAR(255), `phone` VARCHAR(20), `balance` DECIMAL(10,2) DEFAULT 0 COMMENT '余额', `chips` INT DEFAULT 10000 COMMENT '游戏筹码', `level` INT DEFAULT 1 COMMENT '等级', `total_profit` DECIMAL(10,2) DEFAULT 0 COMMENT '总盈亏', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 游戏房间表 CREATE TABLE `poker_room` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `room_no` VARCHAR(20) UNIQUE COMMENT '房间号/邀请码', `blind_level` INT DEFAULT 1 COMMENT '盲注等级', `max_players` INT DEFAULT 9, `status` TINYINT DEFAULT 0 COMMENT '0等待中 1游戏中 2已结束', `creator_id` BIGINT, `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 牌局记录表 CREATE TABLE `poker_hand` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `room_id` BIGINT, `player_id` BIGINT, `hole_cards` VARCHAR(20) COMMENT '底牌 如 AH-KH', `final_rank` INT COMMENT '最终牌型 0高牌~9皇家同花顺', `win_chips` INT DEFAULT 0 COMMENT '赢得筹码', `is_winner` TINYINT DEFAULT 0, `played_at` DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 点餐订单表 CREATE TABLE `dinner_order` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `user_id` BIGINT, `table_no` VARCHAR(10) COMMENT '桌台号', `total_amount` DECIMAL(10,2), `status` TINYINT DEFAULT 0 COMMENT '0待支付 1已支付 2已完成 3已取消', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 存酒记录表 CREATE TABLE `wine_storage` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `user_id` BIGINT, `wine_name` VARCHAR(100), `quantity` INT DEFAULT 1, `store_date` DATE, `status` TINYINT DEFAULT 0 COMMENT '0存放中 1已取走' );五、核心代码实现
1. 德州扑克牌型判定(Java)
java
public class PokerHandEvaluator { // 牌型等级:0高牌 ~ 9皇家同花顺 public static int evaluate(List<Card> sevenCards) { // 从7张牌(2手牌+5公共牌)中选出最好的5张组合 List<List<Card>> combinations = comb(sevenCards, 5); int bestRank = -1; for (List<Card> combo : combinations) { int rank = rankHand(combo); if (rank > bestRank) bestRank = rank; } return bestRank; } private static int rankHand(List<Card> cards) { Collections.sort(cards); boolean isFlush = cards.stream().map(Card::getSuit).distinct().count() == 1; boolean isStraight = checkStraight(cards); Map<Integer, Long> freq = cards.stream() .collect(Collectors.groupingBy(Card::getRankValue, Collectors.counting())); List<Long> counts = new ArrayList<>(freq.values()); Collections.sort(counts, Collections.reverseOrder()); if (isFlush && isStraight && cards.get(0).getRankValue() == 14) return 9; // 皇家同花顺 if (isFlush && isStraight) return 8; // 同花顺 if (counts.get(0) == 4) return 7; // 四条 if (counts.get(0) == 3 && counts.get(1) == 2) return 6; // 葫芦 if (isFlush) return 5; // 同花 if (isStraight) return 4; // 顺子 if (counts.get(0) == 3) return 3; // 三条 if (counts.get(0) == 2 && counts.get(1) == 2) return 2; // 两对 if (counts.get(0) == 2) return 1; // 一对 return 0; // 高牌 } private static boolean checkStraight(List<Card> cards) { List<Integer> vals = cards.stream() .map(Card::getRankValue).distinct().sorted().toList(); if (vals.size() < 5) return false; // A-2-3-4-5 特殊顺子 if (vals.contains(14) && vals.contains(2) && vals.contains(3) && vals.contains(4) && vals.contains(5)) return true; for (int i = 0; i < vals.size() - 4; i++) { if (vals.get(i + 4) - vals.get(i) == 4) return true; } return false; } }2. 游戏房间 WebSocket 实时同步
java
@ServerEndpoint("/ws/room/{roomId}") @Component public class PokerWebSocket { private static Map<String, Session> sessions = new ConcurrentHashMap<>(); @OnOpen public void onOpen(Session session, @PathParam String roomId) { sessions.put(roomId + ":" + session.getId(), session); broadcast(roomId, new GameMessage("player_joined", playerInfo)); } @OnMessage public void onMessage(String message, @PathParam String roomId) { GameMessage msg = JSON.parseObject(message, GameMessage.class); // 处理下注、弃牌、比牌等操作 if ("bet".equals(msg.getAction())) { processBet(roomId, msg); } broadcast(roomId, msg); // 实时推送给所有玩家 } private void broadcast(String roomId, GameMessage msg) { sessions.values().stream() .filter(s -> s.getId().toString().startsWith(roomId)) .forEach(s -> s.getAsyncRemote().sendText(JSON.toJSONString(msg))); } }3. UniApp 小程序前端 - 牌桌页面
vue
<template> <view class="poker-table"> <!-- 牌桌中央:公共牌 + 底池 --> <view class="community-cards"> <view v-for="card in communityCards" :key="card" class="card"> {{ card }} </view> </view> <view class="pot">底池: {{ potChips }}</view> <!-- 玩家座位 --> <view v-for="player in players" :key="player.id" class="seat" :style="{left: player.x, top: player.y}"> <view class="avatar">{{ player.avatar }}</view> <view class="name">{{ player.nickname }}</view> <view class="chips">💰{{ player.chips }}</view> <view v-if="player.isDealer" class="dealer-btn">D</view> </view> <!-- 操作按钮 --> <view class="actions"> <button @click="fold" class="btn-fold">弃牌</button> <button @click="call" class="btn-call">跟注 {{currentBet}}</button> <button @click="raise" class="btn-raise">加注</button> <button @click="allIn" class="btn-allin">ALL IN</button> </view> </view> </template> <script> export default { data() { return { communityCards: [], potChips: 0, players: [], currentBet: 0 } }, onLoad(options) { this.roomId = options.roomId this.connectWebSocket() }, methods: { connectWebSocket() { this.ws = uni.connectSocket({ url: `wss://your-domain.com/ws/room/${this.roomId}` }) this.ws.onMessage((res) => { const msg = JSON.parse(res.data) if (msg.type === 'community_cards') { this.communityCards = msg.cards } if (msg.type === 'pot_update') { this.potChips = msg.chips } }) }, bet() { this.ws.send({ data: JSON.stringify({ action: 'bet', amount: this.betAmount }) }) } } } </script>六、项目目录结构
poker-tavern/ ├── poker-server/ # SpringBoot后端 │ ├── src/main/java/com/poker/ │ │ ├── controller/ # API控制器 │ │ │ ├── UserController.java │ │ │ ├── RoomController.java │ │ │ ├── OrderController.java │ │ │ └── GameController.java │ │ ├── service/ │ │ │ ├── PokerService.java # 牌局逻辑 │ │ │ ├── RoomService.java # 房间管理 │ │ │ └── OrderService.java # 订单服务 │ │ ├── websocket/ │ │ │ └── PokerWebSocket.java │ │ ├── entity/ │ │ ├── mapper/ │ │ └── config/ │ ├── src/main/resources/ │ │ └── application.yml │ └── pom.xml │ ├── poker-miniapp/ # UniApp前端 │ ├── pages/ │ │ ├── index/ # 首页(酒馆+游戏入口) │ │ ├── lobby/ # 游戏大厅 │ │ ├── table/ # 牌桌 │ │ ├── order/ # 点餐 │ │ └── mine/ # 我的 │ ├── components/ │ │ ├── poker-card.vue # 扑克牌组件 │ │ └── player-seat.vue # 玩家座位 │ ├── store/ # Pinia状态管理 │ ├── App.vue │ └── manifest.json │ ├── admin-web/ # Vue3管理后台 │ └── src/ │ └── docker-compose.yml七、部署方案
yaml
# docker-compose.yml version: '3' services: mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: poker_tavern ports: - "3306:3306" redis: image: redis:7 ports: - "6379:6379" poker-server: build: ./poker-server ports: - "8080:8080" depends_on: - mysql - redis nginx: image: nginx ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf八、开发排期(参考)
| 阶段 | 内容 | 工期 |
|---|---|---|
| P1 | 需求确认 + 数据库设计 + 接口定义 | 3天 |
| P2 | 后端核心:用户/房间/牌局逻辑/WebSocket | 7天 |
| P3 | 小程序:首页/大厅/牌桌/点餐/我的 | 7天 |
| P4 | 管理后台 + 支付对接 + 联调测试 | 5天 |
| P5 | 部署上线 + 压力测试 | 3天 |
| 合计 | 约25个工作日 |
