【C#】使用代码实现龙年春晚扑克牌魔术(守岁共此时),代码实现篇

欢迎来到《小5讲堂》
大家好,我是全栈小5。
这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解,
特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握。
温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!

在这里插入图片描述

目录

  • 前言
  • 实现步骤
    • 设置牌
    • 随机牌
    • 撕开两半
    • 姓名牌
    • 任意牌
    • 标记牌
    • 区域牌
    • 性别牌
    • 循环牌
    • 好运牌
  • 约瑟夫原理
  • 完整代码
    • 主要代码
    • 打乱顺序
  • 相关文章

前言

2024年春晚上,表演了一个魔术《守岁共此时》,博主也跟着做了一遍,确实都成功了。
对于此魔术的好奇心,博主从代码逻辑的角度思考了下,肯定是可以实现的,毕竟代码只是一个工具,只要实际逻辑合理基本没问题。
上一篇已经对魔术步骤进行了描述,本篇文章将通过代码步骤进行描述和实现。
实际上,了解原理后,使用递归方法和循环队列去实现是比较合理的。

实现步骤

为了方便查看,每一个步骤都把变化前的扑克牌保存到一个泛型变量里
##设置变量
姓名、来自区域、以及性别,这三者为变量,决定每个人手上牌的顺序会不一样。

string myName = "小美";
string positionValue = "北方人";
string sex = "女生";

设置牌

设置好52张扑克牌

List<string> tempList = new List<string>();string pokerStr = @"黑桃-A、黑桃-2、黑桃-3、黑桃-4、黑桃-5、黑桃-6、黑桃-7、黑桃-8、黑桃-9、黑桃-10、黑桃-J、黑桃-Q、黑桃-K、
红桃-A、红桃-2、红桃-3、红桃-4、红桃-5、红桃-6、红桃-7、红桃-8、红桃-9、红桃-10、红桃-J、红桃-Q、红桃-K、
梅花-A、梅花-2、梅花-3、梅花-4、梅花-5、梅花-6、梅花-7、梅花-8、梅花-9、梅花-10、梅花-J、梅花-Q、梅花-K、
方块-A、方块-2、方块-3、方块-4、方块-5、方块-6、方块-7、方块-8、方块-9、方块-10、方块-J、方块-Q、方块-K";
List<string> pokerList = pokerStr.Split('、').Select(a=>a.Replace("\r\n","").Trim()).ToList();

随机牌

通过上一步骤设置的52张牌,随机产生4张牌

// 随机四张
List<string> myPokerList = new List<string>();
for(int i = 0; i < 4; i++)
{int randomIndex = new Random().Next(0, pokerList.Count);string pokder = pokerList[randomIndex];myPokerList.Add(pokder);pokerList.RemoveAt(randomIndex);
}

在这里插入图片描述

撕开两半

撕开两半,并且右边的一半放到底部,对于数组而言实际上就是放到首位

// 撕开2半
List<string> newList = new List<string>();
tempList = NewOrder(myPokerList);// 右半边
for (int i = 0; i < tempList.Count; i++)
{newList.Add($"{tempList[i]}-右");
}// 左半边
for (int i = 0; i < tempList.Count; i++)
{newList.Add($"{tempList[i]}-左");
}

在这里插入图片描述

姓名牌

每个人姓名长度不一样,顺序也就不一样,下面代码实现比较逻辑,其实目标就是把最上面的一张牌放到底部,多少个字就放几次。
博主姓名是三个字,就依次放三张牌到底部。代码实现逻辑就是数组最后一个值放到首位。

// 姓名数字 - 动态值
int myNameLength = myName.Length;
string nameString = string.Empty;
List<string> nameList = new List<string>();
List<string> nameListMy = new List<string>();
for (int i = 0; i < myNameLength; i++)
{string pv = newList[newList.Count - 1 - i];nameListMy.Add(pv);nameString = $"{pv},{nameString}";
}
for (int i = 0; i < newList.Count - myNameLength; i++)
{nameString += $",{newList[i]}";
}
nameList = nameString.Split(',').Where(a => !string.IsNullOrWhiteSpace(a)).ToList();

在这里插入图片描述

任意牌

拿起最上面3张牌,插入到任意牌的中间,1、2、3、4、5,1到5之间插入

// 
int topValue = 3;
int randomValue = new Random().Next(1, nameList.Count - topValue - 1);
List<string> top3List = new List<string>();
for (int i = 0; i < nameList.Count - topValue; i++)
{if (i == randomValue){for (int j = topValue; j > 0; j--){top3List.Add(nameList[nameList.Count - j]);}}top3List.Add(nameList[i]);
}

