84669 人學習
152542 人學習
20005 人學習
5487 人學習
7821 人學習
359900 人學習
3350 人學習
180660 人學習
48569 人學習
18603 人學習
40936 人學習
1549 人學習
1183 人學習
32909 人學習
自己想实现一个扑克牌的发牌算法,花色不知道怎么下手,求指点:
拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...
首先,楼主你贴出来的这个发牌算法有问题(没有考虑重复问题),比如第一张发了A,第二张就不应该再能有A了。
然后说下本题的解法,首先基于你的提问,猜测你是做一个类似扑克牌的程序,想要实现随机发牌功能,那么基于这一点,考虑到后续可能的需求变更(比如随机发4张,...,54张),因此拓展为随机发N(n<=54)张扑克牌,这时回答的方向就很明朗了:这是一个典型的扑克牌随机洗牌算法(洗牌后可以随机发出所有的扑克牌)
// 洗牌算法,传入一个数组,随机乱序排列,不污染原数组 function shuffle(arr) { if (!arr) { throw '错误,请传入正确数组'; } var newArr = arr.slice(0); for (var i = newArr.length - 1; i >= 0; i--) { // 随机范围[0,1) var randomIndex = Math.floor(Math.random() * (i + 1)); var itemAtIndex = newArr[randomIndex]; newArr[randomIndex] = newArr[i]; newArr[i] = itemAtIndex; } return newArr; } // 生成一副扑克牌 function generatePoker() { // 第一步:定义四个花色,这里就用中文了 var cardType = ['黑桃', '红桃', '梅花', '方块']; // 第二步:定义13张普通牌 var cardValue = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']; // 第三步:定义2张特殊牌,大王与小王 var specialCard = ['大王', '小王']; // 第四步:根据上述数组生成54张牌 var allCards = []; for (var i = 0, len1 = cardType.length; i < len1; i++) { for (var j = 0, len2 = cardValue.length; j < len2; j++) { allCards.push(cardType[i] + cardValue[j]); } } allCards = allCards.concat(specialCard); return allCards; } // 随机发N张扑克牌 function dealPoker(num) { if(!num || num>54 || typeof(num)!== 'number') { throw '错误,传入的数字非法,只能是[1-54]'; } // 生成扑克牌 var allCards = generatePoker(); // 洗牌-不污染原先的数组 var randomCards = shuffle(allCards); return randomCards.slice(0, num); } // 测试用例 console.log(dealPoker(3)); console.log(dealPoker(4)); console.log(dealPoker(10)); // 生成一副洗好的全新乱序牌 var poker = dealPoker(54); // 接下来如果想要发牌,依次将数组pop即可,因为它本身已经被打乱了,可以一直发完54张
上述代码中核心算法是洗牌算法,这里就不赘述了,可以自行搜索,网上有大量相关资源与教程。
另外,没有做其它相关的封装操作,实际过程中建议自行良好的封装起来。
const pools = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "red Joker", "black Joker"]; const types = ["♠", "♥", "♣", "♦"]; // pools 点数,types 花色,count 张数 function getRandom(pools, types, count) { const arr = []; for (let i = 0; i < count; i++) { // 获取点数(大小王) let pool = pools[Math.floor(Math.random() * pools.length)]; // 获取花色 let type = types[Math.floor(Math.random() * types.length)]; // 获取组合 let poker = pool === 'red Joker' || pool === 'black Joker' ? pool : type + pool; // 组合去重 arr.indexOf(poker) == -1 ? arr.push(poker) : i--; } return arr; } getRandom(pools, types, 7) // ["♥8", "♠4", "♠2", "♣5", "♠10", "♦3", "black Joker"]
搞成一个类二维数组不行吗
不是一样么,再写一个随机,在4个花色里面选一个,两个随机凑在一起就是一张牌。
二维数组, 或者四个数组,
var base = [[s2,..., sA], [h2, ..., hA], [...], [...]]; 或 var spade = [2, ... , A], heart = [...], club = [...], diamond = [...]; 1. 首先深拷贝 这个base数组或s h c d四个数组 //为了不破坏声明的默认值. 2. 随机选择其中一个数组(花色) 3. 取值, splice这个值.//剩余的即为未发的牌 循环即可.
四个数组(或二维数组), 可以满足多重需求. 建议仔细考虑一下.
花色和数字可以写一起,组成54长度的数组即可;
[['diamond',1],['Heart',1],['Club',1],['Spade',1].....]
52张牌都放到数组里面,用52个数字来代替,一个数字代表一张牌,有三个属性:数值、底图、花色。这样子,应该能满足要求!
我的实现
const POOL = ['2','3','4','5','6','7','8','9','10','J','Q','K','A','redJoker','blackJoker']; const TYPE = ['spade','heart','diamond','club'] //黑桃、红桃、方片、梅花 function getRandom(pool,type,num){ var result = [], lengthP = pool.length, lengthT = type.length; return function(){ var poolTemp = '' , typeTemp = '' ,resultTemp = ''; while(num){ poolTemp = pool[Math.floor(Math.random()*lengthP)]; typeTemp = /^(red)|(black)Joker$/.test(poolTemp) ? '' : type[Math.floor(Math.random()*lengthT)]; resultTemp = poolTemp+typeTemp; if(result.indexOf(resultTemp) !=-1) continue; result.push(resultTemp); num--; } return result } } var result = getRandom(POOL,TYPE,8)(); console.log(result.join(',')) //4club,7diamond,10spade,8heart,3spade,9spade,Jspade,Jheart
首先,楼主你贴出来的这个发牌算法有问题(没有考虑重复问题),比如第一张发了A,第二张就不应该再能有A了。
然后说下本题的解法,首先基于你的提问,猜测你是做一个类似扑克牌的程序,想要实现随机发牌功能,那么基于这一点,考虑到后续可能的需求变更(比如随机发4张,...,54张),因此拓展为随机发N(n<=54)张扑克牌,这时回答的方向就很明朗了:这是一个典型的扑克牌随机洗牌算法(洗牌后可以随机发出所有的扑克牌)
代码实现(JS实现)
代码详解
上述代码中核心算法是洗牌算法,这里就不赘述了,可以自行搜索,网上有大量相关资源与教程。
另外,没有做其它相关的封装操作,实际过程中建议自行良好的封装起来。
搞成一个类二维数组不行吗
不是一样么,再写一个随机,在4个花色里面选一个,两个随机凑在一起就是一张牌。
二维数组, 或者四个数组,
四个数组(或二维数组), 可以满足多重需求.
建议仔细考虑一下.
花色和数字可以写一起,组成54长度的数组即可;
52张牌都放到数组里面,用52个数字来代替,一个数字代表一张牌,有三个属性:数值、底图、花色。
这样子,应该能满足要求!
我的实现