Loading

小猫钓鱼算法(队列+栈练习)

星期天小哼和小哈约在一起玩桌游,他们正在玩一个非常古怪的扑克游戏——“小猫钓鱼”。游戏的规则是这样的:将一副扑克牌平均分成两份,每人拿一份。
小哼先拿出手中的第一张扑克牌放在桌上,然后小哈也拿出手中的第一张扑克牌,并放在小哼刚打出的扑克牌的上面,就像这样两人交替出牌。出牌时,如果某人打出的牌与桌上某张牌的牌面相同,即可将两张相同的牌及其中间所夹的牌全部取走,并依次放到自己手中牌的末尾。
当任意一人手中的牌全部出完时,游戏结束,对手获胜。 假如游戏开始时,小哼手中有 6 张牌,顺序为 2 4 1 2 5 6,小哈手中也有 6 张牌,顺序为 3 1 3 5 6 4,最终谁会获胜呢?现在你可以拿出纸牌来试一试。接下来请你写一个程序来自动判断谁将获胜。这里我们做一个约定,小哼和小哈手中牌的牌面只有 1~9。 

思路:
每人有两种操作,分别是出牌和赢牌。这恰好对应队列的两个操作,出牌就是出队,赢牌就是入队。而桌子就是一个栈,每打出一张牌放到桌上就相当于入栈。当有人赢牌的时候,依次将牌从桌上 拿走,这就相当于出栈。
赢牌的规则是:如果某人打出的牌与桌上的某张牌相同,即可将两张牌以及中间所夹的牌全部取走。因为牌面为1-9,可以建一个数组初始化为0,当牌面n出现在桌子上后数组【n】=1(类似桶排序)
需要两个队列、一个栈来模拟整个游戏

具体代码实现如下:

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;

public class 小猫钓鱼 {

    public static void main(String[] args) {
        Stack<Integer> deskStack = new Stack<>();//桌子上的牌,用栈进行管理
        Queue<Integer> playerA = new LinkedList();//用队列管理每个选手的牌
        Queue<Integer> playerB = new LinkedList();
        int book[] = new int[10];
        Scanner scanner = new Scanner(System.in);
        //发牌,每人6张
        for (int i = 0; i < 6; i++) {
            playerA.add(scanner.nextInt());
        }
        for (int i = 0; i < 6; i++) {
            playerB.add(scanner.nextInt());
        }
        //当两个队列都不为空,表示游戏没有结束
        while (!playerA.isEmpty() && !playerB.isEmpty()) {
            int ta = playerA.peek();//A出一张牌
            //判断A出的牌能不能赢牌
            if (book[ta] == 0) {//桌子上没有这张牌
                //A不能赢牌
                playerA.remove();//打出的牌出队列
                deskStack.add(ta);//打出的牌入栈
                book[ta] = 1;//标记打出的牌出现在桌子上
            } else {//A能赢牌
                playerA.remove();//打出的牌出队列
                playerA.add(ta);//打出的牌入队列
                while (deskStack.lastElement() != ta) {
                    book[deskStack.lastElement()] = 0;
                    playerA.add(deskStack.lastElement());
                    deskStack.pop();
                }
            }
            int tb = playerB.peek();//B出一张牌
            //判断B出的牌能不能赢牌
            if (book[tb] == 0) {//桌子上没有这张牌
                //B不能赢牌
                playerB.remove();//打出的牌出队列
                deskStack.add(tb);//打出的牌入栈
                book[tb] = 1;//标记打出的牌出现在桌子上
            } else {//B能赢牌
                playerB.remove();//打出的牌出队列
                playerB.add(tb);//打出的牌入队列
                while (deskStack.lastElement() != tb) {
                    book[deskStack.lastElement()] = 0;
                    playerB.add(deskStack.lastElement());
                    deskStack.pop();
                }
            }
        }
        if (playerA.isEmpty()) {
            System.out.println("B赢了");
            System.out.print("B手中的牌为:");
            while (!playerB.isEmpty()) {
                System.out.print(playerB.peek() + " ");
                playerB.remove();
            }
        } else {
            System.out.println("A赢了");
            System.out.print("A手中的牌为:");
            while (!playerA.isEmpty()) {
                System.out.print(playerA.peek() + " ");
                playerA.remove();
            }
        }
        System.out.println("");
        System.out.print("桌子上的牌为:");
        while (!deskStack.isEmpty()) {
            System.out.print(deskStack.lastElement() + " ");
            deskStack.pop();
        }
    }
}
输入手中牌的个数
6
输入A君手中牌的大小
2 4 1 2 5 6
输入B君手中牌的大小
3 1 3 5 6 4
输入完毕开始游戏
A君胜利!A手中的牌是
5 6 2 3 1 4 6 5 
桌面上的牌是
2 1 3 4 

 

补充知识:

  Stack<Integer> stack = new Stack<>();

  stack1.peek() 返回栈顶元素,但不在堆栈中删除它。
  Stack2.pop() 返回栈顶元素,并在进程中删除它。

        总结一下:
        当我们只需要取出栈顶的元素进行处理(或者说我们需要先对栈顶的数据进行处理例如比较)然后根据处理的结果进行决定是否要pop(),这种情况下,我们可以先使用peek()方法,取出栈顶的值。
        补充总结一下栈中的其他常用的方法:
        empty( )——如果堆栈是空的,则返回true,当堆栈包含元素时,返回false;

        参考:https://blog.csdn.net/Late_whale/article/details/111463791

 

 

 

posted @ 2021-02-03 11:00  Robinzhao  阅读(577)  评论(0)    收藏  举报