在这里插入图片描述

标记牌

拿起最上面一张牌,就是黑桃3-右,放到一遍,在数组里就是移除此张牌,并保存到一个变量里

// 【第一次移除牌】
// 拿起最上面一张牌,就是黑桃3-右,放到一遍
string topPoker = top3List[top3List.Count - 1];
List<string> sevenList = new List<string>();
for (int i = 0; i < top3List.Count - 1; i++)
{sevenList.Add(top3List[i]);
}

在这里插入图片描述

区域牌

南方人:拿起一张牌、北方人:拿起两张牌、不知道是南方还是北方人:拿起三张牌
插入到剩下牌的中间,1到5或者1到6之间插入

// int fromValue = (positionValue == "南方人" ? 1 : positionValue == "北方人" ? 2 : 3);
int randomValue2 = new Random().Next(1, sevenList.Count - fromValue - 1);
List<string> fromList = new List<string>();
for (int i = 0; i < sevenList.Count - fromValue; i++)
{if (i == randomValue2){for (int j = fromValue; j > 0; j--){fromList.Add(sevenList[sevenList.Count - j]);}}fromList.Add(sevenList[i]);
}

在这里插入图片描述

性别牌

男生:拿起一张、女生:拿起两张、拿起的牌,撒到空中去,就是从数组中移除

// 【再次移除牌】int sexType = (sex == "男生" ? 1 : 2);
List<string> sexList = new List<string>();
for (int i = 0; i < fromList.Count - sexType; i++)
{sexList.Add(fromList[i]);
}

在这里插入图片描述

循环牌

见证奇迹的时刻,这是七个字,就是循环遍历7次,对于数组而言,就是循环从最后一个值移动到第一个值。

string textValue = "见证奇迹的时刻";
List<string> forList = new List<string>();
for (int i = 0; i < sexList.Count; i++)
{forList.Add(sexList[i]);
}for (int i = 0; i < textValue.Length; i++)
{string lastElement = forList[forList.Count - 1]; // 保存最后一个元素的值forList.RemoveAt(forList.Count - 1); // 移除最后一个元素forList.Insert(0, lastElement); // 将最后一个元素插入到第一个位置
}

在这里插入图片描述

好运牌

最后一个环节:好运留下来,烦恼丢出去
第一张放到下面,然后最上面的丢出去,就是移除数组最后一个

// List<string> lastList = new List<string>();
for (int i = 0; i < forList.Count; i++)
{lastList.Add(forList[i]);
}
while (lastList.Count > 1)
{string lastElement = lastList[lastList.Count - 1]; // 保存最后一个元素的值lastList.RemoveAt(lastList.Count - 1); // 移除最后一个元素lastList.Insert(0, lastElement); // 将最后一个元素插入到第一个位置lastList.RemoveAt(lastList.Count - 1);
}
string lastPoker = lastList[0];// 合并扑克牌
string allPoker = $"【{lastPoker}】【{topPoker}】";

在这里插入图片描述

约瑟夫原理

上面扑克牌魔术没想到用到了这个原理,不是每个人都能快速理解各种各样的原理,所以这也早就了魔术神奇而又神秘的一面。

约瑟夫原理(也称为约瑟夫问题或约瑟夫环)是一个著名的理论问题,其起源可以追溯到公元1世纪的一个历史事件。据传,著名犹太历史学家Josephus和他的同伴被敌人包围,在面临绝境时,他们决定通过自杀的方式结束生命。为了执行这个决定,他们围成一个圈,然后按照一定的规则来选择自杀的人,直到只剩下最后一个人。Josephus作为一个不愿意自杀的人,快速地计算出了一个位置,使得他成为了最后一个存活的人,从而有机会逃脱。

这个问题可以用数学模型进行抽象和解释。假设有n个人围成一圈,从某个人开始,按顺时针方向逐一编号。接着从编号为1的人开始报数,每数到m就将该人从圈中排除,然后从下一个人重新开始报数,直到圈中只剩下一个人。最后剩下的这个人的位置就是从1开始数的序号。这个问题可以用数学公式或伪代码进行求解。

约瑟夫原理在理论计算机科学、组合数学、离散数学等领域有着广泛的应用。它不仅是一个有趣的问题,还可以用于解决各种实际问题,如任务调度、资源管理、网络通信等。通过研究和应用约瑟夫原理,可以更好地理解和解决一些复杂的计算和决策问题。

完整代码

博主使用C#语言比较多,因此下面是以C#代码进行实现,感兴趣的小伙伴可以使用其他语言实现

