【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);

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/385210.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[Python] 文件

这篇是Python基础语法的一个结尾了&#xff0c;还是可莉跟着大家一起学习哦~ 可莉将这篇博客收录在&#xff1a;《Python》 可莉推荐的优质博主主页&#xff1a;Keven ’ s blog 目录 一、文件是什么 二、常用的文件操作函数 1、打开文件 2、关闭文件 3、读取文件 read( ) …

JAVA设计模式之命令模式详解

命令模式 1 命令模式介绍 命令模式(command pattern)的定义: 命令模式将请求&#xff08;命令&#xff09;封装为一个对象&#xff0c;这样可以使用不同的请求参数化其他对象&#xff08;将不同请求依赖注入到其他对象并且能够支持请求&#xff08;命令&#xff09;的排队执行…

jsp课程教学管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 课程教学管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0…

vue3-内置组件-Suspense

Suspense (实验性功能) <Suspense> 是一项实验性功能。它不一定会最终成为稳定功能&#xff0c;并且在稳定之前相关 API 也可能会发生变化。 <Suspense> 是一个内置组件&#xff0c;用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌…

最新Burp Suite入门讲解

Burp Suite的安装 Burp Suite是一款集成化的渗透测试工具&#xff0c;包含了很多功能&#xff0c;可以帮助我们高效地完成对Web应用程序的渗透测试和安全检测。 Burp Suite由Java语言编写&#xff0c;Java自身的跨平台性使我们能更方便地学习和使用这款软件。不像其他自动化测…

Offer必备算法06_位运算_十道力扣OJ题详解_由易到难

目录 位运算算法原理 ①力扣191. 位1的个数 解析代码 ②力扣338. 比特位计数 解析代码 ③力扣461. 汉明距离 解析代码 ④力扣136. 只出现一次的数字 解析代码 ⑤力扣260. 只出现一次的数字 III 解析代码 ⑥力扣面试题 01.01. 判定字符是否唯一 解析代码 ⑦力扣26…

STM32F1 - GPIO外设

