游戏规则:
民间击鼓传花游戏,也称传彩球。数人、十数人或数十人围成一个圆圈,把花尽快地传递给旁边的人。某一时刻传花停止,这个时候花在谁手里,谁就退圈、结束游戏。重复该过程,直到只剩一个人(胜利者)。
相信大家小时候都玩过击鼓传花小游戏,那么接下来,我们就代码实现理论与实际相结合。
概念介绍:
队列(Queue):队列是遵循先进先出(FIFO)原则的一组有序的项。队列在尾部添加新元素,并从顶部移除元素。最新添加的元素必须排队队列中的末尾。像现实生活中的一条单行线,先进来的人会先出去。
双端队列(Deque):双端队列是一种允许我们从前端和后端同时添加和移除元素的特殊队列。常见应用是存储一系列的撤销操作。像现实生活中排队结账,排在第一位的人会先享受服务,离开后有需要咨询的问题,可以回头插入到第一位,继续询问,排在末尾的人,也可以选择直接离开。由于双端队列同时遵守了先进先出和后进后出原则,可以说它是队列和栈相结合的一种数据结构。
代码实现:
基于数组封装队列类
function Queue() {
// 属性
this.items = [];
// 方法
// 1.enqueue():将元素加入到队列中
Queue.prototype.enqueue = (element) => {
this.items.push(element);
};
// 2.dequeue():从队列中删除前端元素
Queue.prototype.dequeue = () => {
return this.items.shift();
};
// 3.front():查看前端的元素
Queue.prototype.front = () => {
return this.items[0];
};
// 4.isEmpty:查看队列是否为空
Queue.prototype.isEmpty = () => {
return this.items.length == 0;
};
// 5.size():查看队列中元素的个数
Queue.prototype.size = () => {
return this.items.length;
};
// 6.toString():将队列中元素以字符串形式输出
Queue.prototype.toString = () => {
let resultString = "";
for (let i of this.items) {
resultString += i + " ";
}
return resultString;
};
}
击鼓传花游戏代码实现:
function hotPotato(elementsList, num) {
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.push(queue.dequeue());
}
return {
eliminated: elimitatedList,
winner: queue.dequeue(),
};
}
const names = ["summer", "sunny", "jake", "mickael", "winter"];
const result = hotPotato(names, 8);
result.eliminated.forEach((name) => {
console.log(`${name}在击鼓传花游戏中被淘汰`);
});
console.log(`winner:${result.winner}`);
运行效果图如下:
参考书籍:《学习JavaScript数据结构与算法》