主要代码

string myName = "小美";
string positionValue = "北方人";
string sex = "女生";List<string> tempList = new List<string>();string pokerStr = @"黑桃-A、黑桃-2、黑桃-3、黑桃-4、黑桃-5、黑桃-6、黑桃-7、黑桃-8、黑桃-9、黑桃-10、黑桃-J、黑桃-Q、黑桃-K、
红桃-A、红桃-2、红桃-3、红桃-4、红桃-5、红桃-6、红桃-7、红桃-8、红桃-9、红桃-10、红桃-J、红桃-Q、红桃-K、
梅花-A、梅花-2、梅花-3、梅花-4、梅花-5、梅花-6、梅花-7、梅花-8、梅花-9、梅花-10、梅花-J、梅花-Q、梅花-K、
方块-A、方块-2、方块-3、方块-4、方块-5、方块-6、方块-7、方块-8、方块-9、方块-10、方块-J、方块-Q、方块-K";
List<string> pokerList = pokerStr.Split('、').Select(a=>a.Replace("\r\n","").Trim()).ToList();// 随机四张
List<string> myPokerList = new List<string>();
for(int i = 0; i < 4; i++)
{int randomIndex = new Random().Next(0, pokerList.Count);string pokder = pokerList[randomIndex];myPokerList.Add(pokder);pokerList.RemoveAt(randomIndex);
}// 撕开2半
List<string> newList = new List<string>();
tempList = NewOrder(myPokerList);// 右半边
for (int i = 0; i < tempList.Count; i++)
{newList.Add($"{tempList[i]}-右");
}// 左半边
for (int i = 0; i < tempList.Count; i++)
{newList.Add($"{tempList[i]}-左");
}// 姓名数字 - 动态值
int myNameLength = myName.Length;
string nameString = string.Empty;
List<string> nameList = new List<string>();
List<string> nameListMy = new List<string>();
for (int i = 0; i < myNameLength; i++)
{string pv = newList[newList.Count - 1 - i];nameListMy.Add(pv);nameString = $"{pv},{nameString}";
}
for (int i = 0; i < newList.Count - myNameLength; i++)
{nameString += $",{newList[i]}";
}
nameList = nameString.Split(',').Where(a => !string.IsNullOrWhiteSpace(a)).ToList();// 拿起最上面3张牌,插入到任意牌的中间,1、2、3、4、5,1到5之间插入
int topValue = 3;
int randomValue = new Random().Next(1, nameList.Count - topValue - 1);
List<string> top3List = new List<string>();
for (int i = 0; i < nameList.Count - topValue; i++)
{if (i == randomValue){for (int j = topValue; j > 0; j--){top3List.Add(nameList[nameList.Count - j]);}}top3List.Add(nameList[i]);
}// 【第一次移除牌】
// 拿起最上面一张牌,就是黑桃3-右,放到一遍
string topPoker = top3List[top3List.Count - 1];
List<string> sevenList = new List<string>();
for (int i = 0; i < top3List.Count - 1; i++)
{sevenList.Add(top3List[i]);
}// 南方人:拿起一张牌、北方人:拿起两张牌、不知道是南方还是北方人:拿起三张牌
// 插入到剩下牌的中间,1到5或者1到6之间插入
int fromValue = (positionValue == "南方人" ? 1 : positionValue == "北方人" ? 2 : 3);
int randomValue2 = new Random().Next(1, sevenList.Count - fromValue - 1);
List<string> fromList = new List<string>();
for (int i = 0; i < sevenList.Count - fromValue; i++)
{if (i == randomValue2){for (int j = fromValue; j > 0; j--){fromList.Add(sevenList[sevenList.Count - j]);}}fromList.Add(sevenList[i]);
}// 【再次移除牌】
// 男生:拿起一张、女生:拿起两张、拿起的牌,撒到空中去,就是从数组中移除
int sexType = (sex == "男生" ? 1 : 2);
List<string> sexList = new List<string>();
for (int i = 0; i < fromList.Count - sexType; i++)
{sexList.Add(fromList[i]);
}// 见证奇迹的时刻
string textValue = "见证奇迹的时刻";
List<string> forList = new List<string>();
for (int i = 0; i < sexList.Count; i++)
{forList.Add(sexList[i]);
}for (int i = 0; i < textValue.Length; i++)
{string lastElement = forList[forList.Count - 1]; // 保存最后一个元素的值forList.RemoveAt(forList.Count - 1); // 移除最后一个元素forList.Insert(0, lastElement); // 将最后一个元素插入到第一个位置
}// 最后一个环节:好运留下来,烦恼丢出去
// 第一张放到下面,然后最上面的丢出去,就是移除数组最后一个
List<string> lastList = new List<string>();
for (int i = 0; i < forList.Count; i++)
{lastList.Add(forList[i]);
}
while (lastList.Count > 1)
{string lastElement = lastList[lastList.Count - 1]; // 保存最后一个元素的值lastList.RemoveAt(lastList.Count - 1); // 移除最后一个元素lastList.Insert(0, lastElement); // 将最后一个元素插入到第一个位置lastList.RemoveAt(lastList.Count - 1);
}
string lastPoker = lastList[0];// 合并扑克牌
string allPoker = $"【{lastPoker}】【{topPoker}】";

