javascript实现数据结构栈与队列的打牌小游戏

利用数据结构中的栈与队列实现两个人打牌的游戏,没人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>

运行结果:

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
用于实现队列数据结构队列数据结构队列是一种列表,它具有先进先出(FIFO)的特性,即先到队列的元素会先被处理。队列实现可以使用数组或链表来存储元素。在队列中,新的元素会被插入到队列的末尾,而删除操作则在队列的头部进行。这样就保证了队列中的元素按照插入的顺序被处理。队列实现可以通过使用数组和两个指针(一个指向队列的头部,一个指向队列的尾部),或者使用链表来实现队列数据结构实现有助于解决许多实际问题,并且在计算机科学中被广泛应用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [队列 数据结构_什么是队列数据结构?](https://blog.csdn.net/cunfen6312/article/details/107685027)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [基于JavaScript数据结构队列动画实现示例解析](https://download.csdn.net/download/weixin_38651812/14901203)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值