【C语言】解析刘谦春晚魔术《守岁共此时》

简介: 【C语言】解析刘谦春晚魔术《守岁共此时》

今年的春晚上刘谦表演了魔术《守岁共此时》,台上台下积极互动(尤其是小尼),十分的有趣。刘谦老师的魔术不仅仅是他的高超手法,还有这背后的严谨逻辑,下面我们来用C语言来解析魔术吧。


源代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
int main()
{
    srand(time(NULL)); // 使用当前时间作为随机数生成器的种子
    // 任意选四张牌
    int card[4];
    printf("请输入四个牌的数字\n");
    for (int i = 0; i < 4; i++)
    {
        scanf("%d", &card[i]); // 输入四张牌的数字
    }
    int cardend[8];
    for (int i = 0; i < 4; i++)
    {
        cardend[i] = card[i];
    }
    for (int i = 4; i < 8; i++)
    {
        cardend[i] = card[i - 4];
    }
    // 报名字字数
    printf("请输入名字个数\n");
    int name = 0;
    scanf("%d", &name); // 输入名字个数
    int x = 0;
    for (int i = 0; i < name; i++)
    {
        x = cardend[0];
        for (int j = 0; j < 7; j++)
        {
            cardend[j] = cardend[j + 1];
        }
        cardend[7] = x;
    }
    // 最上面三张插到中间位置
    // 取随机数进行处理保证插的位置随机
    // 此时剩五张牌,有四个位置
    int cardmove[8];
    int where = rand() % 4 + 1; // 生成一个1到4之间的随机数
    for (int i = 0; i < where; i++)
    {
        cardmove[i] = cardend[i + 3];
    }
    int num = 0;
    for (int i = where; i < where + 3; i++)
    {
        cardmove[i] = cardend[num];
        num++;
    }
    int end = 7;
    for (int i = 0; i < 5 - where; i++)
    {
        cardmove[end] = cardend[end];
        end--;
    }
    // 第一张牌
    printf("第一张牌为%d\n", cardmove[0]);
    cardmove[0] = 0;
    for (int i = 0; i < 7; i++)
    {
        cardmove[i] = cardmove[i + 1];
    }
    // 南方人输入1,北方人输入2,不确定3张
    printf("南方人输入1,北方人输入2,不确定3张\n");
    int place = 0;
    scanf("%d", &place);
    for (int i = 0; i < 8; i++)
    {
        cardend[i] = cardmove[i];
    }
    // 根据地区移动牌
    // 男生拿一张,女生拿两张
    printf("男生拿一张,女生拿两张\n");
    int sex = 0;
    scanf("%d", &sex);
    for (int i = 0; i < sex; i++)
    {
        cardmove[i] = 0;
    }
    int numbercard = 8 - sex;
    // 见证奇迹的时刻挪七张
    printf("见证奇迹的时刻\n");
    int magic = 7;
    for (int i = 0; i < magic; i++)
    {
        int first = cardmove[0];
        for (int j = 0; j < numbercard; j++)
        {
            cardmove[j] = cardmove[j + 1];
        }
        cardmove[numbercard - 1] = first;
    }
    // 扔牌
    int flag = 1;
    while (numbercard > 1)
    {
        if (flag > numbercard)
        {
            flag -= numbercard;
        }
        while (cardmove[flag] == 0)
        {
            flag++;
        }
        cardmove[flag - 1] = 0;
        printf("好运留下来\n");
        printf("烦恼丢出去\n");
        numbercard--;
    }
    int endcard = 0;
    for (int i = 0; i < 7; i++)
    {
        if (cardmove[i] != 0)
        {
            endcard = cardmove[i];
        }
    }
    printf("剩下的第一张为%d\n", endcard);
}

源代码解读

请对照上文的代码进行翻阅

#define _CRT_SECURE_NO_WARNINGS 1

这行代码是用来定义预处理器宏,用于禁用安全警告。在这里,它可能是为了避免一些特定的安全警告(scanf)。

srand(time(NULL));

这行代码使用当前时间作为随机数生成器的种子,以便在后续使用 rand() 生成随机数时能够获得不同的随机序列。

// 任意选四张牌
    int card[4];
    printf("请输入四个牌的数字\n");
    for (int i = 0; i < 4; i++)
    {
        scanf("%d", &card[i]); // 输入四张牌的数字
    }

创建一个数组用来存贮选择的牌。

int cardend[8];
    for (int i = 0; i < 4; i++)
    {
        cardend[i] = card[i];
    }
    for (int i = 4; i < 8; i++)
    {
        cardend[i] = card[i - 4];
    }

将输入的四张牌按顺序复制到名为 cardend 的数组中,并将其重复一次,以便后续的处理。

