当前位置:首页 > JavaScript

js实现麻将

2026-01-31 19:21:35JavaScript

麻将游戏的基本实现思路

麻将游戏的核心逻辑包括洗牌、发牌、玩家操作(摸牌、打牌、吃碰杠胡)以及胜负判定。以下是基于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;
}

前端界面建议

对于网页版麻将游戏,可以考虑以下技术组合:

js实现麻将

  • 使用Canvas或WebGL渲染牌面
  • 基于Vue/React的状态管理
  • WebSocket实现多人联网对战
  • 使用Howler.js等库添加音效

性能优化方向

  • 使用TypedArray代替普通数组存储牌数据
  • 实现高效的胡牌算法缓存
  • 使用Web Worker处理AI计算
  • 实现增量渲染减少DOM操作

完整实现一个麻将游戏需要约2000-3000行代码,建议先从基础功能开始,逐步添加吃碰杠等高级规则。对于商业项目,还需要考虑网络同步、断线重连、观战系统等复杂功能。

标签: 麻将js
分享给朋友:

相关文章

vue.js实现轮播

vue.js实现轮播

Vue.js 实现轮播功能 使用第三方库(推荐) Vue.js 生态中有许多成熟的轮播组件库,例如 vue-awesome-swiper 或 swiper,它们功能丰富且易于集成。 安装 swipe…

js实现类

js实现类

JavaScript 实现类的几种方式 JavaScript 是一种基于原型的语言,但在 ES6 之后引入了 class 语法糖,使得实现类更加直观。以下是几种常见的实现方式: 使用构造函数 传统的…

js实现目录

js实现目录

实现目录的基本思路 在JavaScript中实现目录功能通常涉及以下几个核心步骤:解析文档中的标题元素(如h1-h6),动态生成目录结构,并添加交互逻辑(如点击跳转)。以下是具体实现方法: 解析标题…

js实现密码

js实现密码

密码强度验证 使用正则表达式验证密码强度是一种常见方法。以下代码检查密码是否包含大小写字母、数字和特殊字符,且长度至少为8位: function checkPasswordStrength(pass…

节流js实现

节流js实现

节流(Throttle)的实现原理 节流是一种限制函数执行频率的技术,确保函数在一定时间间隔内最多执行一次。适用于高频触发事件(如滚动、输入、窗口调整等)的场景。 基础实现方式 使用时间戳判断是否执…

js实现正交

js实现正交

正交的概念 正交在数学和计算机科学中通常指两个向量垂直或线性无关。在编程中,正交性常被用于设计模块化、低耦合的系统。 向量正交判断 判断两个向量是否正交可以通过点积是否为0来实现: fun…