GPIO 1> 硬件框图2> 工作模式 1> 硬件框图 2> 工作模式 C语言描述 /** * brief Configuration Mode enumeration */typedef enum { GPIO_Mode_AIN 0x0, // Analog Input 模拟输入 GPIO_Mode_IN_FLOATING 0x04, // input floating 浮空输入GPIO_Mode_I…

Linux第47步_安装支持linux的第三方库和mkimage工具

安装支持linux的第三方库和mkimage工具&#xff0c;做好移植前的准备工作。 编译linux内核之前&#xff0c;需要先在 ubuntu上安装“lzop库”和“libssl-dev库”&#xff0c;否则内核编译会失败。 mkimage工具会在zImage镜像文件的前面添加0x40个字节的头部信息,就可以得到uI…

【JAVA WEB】JavaScript--函数 作用域 对象

目录 函数 语法格式 示例 定义没有参数列表&#xff0c;也没有返回值的一个函数 定义一个有参数列表 &#xff0c;有返回值的函数 关于参数个数 函数表达式 作用域 作用域链 对象 基本概念 创建对象 1.使用 字面量 创建对象 2.使用new Object()创建对象 3.使…

Microsoft Word 超链接

Microsoft Word 超链接 1. 取消超链接2. 自动超链接2.1. 选项2.2. 校对 -> 自动更正选项2.3. Internet 及网络路径替换为超链接 References 1. 取消超链接 Ctrl A -> Ctrl Shift F9 2. 自动超链接 2.1. 选项 2.2. 校对 -> 自动更正选项 ​​​ 2.3. Internet…

java中事务的使用

文章目录 前言一、同一张表1.业务代码2.测试代码3.测试结果 二、不同表1.业务代码2.测试代码3.测试结果 总结 前言 本文将介绍在springboot中使用Transactional注解来完成对数据库事务的操作&#xff0c;保证数据一致性。 一、同一张表 1.业务代码 Controller Controller p…

二、ClickHouse简介

ClickHouse简介 前言一、行式存储二、DBMS功能三、多样化引擎四、高吞吐写入能力五、数据分区与线程级并行六、场景七、特定版本 前言 ClickHouse 是俄罗斯的 Yandex 于 2016 年开源的列式存储数据库&#xff08;DBMS&#xff09;&#xff0c;使用 C 语言编写&#xff0c;主要…

C++线程浅谈

本篇文章我们来介绍一下C 多进程 多线程的技术 1.为什要学习多线程 多进程 提高程序的性能&#xff1a;进程和线程可以使程序并发执行&#xff0c;从而充分利用计算机的多核处理器和资源&#xff0c;提高程序的执行效率和吞吐量。 实现复杂任务&#xff1a;通过将任务划分为多…

Acwing---842.排列数字

排列数字 1.题目2.基本思想3.代码实现 1.题目 给定一个整数 n&#xff0c;将数字 1∼n排成一排&#xff0c;将会有很多种排列方法。 现在&#xff0c;请你按照字典序将所有的排列方法输出。 输入格式 共一行&#xff0c;包含一个整数 n。 输出格式 按字典序输出所有排列方案…

Java安全 URLDNS链分析

Java安全 URLDNS链分析 什么是URLDNS链URLDNS链分析调用链路HashMap类分析URL类分析 exp编写思路整理初步expexp改进最终exp 什么是URLDNS链 URLDNS链是Java安全中比较简单的一条利用链&#xff0c;无需使用任何第三方库&#xff0c;全依靠Java内置的一些类实现&#xff0c;但…

读千脑智能笔记12_阻止人类灭绝

1. 阻止人类灭绝 1.1. 宇宙中唯一知道这些的物体&#xff0c;唯一知道宇宙存在的物体&#xff0c;是我们的大脑 1.2. 如果没有关于某个事物的知识&#xff0c;我们能说这个事物就一定存在吗&#xff1f; 1.2.1. 我们的大脑扮演着这样一个独特的角色&#xff0c;这很令人着迷…

使用matplotlib库在Python中绘制散点图

使用matplotlib库在Python中绘制散点图&#xff0c;展示了两个月份的气温变化。 # coding: utf-8 from matplotlib import pyplot as plt # 导入matplotlib库中的pyplot模块&#xff0c;并重命名为plt from matplotlib import font_manager # 导入font_manager模块&#xff…

代码随想录刷题笔记 DAY 23 | 修剪二叉搜索树 No.669 | 将有序数组转换为二叉搜索树 No.108 | 把二叉搜索树转换为累加树 No.538

文章目录 Day 2301. 修剪二叉搜索树&#xff08;No. 669&#xff09;1.1 题目1.2 笔记1.3 代码 02. 将有序数组转换为二叉搜索树&#xff08;No. 108&#xff09;2.1 题目2.2 笔记2.3 代码 03. 把二叉搜索树转换为累加树&#xff08;No. 538&#xff09;3.1 题目3.2 笔记3.3 代…

Linux_进程地址空间

我们用c语言写的程序&#xff0c;经过编译后形成可执行程序存放在硬盘。当运行该程序时&#xff0c;操作系统将该程序加载到内存中&#xff0c;创建进程控制块&#xff0c;变为进程&#xff0c;然后开始执行该程序。大家是否想过&#xff0c;操作系统是如何加载的呢&#xff1b…

有状态DHCPv6快速模式配置及EUI-64介绍

正文共&#xff1a;1024 字 15 图&#xff0c;预估阅读时间&#xff1a;3 分钟 我们现在已经熟悉了IPv6的地址架构&#xff08;IPv6地址架构一本通&#xff09;&#xff0c;掌握了IPv6地址的手工配置方式&#xff08;IPv6从入门到精通&#xff09;和DHCPv6有状态地址配置&#…