int x = 0;
    for (int i = 0; i < name; i++)
    {
        x = cardend[0];
        for (int j = 0; j < 7; j++)
        {
            cardend[j] = cardend[j + 1];
        }
        cardend[7] = x;
    }

根据输入的名字个数,将牌进行移动,具体地,将数组 cardend 中的第一个元素依次移到数组的末尾,这个过程重复了名字个数次。

// 最上面三张插到中间位置
    // 取随机数进行处理保证插的位置随机
    // 此时剩五张牌,有四个位置
    int cardmove[8];
    int where = rand() % 4 + 1; // 生成一个1到4之间的随机数
    for (int i = 0; i < where; i++)
    {
        cardmove[i] = cardend[i + 3];
    }
    int num = 0;
    for (int i = where; i < where + 3; i++)
    {
        cardmove[i] = cardend[num];
        num++;
    }
    int end = 7;
    for (int i = 0; i < 5 - where; i++)
    {
        cardmove[end] = cardend[end];
        end--;
    }

随机生成一个数 where,然后将数组 cardend 中的一部分元素插入到数组 cardmove 的中间位置。

// 第一张牌
printf("第一张牌为%d\n", cardmove[0]);
cardmove[0] = 0;
for (int i = 0; i < 7; i++)
{
    cardmove[i] = cardmove[i + 1];
}

输出数组 cardmove 中的第一个元素,并将其置为0。

// 南方人输入1,北方人输入2,不确定3张
    printf("南方人输入1,北方人输入2,不确定3张\n");
    int place = 0;
    scanf("%d", &place);
    for (int i = 0; i < 8; i++)
    {
        cardend[i] = cardmove[i];
    }

根据用户输入的地区,移动牌的位置。

// 男生拿一张,女生拿两张
    printf("男生拿一张,女生拿两张\n");
    int sex = 0;
    scanf("%d", &sex);
    for (int i = 0; i < sex; i++)
    {
        cardmove[i] = 0;
    }
    int numbercard = 8 - sex;
// 见证奇迹的时刻挪七张
    printf("见证奇迹的时刻\n");
    int magic = 7;
    for (int i = 0; i < magic; i++)
    {
        int first = cardmove[0];
        for (int j = 0; j < numbercard; j++)
        {
            cardmove[j] = cardmove[j + 1];
        }
        cardmove[numbercard - 1] = first;
    }

对牌堆进行特定的移动,重复了7次。

// 扔牌
    int flag = 1;
    while (numbercard > 1)
    {
        if (flag > numbercard)
        {
            flag -= numbercard;
        }
        while (cardmove[flag] == 0)
        {
            flag++;
        }
        cardmove[flag - 1] = 0;
        printf("好运留下来\n");
        printf("烦恼丢出去\n");
        numbercard--;
    }

根据特定的规则,不断扔掉牌,直到只剩下一张牌。

int endcard = 0;
    for (int i = 0; i < 7; i++)
    {
        if (cardmove[i] != 0)
        {
            endcard = cardmove[i];
        }
    }
    printf("剩下的第一张为%d\n", endcard);

输出最后剩下的一张牌的数字,魔术结束。

祝大家新年快乐,龙年大吉!!


目录
相关文章
|
16天前
|
C语言
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
|
16天前
|
编译器 C语言
操作符详解(C语言基础深入解析)
操作符详解(C语言基础深入解析)
|
1月前
|
存储 编译器 Linux
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
|
11天前
|
存储 程序员 C语言
【C 言专栏】C 语言指针的深度解析
【4月更文挑战第30天】C 语言中的指针是程序设计的关键,它如同一把钥匙,提供直接内存操作的途径。指针是存储其他变量地址的变量,通过声明如`int *ptr`来使用。它们在动态内存分配、函数参数传递及数组操作中发挥重要作用。然而,误用指针可能导致错误,如空指针引用和内存泄漏。理解指针的运算、与数组和函数的关系,以及在结构体中的应用,是成为熟练 C 语言程序员的必经之路。虽然挑战重重,但掌握指针将增强编程效率和灵活性。不断实践和学习,我们将驾驭指针,探索更广阔的编程世界。
|
16天前
|
存储 C语言
指针深入解析(C语言基础)带你走进指针,了解指针
指针深入解析(C语言基础)带你走进指针,了解指针
|
16天前
|
存储 编译器 C语言
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
|
16天前
|
C语言 C++
C语言:指针运算笔试题解析(包括令人费解的指针题目)
C语言:指针运算笔试题解析(包括令人费解的指针题目)
|
16天前
|
机器学习/深度学习 C语言
函数递归深入解析(C语言)
函数递归深入解析(C语言)
|
16天前
|
编译器 C语言
函数深入解析(C语言基础入门)
函数深入解析(C语言基础入门)
|
16天前
|
C语言
循坏语句解析(C语言零基础教程)
循坏语句解析(C语言零基础教程)

推荐镜像

更多