大家小时候应该都玩过击鼓传花(Hot Potato)的游戏吧!
一群小孩围成一个圆圈,把花尽快的传给旁边的人。某一时刻传花停止,这时花在谁手里,谁就退出圆圈结束游戏。重复此过程,直到剩下最后一个孩子,即为胜者。
如何用 JavaScript 代码按此规则实现击鼓传花呢?
这里需要借助 JavaScript 中队列的知识,利用循环队列来实现。
队列
首先,我们创建一个 queue.js 的文件存储 Queue 类,代码如下:
export default class Queue {
constructor() {
this.count = 0;
this.lowestCount = 0;
this.items = {};
}
enqueue(element) {
this.items[this.count] = element;
this.count++;
}
dequeue() {
if (this.isEmpty()) {
return undefined;
}
const result = this.items[this.lowestCount];
delete this.items[this.lowestCount];
this.lowestCount++;
return result;
}
isEmpty() {
return this.size() === 0;
}
clear() {
this.items = {};
this.count = 0;
this.lowestCount = 0;
}
size() {
return this.count - this.lowestCount;
}
toString() {
if (this.isEmpty()) {
return '';
}
let objString = `${this.items[this.lowestCount]}`;
for (let i = this.lowestCount + 1; i < this.count; i++) {
objString = `${objString},${this.items[i]}`;
}
return objString;
}
}
其次,根据击鼓传花的规则和循环队列的知识,组织代码:
/**
* @param {Array:参加游戏的人员} elementsList
* @param {number:每次击鼓的次数} num
*/
function hotPotato(elementsList, num) {
// 引入 queue.js 创建 Queue 实例
const queue = new Queue();
const elimitatedList = [];
for (let i = 0; i < elementsList.length; i++) {
// 把参加的人列入队列中
queue.enqueue(elementsList[i]);
}
while (queue.size() > 1) {
for (let i = 0; i < num; i++) {
// 把队列的第一个人放入队尾循环队列
queue.enqueue(queue.dequeue());
}
// 把淘汰的人放入 elimitatedList 数组中
elimitatedList.push(queue.dequeue());
}
return {
eliminated: elimitatedList, // 淘汰的人
winner: queue.dequeue() // 胜利者
};
}
// test
const names = ['丁一', '龙二', '张三', '李四', '王五', '赵六'];
const result = hotPotato(names, 7);
result.eliminated.forEach(name => {
console.log(`${name} was eliminated from the Hot Potato game.`);
});
console.log(`The winner is: ${result.winner}`);
// 龙二 was eliminated from the Hot Potato game.
// 王五 was eliminated from the Hot Potato game.
// 李四 was eliminated from the Hot Potato game.
// 丁一 was eliminated from the Hot Potato game.
// 赵六 was eliminated from the Hot Potato game.
// The winner is: 张三
输出的结果依次为被淘汰的选手和最后的胜利者,这个方法有个弊病:每次淘汰选手敲得鼓声都是一样,导致淘汰的选手和胜利者能预测到。一般我们游戏的时候敲的鼓声都是不确定的,那如何做到不确定,达到一定的游戏氛围呢?大家集思广益吧!