2024春晚刘谦扑克魔术的链表实现

这篇文章介绍了刘谦春晚魔术中利用链表的插入和删除操作实现的神奇牌堆变换过程,详细展示了如何洗牌、切牌以及进行各种位置的插入和删除操作来达到魔术效果。
摘要由CSDN通过智能技术生成

原视频见央视节目:

[2024央视春晚]魔术《守岁共此时》 表演:刘谦(字幕版)

该魔术背后的数学原理,可通过链表的插入、删除实现。

先提前展示运行结果:

原始牌:[方块2, 方块7, 方块6, 红桃5]
洗牌之后:[红桃5, 方块7, 方块2, 方块6]
撕成一半之后的牌:红桃5:1 方块7:1 方块2:1 方块6:1 红桃5:2 方块7:2 方块2:2 方块6:2
移动名字长度的牌至牌底:方块2:1 方块6:1 红桃5:2 方块7:2 方块2:2 方块6:2 红桃5:1 方块7:1
将前3张牌放置牌堆中间:方块7:2 方块2:2 方块6:2 方块2:1 方块6:1 红桃5:2 红桃5:1 方块7:1
将牌收藏起来: 方块7:2
南方人将前1张牌放置牌堆中间:方块6:2 方块2:1 方块6:1 红桃5:2 红桃5:1 方块2:2 方块7:1
男性将前1扔掉: 方块2:1 方块6:1 红桃5:2 红桃5:1 方块2:2 方块7:1
执行见证奇迹的时刻循环后: 方块6:1 红桃5:2 红桃5:1 方块2:2 方块7:1 方块2:1
最后一张牌为:方块7:1

原代码:



import org.apache.commons.lang3.ArrayUtils;

import java.util.Arrays;

public class LiuQianMagic {

    public static void main(String[] args) {
        LiuQianMagic liuQianMagic = new LiuQianMagic();
        String[] oriCardArr = liuQianMagic.generateOriCardArr("方块2", "方块7", "方块6", "红桃5");
        System.out.println("原始牌:" + Arrays.toString(oriCardArr));
        ArrayUtils.shuffle(oriCardArr);
        System.out.println("洗牌之后:" + Arrays.toString(oriCardArr));
        System.out.print("撕成一半之后的牌:");
        Node head = liuQianMagic.generateCutCardLinkedList(oriCardArr);
        liuQianMagic.printLinkedList(head);
        String yourName = "刘谦";
        Node newHead = liuQianMagic.movedToEnd(head, yourName);
        System.out.print("移动名字长度的牌至牌底:");
        liuQianMagic.printLinkedList(newHead);
        // pos为插入的牌堆位置:需要大于等于3, 小于等于7
        int pos = 5;
        System.out.print("将前3张牌放置牌堆中间:");
        Node<Card> newHead2 = liuQianMagic.pickFirstMultiCardAndInsert(newHead, pos, 3);
        liuQianMagic.printLinkedList(newHead2);
        Card card = newHead2.card;
        System.out.println("将牌收藏起来: " + card);
        Node newHead3 = liuQianMagic.deleteFirstNode(newHead2);
        // 地域: 南方人
        Region region = Region.SOUTH;
        System.out.print(region.regionName + "将前" + region.cardNum + "张牌放置牌堆中间:");
        Node newHead4 = liuQianMagic.pickFirstMultiCardAndInsertByRegion(newHead3, pos, region);
        liuQianMagic.printLinkedList(newHead4);
        // 性别:男
        Gender gender = Gender.MALE;
        Node newHead5 = liuQianMagic.deleteFirstMultiNodeByGender(newHead4, gender);
        System.out.print(gender.genderName + "将前" + gender.carNum + "扔掉: ");
        liuQianMagic.printLinkedList(newHead5);
        // 执行见证奇迹的时刻
        Node newHead6 = liuQianMagic.movedToEnd(newHead5, "见证奇迹的时刻");
        System.out.print("执行见证奇迹的时刻循环后: ");
        liuQianMagic.printLinkedList(newHead6);
        // 从牌堆顶将一张牌放在牌堆底, 再扔掉牌堆顶的一张牌。重复以上,直到只剩一张牌。
        Card cardEnd = liuQianMagic.moveAndDropCard(newHead6);
        System.out.println("最后一张牌为:" + cardEnd);
    }

    private Node head;

    private String[] generateOriCardArr(String a, String b, String c, String d) {
        return new String[]{a, b, c, d};
    }

