利用数据结构中的栈与队列实现两个人打牌的游戏,没人6张不同的牌,交替出牌,遇到相同的牌则拾取继续,直到一方牌打完产生赢家。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//牌节点
class cardNode {
constructor(data) {
this.data = data;
this.next = null;
}
}
//队列类
class Queue {
constructor() {
this.topPoint = null; //队头
this.tailPoint = null; //队尾
this.length = 0; //队长
}
//初始化队列,插入6张牌
//入队
pushQue(data) {
const node = new cardNode(data);
if (this.isEmpty()) {
// 队列为空,头尾指针指向同一个节点
this.topPoint = node;
this.tailPoint = node;
} else {
// 不为空,新节点的指针域指向头节点,更新队头指针
this.tailPoint.next = node;
this.tailPoint = node;
}
// 队列长度加一
this.length++;
}
//出队
popQue() {
let data; //保存出队数据
// 队列为空则不做操作
if (this.isEmpty()) {
console.log('队空');
return false;
} else {
// 不为空,保存出队数据,更新队列指针
data = this.topPoint.data;
this.topPoint = this.topPoint.next;
}
// 队列长度减一,返回出队数据
this.length--;
return data;
}
//判断队列是否为空
isEmpty() {
if (this.length === 0) {
this.topPoint = null; //队头
this.tailPoint = null; //队尾
return true;
} else {
return false;
}
}
//转换字符串
dataToString() {
let str = '队头';
if (this.isEmpty()) {
return '队空';
} else {
let node = this.topPoint;
while (node.next) {
str += node.data + ' --> ';
node = node.next;
}
str += node.data + '队尾';
}
return str;
}
}
// 两个队列
const que1 = new Queue();
const que2 = new Queue();
//栈
let = oderfFlag = true; //出牌顺序标志,默认为true,队列1先出牌
class CardStack {
constructor() {
this.topPoint = null; //栈顶指针
this.basePoint = null; //栈底指针
this.length = 0; //栈的长度
}
//获取需要入栈的元素及顺序,默认队1先出牌
getPushElement() {
let data;
//为真调用队列1出队元素
if (oderfFlag) {
data = que1.popQue();
oderfFlag = !oderfFlag;
// 为假调用队列2出队元素
} else {
data = que2.popQue();
oderfFlag = !oderfFlag;
}
return data;
}
//把获取到的队列元素交替入栈
pushStack(data = this.getPushElement()) { //调用两个队列交替出队数据
//循环调用出栈方法的次数
const card = new cardNode(data);
// 判断栈是否为空,再操作
if (this.isEmpty()) {
//栈顶栈底指针指向唯一的元素
this.topPoint = card;
this.basePoint = card;
} else {
// 修改栈顶指针
card.next = this.topPoint;
this.topPoint = card;
}
this.length++;
// 入栈后开始依次对比是否有相同数据(调用方法对比),需要长度进行循环,所以放在长度后
// 根据isUnique方法返回值决定要不要调用出栈方法
const counter = this.isUnique();
if (counter) {
//调用出栈方法 ,调用次数由需要出栈的元素数量决定
for (let i = 0; i < counter; i++) {
this.popStack(); //有相同元素,调用出栈方法
}
// 收牌的人先出牌,修改出牌标志
oderfFlag = !oderfFlag;
}
// 如果栈打出最后一张牌,且栈顶的牌与这张牌不一样,则游戏结束
if (!counter && this.getWhichQue().isEmpty()) {
// 游戏结束
return true;
}
}
//获取当前是哪个队列在出队
getWhichQue() {
if (oderfFlag) {
return que2;
} else {
return que1;
}
}
// 对比刚入栈的元素是否有相同元素
isUnique() {
//退出函数时,pre指针指向相同的那个数据
let pre = this.topPoint.next;
//用栈长度来进行循环,空栈和只有一个元素时不需要对比
// 返回调用出栈方法的次数
for (let i = 1; i < this.length; i++) {
if (this.topPoint.data === pre.data) {
//console.log(pre.data);
return (i + 1); //找到相同的返回
} else {
pre = pre.next;
}
}
return 0; //没有相同的返回0(即false)
}
//出栈
popStack() {
let data; //保存出栈的数据
if (this.isEmpty()) {
return; //空栈
} else {
data = this.topPoint.data;
this.topPoint = this.topPoint.next;
}
this.length--;
// 条件为真说明刚入栈的元素为队列2的元素,为假元素为队列1的元素
if (oderfFlag) {
que2.pushQue(data);
} else {
que1.pushQue(data)
}
// return data;
}
//判断是否为空栈
isEmpty() {
if (this.length === 0) {
//空栈
this.topPoint = null; //栈顶指针
this.basePoint = null; //栈底指针
return true;
} else {
//不空栈
return false;
}
}
//转换字符串
elementToString() {
if (this.isEmpty()) {
return '空栈';
} else {
let node = this.topPoint;
let str = '栈顶 ';
while (node.next) {
str += node.data + '->';
node = node.next;
}
str += node.data + ' 栈底';
return str;
}
}
}
//实例化栈
const stack = new CardStack();
//游戏类
class Game {
constructor() {
this.times = 0; //回合数
this.timer = null; //定时器
this.init();
}
//初始化
init() {
this.initQue();
this.timer = setInterval(() => {
console.log('队列1: ' + que1.dataToString());
console.log('队列2: ' + que2.dataToString());
console.log(stack.elementToString());
const stop = stack.pushStack();
this.times++;
// 判断游戏是否结束
this.isGameOver(stop);
}, 500)
}
// 游戏结束方法
isGameOver(stop) {
if (stop) {
// 清除定时器,输出结果
clearInterval(this.timer);
console.log('游戏结束');
if (oderfFlag) {
console.log('队列1获胜');
} else {
console.log('队列2获胜');
}
console.log('游戏进行了' + this.times + '个回合');
console.log('队列1: ' + que1.dataToString());
console.log('队列2: ' + que2.dataToString());
console.log(stack.elementToString());
console.log(que1);
console.log(que2);
console.log(stack);
}
}
//初始化队列
initQue() {
// 随机数保存到临时数组
const que1Arr = this.getRandom();
const que2Arr = this.getRandom();
//把随机数入队
for (let i = 0; i < 6; i++) {
que1.pushQue(que1Arr.pop());
que2.pushQue(que2Arr.pop());
}
}
//生成1~9的6个随机数,
getRandom(min = 1, max = 9) {
// 保存元素的数组
const queArr = [];
//外层循环,当数组元素到6个时退出
outer: while (queArr.length != 6) {
// 生成随机数
let num = Math.floor(Math.random() * (max - min + 1)) + min;
// 内层循环,对比数组中是否有该元素
for (let i = 0; i < queArr.length; i++) {
if (queArr[i] === num) {
// 如果数组中有该元素,则开始下一次外层循环
continue outer;
}
}
queArr.push(num); //随机数加入数组
}
return queArr;
}
}
// 游戏
const game = new Game();
</script>
</body>
</html>
运行结果: