You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Javascript生成唯一卡牌数组并实现无重复发牌功能

解决卡牌发牌器的重复抽牌、牌组生成与抽牌限制问题

核心问题修复与优化点

1. 生成唯一52张卡牌数组

原代码每次点击按钮都会重新创建牌组,导致卡牌重复堆积,且循环变量未声明为局部变量。修复后:

  • 页面加载时仅初始化一次牌组,避免重复创建
  • 使用let声明循环变量,避免污染全局作用域
  • 实际使用你定义的Card类创建卡牌对象(原代码定义但未使用)

2. 避免重复抽牌

原代码随机选卡牌但不移除已抽中的牌,导致重复。修复方式:

  • 抽牌时从牌组中删除选中的卡牌,确保每张牌仅被抽取一次
  • 每次抽牌前清空手牌数组,避免旧牌残留

3. 清空旧牌+牌组耗尽限制

  • 每次点击按钮先清空页面上的旧牌显示
  • 检查牌组剩余数量,不足5张时禁用按钮并提示牌组耗尽

修改后的完整代码

<head>
  <script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
</head>
<body>
  <h1>Robo Dealer</h1>

  <button onclick="dealHand();">Deal Hand</button>

  <hr />
  <div id="card_hand"></div>

  <script>
    // 花色与点数数组
    const suits = ["Hearts", "Spades", "Clubs", "Diamonds"];
    const values = ["Ace", 2, 3, 4, 5, 6, 7, 8, 9, 10, "Jack", "Queen", "King"];
    
    // 卡牌类
    class Card {
      constructor(suit, value) {
        this.suit = suit;
        this.value = value;
      }
    }

    let deck = [];
    let hand = [];

    // 初始化牌组(仅执行一次)
    function createDeck() {
      // 清空原有牌组,避免重复初始化
      deck = [];
      for (let i = 0; i < suits.length; i++) {
        for (let j = 0; j < values.length; j++) {
          // 使用Card类创建卡牌对象
          const card = new Card(suits[i], values[j]);
          deck.push(card);
        }
      }
      return deck;
    }

    // 抽取5张不重复的卡牌
    function getDeck() {
      hand = [];
      // 最多抽5张,且不超过剩余牌数
      const drawCount = Math.min(5, deck.length);
      for (let i = 0; i < drawCount; i++) {
        // 随机选剩余牌组中的索引
        let randomIndex = Math.floor(Math.random() * deck.length);
        // 从牌组移除并加入手牌
        let drawnCard = deck.splice(randomIndex, 1)[0];
        hand.push(drawnCard);
      }
      return hand;
    }

    // 发牌逻辑
    const dealHand = () => {
      const dealBtn = document.querySelector('button');
      const cardHandEl = $("#card_hand");
      
      // 清空旧牌显示
      cardHandEl.html('');
      
      // 如果牌组为空,重新初始化(可选,也可以保持禁用)
      if (deck.length === 0) {
        createDeck();
        dealBtn.disabled = false;
      }

      // 检查剩余牌数是否足够抽5张
      if (deck.length < 5) {
        cardHandEl.html('<p>牌组剩余不足5张,无法发牌!</p>');
        dealBtn.disabled = true;
        return false;
      }

      // 抽牌并渲染
      getDeck();
      let str = "";
      for (let i = 0; i < hand.length; i++) {
        let obj = hand[i];
        str += `- ${obj.value}  of ${obj.suit}  <br>`;
      }
      cardHandEl.html(str);

      return false; // 防止页面刷新
    };

    // 页面加载时初始化牌组
    window.onload = () => {
      createDeck();
    };
  </script>
</body>

关键修改说明

  1. 牌组初始化:通过window.onload在页面加载时仅执行一次createDeck,确保牌组只创建一次,且使用Card类生成规范的卡牌对象。
  2. 无重复抽牌:使用deck.splice(randomIndex, 1)从牌组中移除选中的卡牌,彻底避免重复抽牌的问题。
  3. 旧牌清空:每次发牌前先调用cardHandEl.html('')清空显示区域,再渲染新牌。
  4. 牌组耗尽处理:检查deck.length,不足5张时禁用按钮并提示,用户可以刷新页面重新开始(或添加重置按钮)。

内容的提问来源于stack exchange,提问作者user19334054

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 07:05:24