    private Node<Card> generateCutCardLinkedList(String[] oriCardArr) {
        this.head = new Node(new Card(oriCardArr[0], 1));
        Node node1 = new Node(new Card(oriCardArr[1], 1));
        Node node2 = new Node(new Card(oriCardArr[2], 1));
        Node node3 = new Node(new Card(oriCardArr[3], 1));
        Node node4 = new Node(new Card(oriCardArr[0], 2));
        Node node5 = new Node(new Card(oriCardArr[1], 2));
        Node node6 = new Node(new Card(oriCardArr[2], 2));
        Node node7 = new Node(new Card(oriCardArr[3], 2));
        head.next = node1;
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;
        node6.next = node7;
        return head;
    }


    public Node pickFirstMultiCardAndInsert(Node head, int pos, int carNum){
       insertCard(head, pos, carNum);
       Node newHead = deleteFirstMultiNode(head, carNum);
       return newHead;
    }

    public Node pickFirstMultiCardAndInsertByRegion(Node head, int pos, Region region){
        Node newHead = pickFirstMultiCardAndInsert(head, pos, region.cardNum);
        return newHead;
    }

    public Card moveAndDropCard(Node head) {
        Node<Card> current = head;
        Node<Card> newHead;
        Node<Card> newHead2;
        while (current.next != null) {
            newHead = movedToEnd(current, "1");
            current = newHead;
            if (current.next != null) {
                newHead2 = deleteFirstNode(newHead);
                current = newHead2;
            }
        }
        return current.card;
    }


    // 在中间某位置插入N张卡
    public void insertCard(Node head, int pos, int carNum) {
        if (pos < carNum) {
            System.out.println("pos需要大于等于3, 小于等于7");
            System.exit(1);
        }
        Node<Card> current = head; // 从头开始查找最后一个节点
        for (int i = 0; i < carNum; i++) {
            insert(head, current.card, pos);
            current = current.next;
            pos++;
        }
    }

    public Node deleteFirstMultiNode(Node head, int carNum) {
        for (int i = 0; i < carNum; i++) {
            head = deleteFirstNode(head);
        }
        return head;
    }

    public Node deleteFirstMultiNodeByGender(Node head, Gender gender) {
        for (int i = 0; i < gender.carNum; i++) {
            head = deleteFirstNode(head);
        }
        return head;
    }

    private Node<Card> movedToEnd(Node head, String name) {
        int nameLen = name.length();
//        System.out.println(name + ": 有" + nameLen + "个字");
        if (head == null || head.next == null || nameLen <= 0) {
            return head;
        }
        Node<Card> newHead = null;
        Node<Card> curNode = head;
        for (int i = 0; i < nameLen; i++) {
            addToEnd(head, curNode.card);
            newHead = deleteFirstNode(head);
            curNode = curNode.next;
            head = newHead;
        }
        return newHead;
    }

    public void addToEnd(Node head, Card card){
        Node newNode = new Node(card); // 创建新的节点对象
        Node current = head; // 从头开始查找最后一个节点
        while (current.next != null){
            current = current.next;

        }
        current.setNext(newNode); // 将新节点连接到当前节点的下一个位置
    }


    // 插入某个位置
    public void insert(Node head, Card card, int pos){
        int len = getLinkedListLength(head);
        if (pos >= len) {
            System.out.println("超出长度,插入失败");
            return;
        }

        Node newNode = new Node(card); // 创建新的节点对象

        Node current = head; // 从头开始查找

        for (int i = 0; i < pos; i++) {
            current = current.next;
        }
        Node<Card> nextNode = current.next;
        current.setNext(newNode);
        newNode.setNext(nextNode);
    }

    public Node deleteFirstNode(Node head) {
        head = head.next;
        return head;
    }

    private int getLinkedListLength(Node head) {
       int len = 1;
       Node curNode = head;
       while(curNode.next != null) {
           len++;
           curNode = curNode.next;
       }
       return len;
    }

    private  void printLinkedList(Node head) {
        Node curNode = head;
        while (curNode.next != null) {
            System.out.print(curNode.card + " ");
            curNode = curNode.next;
        }
        System.out.print(curNode.card);
        System.out.println();
    }




    class Card {
        String cardName;
        int cardSign;
        Card(String cardName, int cardSign) {
            this.cardName = cardName;
            this.cardSign = cardSign;
        }
        @Override
        public String toString() {
            return cardName + ":" + String.valueOf(cardSign);
        }
    }

    class Node<Card> {
        Card card;
        Node next;
        Node(Card card) {
            this.card = card;
        }
        void setNext(Node next) {
            this.next = next;
        }

    }

    enum Region {
        NORTH("北方人", 2), SOUTH("南方人", 1), UNKOWN("未知", 3);
        private String regionName;
        private int cardNum;
        Region(String regionName, int cardNum) {
            this.regionName = regionName;
            this.cardNum = cardNum;
        }
    }

    enum Gender{
        MALE("男性", 1), FEMALE("女性", 2);
        private String genderName;
        private int carNum;
        Gender(String genderName, int carNum) {
            this.genderName = genderName;
            this.carNum = carNum;
        }
    }
}

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值