打乱顺序

private List<string> NewOrder(List<string> list)
{Random random = new Random();for (int i = list.Count - 1; i > 0; i--){int j = random.Next(i + 1);string temp = list[i];list[i] = list[j];list[j] = temp;}return list;
}

相关文章

【C#】使用代码实现刘谦龙年春晚扑克牌魔术(守岁共此时),代码实现篇
【C#】使用代码实现刘谦龙年春晚扑克牌魔术(守岁共此时),流程描述篇
【C#】约瑟夫原理举例2个代码实现
【C#】List泛型数据集如何循环移动,最后一位移动到第一位,以此类推

温故而知新,不同阶段重温知识点,会有不一样的认识和理解,博主将巩固一遍知识点,并以实践方式和大家分享,若能有所帮助和收获,这将是博主最大的创作动力和荣幸。也期待认识更多优秀新老博主。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用VBA将多个txt批量转换成excel表并保存

VBA将多个txt批量转换成excel表并保存 Sub ykcbf() Set fso CreateObject("scripting.filesystemobject")Application.ScreenUpdating FalseApplication.DisplayAlerts Falsep ThisWorkbook.Path & ""On Error Resume NextFor Each f In fso.GetF…

Linux文件监控方法

Linux系统开发程序&#xff0c;有时候需要监控配置文件的变化&#xff0c;做出相应操作&#xff0c;下面将介绍常用的文件、目录监控方法&#xff1a; 函数介绍&#xff1a; 1.Inotify系列函数&#xff1a; Inotify_init&#xff08;void&#xff09; 系统返回一个文件描述…

mac下mysql 常用命令

mysql启动命令 在Mac OS X启动和停止MySQL服务的命令&#xff0c; 启动MySQL服务 sudo /usr/local/mysql/support-files/mysql.server start 停止MySQL服务 sudo /usr/local/mysql/support-files/mysql.server stop 重启MySQL服务 sudo /usr/local/mysql/support-files/mys…

大模型量化技术原理-LLM.int8()、GPTQ

近年来&#xff0c;随着Transformer、MOE架构的提出&#xff0c;使得深度学习模型轻松突破上万亿规模参数&#xff0c;从而导致模型变得越来越大&#xff0c;因此&#xff0c;我们需要一些大模型压缩技术来降低模型部署的成本&#xff0c;并提升模型的推理性能。 模型压缩主要分…

不知如何获取1688工厂档案信息,你还在为此烦恼吗?

阿里巴巴集团旗下的B2B电子商务网站&#xff0c;提供海量优质商品&#xff0c;为采购商和供应商提供交流、合作、采购等服务&#xff0c;是很多没有货源优势的电商卖家首选的货源途径&#xff0c;也是国内最大、货源种类最齐全的货源网站。 不少做跨境电商无货源的朋友都想要1…

MySQL学习记录——십삼 视图及用户、权限管理

文章目录 1、视图2、用户管理3、权限管理 1、视图 视图把查询出来的结果以表结构的形式存储起来&#xff0c;视图和基表有关系&#xff0c;两者的数据变化都会互相影响。 在查询时&#xff0c;假如要经常查询一条记录&#xff0c;select …&#xff0c;那么为了方便&#xff…

用html编写的招聘简历

用html编写的招聘简历 相关代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</tit…

C语言:指针与内存

C语言&#xff1a;指针与内存 内存与地址指针变量取地址指针变量解引用指针的大小 指针运算指针 - 整数指针 - 指针指针关系运算 const修饰指针字符指针野指针assert断言传址调用 内存与地址 计算机上CPU&#xff08;中央处理器&#xff09;在处理数据的时候&#xff0c;需要…

rk3568 WDG

rk3568 WDG 在嵌入式系统中,看门狗(Watchdog)是一种用于监控系统运行状态并在系统出现故障或死锁时自动重启系统的机制。 监控系统运行状态:看门狗定时器会周期性地计数,在规定的时间内如果系统未能对看门狗进行喂狗操作(即重置看门狗计数器),就会认为系统出现故障或死…

