当前位置:   article > 正文

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

刘谦的魔术守岁共此时观后感

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

源代码

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include<stdio.h>
  3. #include<time.h>
  4. #include<stdlib.h>
  5. int main()
  6. {
  7. srand(time(NULL)); // 使用当前时间作为随机数生成器的种子
  8. // 任意选四张牌
  9. int card[4];
  10. printf("请输入四个牌的数字\n");
  11. for (int i = 0; i < 4; i++)
  12. {
  13. scanf("%d", &card[i]); // 输入四张牌的数字
  14. }
  15. int cardend[8];
  16. for (int i = 0; i < 4; i++)
  17. {
  18. cardend[i] = card[i];
  19. }
  20. for (int i = 4; i < 8; i++)
  21. {
  22. cardend[i] = card[i - 4];
  23. }
  24. // 报名字字数
  25. printf("请输入名字个数\n");
  26. int name = 0;
  27. scanf("%d", &name); // 输入名字个数
  28. int x = 0;
  29. for (int i = 0; i < name; i++)
  30. {
  31. x = cardend[0];
  32. for (int j = 0; j < 7; j++)
  33. {
  34. cardend[j] = cardend[j + 1];
  35. }
  36. cardend[7] = x;
  37. }
  38. // 最上面三张插到中间位置
  39. // 取随机数进行处理保证插的位置随机
  40. // 此时剩五张牌,有四个位置
  41. int cardmove[8];
  42. int where = rand() % 4 + 1; // 生成一个1到4之间的随机数
  43. for (int i = 0; i < where; i++)
  44. {
  45. cardmove[i] = cardend[i + 3];
  46. }
  47. int num = 0;
  48. for (int i = where; i < where + 3; i++)
  49. {
  50. cardmove[i] = cardend[num];
  51. num++;
  52. }
  53. int end = 7;
  54. for (int i = 0; i < 5 - where; i++)
  55. {
  56. cardmove[end] = cardend[end];
  57. end--;
  58. }
  59. // 第一张牌
  60. printf("第一张牌为%d\n", cardmove[0]);
  61. cardmove[0] = 0;
  62. for (int i = 0; i < 7; i++)
  63. {
  64. cardmove[i] = cardmove[i + 1];
  65. }
  66. // 南方人输入1,北方人输入2,不确定3张
  67. printf("南方人输入1,北方人输入2,不确定3张\n");
  68. int place = 0;
  69. scanf("%d", &place);
  70. for (int i = 0; i < 8; i++)
  71. {
  72. cardend[i] = cardmove[i];
  73. }
  74. // 根据地区移动牌
  75. // 男生拿一张,女生拿两张
  76. printf("男生拿一张,女生拿两张\n");
  77. int sex = 0;
  78. scanf("%d", &sex);
  79. for (int i = 0; i < sex; i++)
  80. {
  81. cardmove[i] = 0;
  82. }
  83. int numbercard = 8 - sex;
  84. // 见证奇迹的时刻挪七张
  85. printf("见证奇迹的时刻\n");
  86. int magic = 7;
  87. for (int i = 0; i < magic; i++)
  88. {
  89. int first = cardmove[0];
  90. for (int j = 0; j < numbercard; j++)
  91. {
  92. cardmove[j] = cardmove[j + 1];
  93. }
  94. cardmove[numbercard - 1] = first;
  95. }
  96. // 扔牌
  97. int flag = 1;
  98. while (numbercard > 1)
  99. {
  100. if (flag > numbercard)
  101. {
  102. flag -= numbercard;
  103. }
  104. while (cardmove[flag] == 0)
  105. {
  106. flag++;
  107. }
  108. cardmove[flag - 1] = 0;
  109. printf("好运留下来\n");
  110. printf("烦恼丢出去\n");
  111. numbercard--;
  112. }
  113. int endcard = 0;
  114. for (int i = 0; i < 7; i++)
  115. {
  116. if (cardmove[i] != 0)
  117. {
  118. endcard = cardmove[i];
  119. }
  120. }
  121. printf("剩下的第一张为%d\n", endcard);
  122. }

源代码解读

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

#define _CRT_SECURE_NO_WARNINGS 1

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

srand(time(NULL));

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

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

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

  1. int cardend[8];
  2. for (int i = 0; i < 4; i++)
  3. {
  4. cardend[i] = card[i];
  5. }
  6. for (int i = 4; i < 8; i++)
  7. {
  8. cardend[i] = card[i - 4];
  9. }

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

  1. int x = 0;
  2. for (int i = 0; i < name; i++)
  3. {
  4. x = cardend[0];
  5. for (int j = 0; j < 7; j++)
  6. {
  7. cardend[j] = cardend[j + 1];
  8. }
  9. cardend[7] = x;
  10. }

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

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

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

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

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

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

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

  1. // 男生拿一张,女生拿两张
  2. printf("男生拿一张,女生拿两张\n");
  3. int sex = 0;
  4. scanf("%d", &sex);
  5. for (int i = 0; i < sex; i++)
  6. {
  7. cardmove[i] = 0;
  8. }
  9. int numbercard = 8 - sex;

  1. // 见证奇迹的时刻挪七张
  2. printf("见证奇迹的时刻\n");
  3. int magic = 7;
  4. for (int i = 0; i < magic; i++)
  5. {
  6. int first = cardmove[0];
  7. for (int j = 0; j < numbercard; j++)
  8. {
  9. cardmove[j] = cardmove[j + 1];
  10. }
  11. cardmove[numbercard - 1] = first;
  12. }

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

  1. // 扔牌
  2. int flag = 1;
  3. while (numbercard > 1)
  4. {
  5. if (flag > numbercard)
  6. {
  7. flag -= numbercard;
  8. }
  9. while (cardmove[flag] == 0)
  10. {
  11. flag++;
  12. }
  13. cardmove[flag - 1] = 0;
  14. printf("好运留下来\n");
  15. printf("烦恼丢出去\n");
  16. numbercard--;
  17. }

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

  1. int endcard = 0;
  2. for (int i = 0; i < 7; i++)
  3. {
  4. if (cardmove[i] != 0)
  5. {
  6. endcard = cardmove[i];
  7. }
  8. }
  9. printf("剩下的第一张为%d\n", endcard);

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/131049
推荐阅读
相关标签
  

闽ICP备14008679号