84669 person learning
152542 person learning
20005 person learning
5487 person learning
7821 person learning
359900 person learning
3350 person learning
180660 person learning
48569 person learning
18603 person learning
40936 person learning
1549 person learning
1183 person learning
32909 person learning
自己想实现一个扑克牌的发牌算法,花色不知道怎么下手,求指点:
拥有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个数字来代替,一个数字代表一张牌,有三个属性:数值、底图、花色。
这样子,应该能满足要求!
我的实现