js实现麻将
麻将游戏的基本实现思路
麻将游戏的核心逻辑包括洗牌、发牌、玩家操作(摸牌、打牌、吃碰杠胡)以及胜负判定。以下是基于JavaScript的实现框架:
麻将牌型定义
麻将通常由136张牌组成(不含花牌),分为万、条、筒、字牌四类。可以用数字编码表示:
const TILES = {
CHARACTERS: [1, 2, 3, 4, 5, 6, 7, 8, 9], // 万
BAMBOO: [11, 12, 13, 14, 15, 16, 17, 18, 19], // 条
DOTS: [21, 22, 23, 24, 25, 26, 27, 28, 29], // 筒
HONORS: [31, 32, 33, 34, 35, 36, 37] // 东南西北中发白
};
初始化牌堆
创建并洗牌的函数实现:
function initializeDeck() {
let deck = [];
// 每种牌有4个副本
for (let suit in TILES) {
TILES[suit].forEach(tile => {
for (let i = 0; i < 4; i++) {
deck.push(tile);
}
});
}
// Fisher-Yates洗牌算法
for (let i = deck.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[deck[i], deck[j]] = [deck[j], deck[i]];
}
return deck;
}
玩家类实现
基本玩家类需要包含手牌管理和操作逻辑:
class Player {
constructor() {
this.hand = [];
this.melds = []; // 吃碰杠的牌组
}
drawTile(deck) {
if (deck.length > 0) {
this.hand.push(deck.pop());
this.sortHand();
}
}
discardTile(tileIndex) {
return this.hand.splice(tileIndex, 1)[0];
}
sortHand() {
this.hand.sort((a, b) => a - b);
}
}
游戏流程控制
基础游戏循环的伪代码实现:
class MahjongGame {
constructor(playerCount = 4) {
this.deck = initializeDeck();
this.players = Array(playerCount).fill().map(() => new Player());
this.currentPlayer = 0;
this.discardPile = [];
}
startGame() {
// 初始发牌
for (let i = 0; i < 13; i++) {
this.players.forEach(player => player.drawTile(this.deck));
}
}
nextTurn() {
const player = this.players[this.currentPlayer];
player.drawTile(this.deck);
// 这里应添加AI或玩家交互逻辑
// 例如:等待玩家选择打出的牌
this.currentPlayer = (this.currentPlayer + 1) % this.players.length;
}
}
胡牌判定算法
简单的胡牌检查(不考虑特殊牌型):
function checkWin(hand) {
const counts = {};
hand.forEach(tile => {
counts[tile] = (counts[tile] || 0) + 1;
});
// 检查七对
if (hand.length === 14 && Object.values(counts).every(c => c === 2)) {
return true;
}
// 普通胡牌需要4组3张+1对
return isRegularWin(hand);
}
function isRegularWin(hand, start = 0) {
if (hand.length === 0) return true;
// 尝试找对子作为将
if (hand.length % 3 === 2 && hand[0] === hand[1]) {
if (isRegularWin(hand.slice(2), 0)) return true;
}
// 尝试找刻子
if (hand.length >= 3 && hand[0] === hand[2]) {
if (isRegularWin(hand.slice(3), 0)) return true;
}
// 尝试找顺子
const first = hand[0];
if (first < 30) { // 非字牌才能组成顺子
const second = hand.indexOf(first + 1);
const third = hand.indexOf(first + 2);
if (second !== -1 && third !== -1) {
const newHand = [...hand];
newHand.splice(third, 1);
newHand.splice(second, 1);
newHand.shift();
if (isRegularWin(newHand, 0)) return true;
}
}
return false;
}
前端界面建议
对于网页版麻将游戏,可以考虑以下技术组合:
- 使用Canvas或WebGL渲染牌面
- 基于Vue/React的状态管理
- WebSocket实现多人联网对战
- 使用Howler.js等库添加音效
性能优化方向
- 使用TypedArray代替普通数组存储牌数据
- 实现高效的胡牌算法缓存
- 使用Web Worker处理AI计算
- 实现增量渲染减少DOM操作
完整实现一个麻将游戏需要约2000-3000行代码,建议先从基础功能开始,逐步添加吃碰杠等高级规则。对于商业项目,还需要考虑网络同步、断线重连、观战系统等复杂功能。