探索JDK5的新特性:革新编程体验的里程碑

引言 Java Development Kit (JDK) 5&#xff0c;于2004年发布&#xff0c;是Java发展历程中具有里程碑意义的一个版本。它不仅引入了一系列关键的编程新特性&#xff0c;还大大提升了开发者的生产力和代码质量。本文将带领大家深入了解JDK 5带来的变革性创新&#xff0c;包括泛…

自定义异常处理演示

​ 为了防止黑客从前台异常信息&#xff0c;对系统进行攻击。同时&#xff0c;为了提高用户体验&#xff0c;我们都会都抛出的异常进行拦截处理。 一、全局异常处理 编写一个异常拦截类&#xff0c;如下&#xff1a;ControllerAdvice&#xff0c;很多初学者可能都没有听说过…

《最新出炉》系列初窥篇-Python+Playwright自动化测试-19-处理鼠标拖拽-中篇

1.简介 上一篇中&#xff0c;主要是介绍了拖拽的各种方法的理论知识以及实践&#xff0c;今天宏哥讲解和分享一下划取字段操作。例如&#xff1a;需要在一堆log字符中随机划取一段文字&#xff0c;然后右键选择摘取功能。 2.划取字段操作 划取字段操作就是在一段文字中随机选…

Linux系统——http协议介绍

目录 引言——Internet起源 一、http协议——超文本传输协议 1.http相关概念 2.访问浏览器的过程 3.http协议通信过程 4.http相关技术 4.1WEB开发语言 4.2html 4.3CSS 4.4JS 5.MIME——Multipurpose Internet Mail Extensions 多用途互联网邮件扩展 6.URI URN URL的…

ubuntu配置pip

windows的pip镜像 在C:\Users\当前用户\下创建.pip文件夹在.pip下创建pip.ini文件编辑pip.ini添加如下内容 [global] index-url https://mirror.baidu.com/pypi/simple [install] trusted-host https://mirror.baidu.com/pypi ubuntu的pip镜像 当前用户的pip镜像 1. 进入用…

申请 Segfault 的免费 VPS

打开 Segfault 的官网&#xff1a;https://shell.segfault.net/&#xff0c;然后点击“I’m new here”在弹出的窗口中&#xff0c;复制以保存访问密钥点击 continue&#xff0c;进入主页&#xff0c;然后敲回车以创建服务器如需重返回自己的服务器&#xff0c;可以在官网点击“…

【Redis,Java】Redis的两种序列化方式—nosql数据库

redis和mysql的区别&#xff1a; redis是属于nosql的数据库&#xff0c;而mysql是属于sql数据库&#xff0c;redis是属于nosql数据库。mysql是存储在磁盘中的&#xff0c;redis是存储在内存中的&#xff0c;所以redis的读取书读快。这里所说的redis代表nosql&#xff0c;而mysq…

【wails】(1):使用go做桌面应用开发,wails框架入门学习,在Linux上搭建环境,运行demo项目,并打包测试

1&#xff0c;视频地址 https://www.bilibili.com/video/BV1fK421b7QC/ 【wails】&#xff08;1&#xff09;&#xff1a;使用go做桌面应用开发&#xff0c;wails框架入门学习&#xff0c;在Linux上搭建环境&#xff0c;运行demo项目&#xff0c;并打包测试 2&#xff0c;参考…

在Ubuntu中使用python

目录 一、利用vim使用python 1、下载vim 2、使用vim创建python文件 3、编辑完成后的vim操作 4、如何运行 5、vim常见操作 二、安装Jupyter 1、更新系统 2、安装pip 注&#xff1a;pip无法应用的原因及解决方案 3、安装Jupyter 4、打开Jupyter 三、安装其他Python模…

ActiveMQ高可用架构涉及常用功能整理

ActiveMQ高可用架构涉及常用功能整理 1. activemq的集群模式2. 镜像模式高可用系统架构和相关组件2.1 架构说明2.2 相关概念说明2.3 消息模型2.3.1 点对点2.3.2 发布订阅 3. activemq常用命令4. activemq配置集群5. 疑问和思考5.1 activemq的数据删除策略是怎样的&#xff1f;5…

C++ 中的单例模式singleton

C 中的单例模式 引言 在面向对象编程中&#xff0c;设计模式是解决常见问题的最佳实践。单例模式是其中之一&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。在本文中&#xff0c;我们将详细介绍 C 中的单例模式。 什么是单例模式&…