哪些网站是503错误代码,太原搭建网站的公司,新wordpress仿站,网站根目录文件夹洗牌算法是一种将序列#xff08;如数组、列表#xff09;元素随机打乱的经典算法#xff0c;核心目标是让每个元素在打乱后出现在任意位置的概率均等。在 C# 中#xff0c;常用的洗牌算法有Fisher-Yates 洗牌算法#xff08;也称 Knuth 洗牌算法#xff09;#xff0c;…洗牌算法是一种将序列如数组、列表元素随机打乱的经典算法核心目标是让每个元素在打乱后出现在任意位置的概率均等。在 C# 中常用的洗牌算法有Fisher-Yates 洗牌算法也称 Knuth 洗牌算法它高效且公平时间复杂度为 O (n)空间复杂度为 O (1)。一、Fisher-Yates 洗牌算法原理核心思想从序列的最后一个元素开始依次与前面的随机位置元素交换直到处理完第一个元素。公平性保证每个元素被放置在任意位置的概率均为 1/nn 为序列长度避免了 “部分随机” 导致的分布不均问题。二、C# 实现示例以下是使用 Fisher-Yates 算法对整数数组、字符串列表进行洗牌的实现代码分块分析这段代码是一个简化的斗地主游戏实现主要包含扑克牌的生成、洗牌、发牌和排序功能。下面我将对代码进行分块分析。1. 主程序结构与初始化
static void Main(string[] args)
{int[] ints1 new int[54];ints1 RandomUNorepeatArray(ints1);// 后续代码...
}这部分代码首先创建了一个包含 54 个元素的整数数组ints1并调用RandomUNorepeatArray方法生成 0-53 的随机不重复数组用于作为扑克牌的随机索引。2. 扑克牌对象模型
class Puke
{public string number;public char color;public override string ToString(){return $[{number},{color}];}
}Puke类表示一张扑克牌包含两个属性number牌面数字字符串类型1-13 或 jokercolor花色字符类型 黑 、 红 、 梅 、 方 重写的ToString方法用于格式化输出牌的信息3. 扑克牌生成与初始化
Puke[] puke new Puke[54];
int num 1;
char[] str new char[4] {黑, 红, 梅, 方 };
int num2 3;
for (int i 0; i 52; i)
{puke[i] new Puke();if (num 13){num 1;num2--;}puke[i].number num.ToString();num;puke[i].color str[num2];
}
puke[52] new Puke { number joker, color 黑 };
puke[53] new Puke { number joker, color 红 };这段代码生成了 54 张扑克牌前 52 张是四种花色的 A-K用数字 1-13 表示最后两张是大小王joker4. 洗牌与发牌
Puke[] puke2 new Puke[54];
for (int i 0; i 54; i)
{puke2[i] puke[ints1[i]];
}
// 发牌给三个玩家和底牌
Puke[] puke3 new Puke[17];
Puke[] puke4 new Puke[17];
Puke[] puke5 new Puke[17];
Puke[] puke6 new Puke[3];
for (int i 0; i 17; i)
{puke3[i] puke2[ints1[i]];puke4[i] puke2[ints1[i 17]];puke5[i] puke2[ints1[i 24]]; // 这里索引计算有问题
}
for(int i 0; i 3; i)
{puke6[i] puke2[ints1[i51]];
}这部分代码实现了洗牌和发牌使用随机索引数组ints1重新排列扑克牌数组将牌分发给三个玩家各 17 张和底牌3 张5. 排序算法
Array.Sort(puke3, (a, b)
{int numA a.number joker ? 100 : int.Parse(a.number);int numB b.number joker ? 100 : int.Parse(b.number);int result numA.CompareTo(numB);if (result 0)return a.color.CompareTo(b.color);return result;
});
// 对puke4和puke5有相同的排序代码...这部分代码对每个玩家的手牌进行排序将牌面值转换为整数进行比较Joker 设为 100牌面值相同则比较花色6. 辅助方法生成随机不重复数组
static int[] RandomUNorepeatArray(int[] ints )
{int min 0;int max 53;int count 54;
Listint pool new Listint();for (int i min; i max; i)pool.Add(i);
Random rand new Random();// 洗牌算法for (int i pool.Count - 1; i 0; i--){int j rand.Next(0, i 1);int temp pool[i];pool[i] pool[j];pool[j] temp;}
return pool.ToArray();
}这个方法使用 Fisher-Yates 洗牌算法生成 0-53 的随机排列数组。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 斗地主
{internal class Program{static void Main(string[] args){int[] ints1 new int[54];ints1 RandomUNorepeatArray(ints1);
// //Console.WriteLine(string.Join( , ints1));
// string[] strings new string[]//{// 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,// j1, j2//};
// string[] strings2 new string[60];
// Random random new Random();
// for (int i 0; i ints1.Length; i)// {// // int ints3 random.Next(ints1.Length);// strings2[i] strings[ints1[i]];// }// int num 0;
// foreach (string s in strings2)// {// Console.Write(${s,-4});// num;// if (num % 17 0) Console.WriteLine();// }
Puke[] puke new Puke[54];int num 1;char[] str new char[4] {黑, 红, 梅, 方 };int num2 3;for (int i 0; i 52; i){puke[i] new Puke();if (num 13){num 1;num2--;}puke[i].number num.ToString();num;puke[i].color str[num2];}puke[52] new Puke { number joker, color 黑 };puke[53] new Puke { number joker, color 红 };
Puke[] puke2 new Puke[54];for (int i 0; i 54; i){puke2[i] puke[ints1[i]];}
int count 0;foreach (var item in puke2){Console.Write(${item,-4});count;if (count % 17 0) Console.WriteLine();
//count;//if (count%13 0) Console.WriteLine();}
Puke[] puke3 new Puke[17];Puke[] puke4 new Puke[17];Puke[] puke5 new Puke[17];Puke[] puke6 new Puke[3];for (int i 0; i 17; i){puke3[i] puke2[ints1[i]];puke4[i] puke2[ints1[i 17]];puke5[i] puke2[ints1[i 24]];}for(int i 0; i 3; i){puke6[i] puke2[ints1[i51]];}
Array.Sort(puke3, (a, b) {int numA a.number joker ? 100 : int.Parse(a.number);int numB b.number joker ? 100 : int.Parse(b.number);int result numA.CompareTo(numB);if (result 0)return a.color.CompareTo(b.color);return result;});
Array.Sort(puke4, (a, b) {int numA a.number joker ? 100 : int.Parse(a.number);int numB b.number joker ? 100 : int.Parse(b.number);int result numA.CompareTo(numB);if (result 0)return a.color.CompareTo(b.color);return result;});
Array.Sort(puke5, (a, b) {int numA a.number joker ? 100 : int.Parse(a.number);int numB b.number joker ? 100 : int.Parse(b.number);int result numA.CompareTo(numB);if (result 0)return a.color.CompareTo(b.color);return result;});
Console.WriteLine();Console.Write();Console.WriteLine();
int c 0;foreach (var item in puke3){Console.Write(${item,-6});//count;//if (count%13 0) Console.WriteLine();}Console.WriteLine();foreach (var item in puke4){Console.Write(${item,-6});//count;//if (count%13 0) Console.WriteLine();}Console.WriteLine();foreach (var item in puke5){Console.Write(${item,-6});//count;//if (count%13 0) Console.WriteLine();}Console.WriteLine();foreach (var item in puke6){Console.Write(${item,-6});//count;//if (count%13 0) Console.WriteLine();}
//Array.Sort(puke2, (a, b) //{// int result a.number.CompareTo(b.number);// if (result 0)// {// return b.color.CompareTo(a.color);// }// return result;//});
}
//生成一定范围内随机不成重复数字的数组static int[] RandomUNorepeatArray(int[] ints ){int min 0;int max 53; // 生成1~20之间的不重复数字int count 54; // 需要的数量
Listint pool new Listint();for (int i min; i max; i)pool.Add(i);
//Fisher-Yates 洗牌算法Random rand new Random();// 洗牌for (int i pool.Count - 1; i 0; i--){int j rand.Next(0, i 1);int temp pool[i];pool[i] pool[j];pool[j] temp;}
// 取前count个//for (int i 0; i count; i)//{// Console.Write(pool[i] );//}//Console.WriteLine();
return pool.ToArray();}}
class Puke{// 牌的数字 A-K 用1-13表示public string number;// 牌的花色 黑红梅方 4321public char color;public override string ToString(){return $[{number},{color}];}
}
}
三、代码说明泛型方法ShuffleT 支持任意类型的数组和列表通用性强。随机索引生成random.Next(i 1) 确保生成的索引 j 在 [0, i] 范围内避免越界。元素交换使用 C# 7.0 引入的元组交换语法 (a, b) (b, a)简洁高效也可使用临时变量交换。Random 实例在方法内创建单个 Random 实例避免短时间内多次创建导致的随机序列重复问题。四、算法优势公平性每个元素在每个位置的概率严格相等无偏差。高效性仅需一次遍历和 n-1 次交换时间复杂度 O (n)空间复杂度 O (1)原地洗牌无需额外空间。适用性适用于任何可索引的序列数组、列表等广泛应用于卡牌游戏、随机排序、数据打乱等场景。五、注意事项Random 的线程安全若在多线程环境中使用需确保 Random 实例的线程安全可使用 Random.Shared 或加锁。重复执行的随机性若需每次运行生成不同的打乱结果不要手动指定 Random 的种子默认使用系统时间作为种子。示例输出
[8,梅][4,方][1,梅][3,梅][12,方][4,红][9,黑][2,方][13,梅][9,方][7,黑][joker,红][11,方][joker黑][13,黑][9,红][6,红]
[10,红][12,黑][9,梅][11,黑][3,红][10,方][11,梅][12,梅][10,黑][6,梅][7,梅][2,红][5,梅][12,红][4,黑][3,黑][1,红]
[10,梅][8,红][6,方][5,红][11,红][1,黑][3,方][6,黑][5,黑][1,方][2,梅][13,红][8,方][4,梅][8,黑][5,方][2,黑]
[7,方][7,红][13,方][3,梅] [4,方] [4,梅] [4,黑] [5,梅] [7,方] [7,红] [7,黑] [9,红] [10,梅][10,黑][11,黑][13,方][13,梅][13,红][joker,红][joker,黑]
[2,红] [2,黑] [3,红] [5,方] [5,红] [5,黑] [6,梅] [6,黑] [7,梅] [8,红] [8,黑] [9,方] [9,梅] [10,红][11,梅][12,梅][12,黑]
[1,梅] [1,红] [1,黑] [4,红] [5,红] [5,黑] [6,方] [6,梅] [6,黑] [7,梅] [8,黑] [9,梅] [10,方][10,红][12,梅][12,红][12,黑]
[9,黑] [3,黑] [11,方]