如何用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>
关键修改说明
- 牌组初始化:通过
window.onload在页面加载时仅执行一次createDeck,确保牌组只创建一次,且使用Card类生成规范的卡牌对象。 - 无重复抽牌:使用
deck.splice(randomIndex, 1)从牌组中移除选中的卡牌,彻底避免重复抽牌的问题。 - 旧牌清空:每次发牌前先调用
cardHandEl.html('')清空显示区域,再渲染新牌。 - 牌组耗尽处理:检查
deck.length,不足5张时禁用按钮并提示,用户可以刷新页面重新开始(或添加重置按钮)。
内容的提问来源于stack exchange,提问作者user19334054
相关产品推荐
相关产品推荐

