算法要求:
- 生成一副扑克牌,并打乱顺序
- 对乱序的扑克牌文件进行排序
为了方便阅读,我们直接将扑克牌生成为人工可以识别的字符串,数字从2,3,4,5,6,7,8,9,10,J,Q,K,A,花式为♠,♣,♥,♦。代码如下:
private static void GenerateRandPoker() { List list = new List(); for (int i = 2; i <= 14; i++) { if (i <= 10) { list.Add("♠" + i); list.Add("♣" + i); list.Add("♥" + i); list.Add("♦" + i); } else if (i == 11) { list.Add("♠J"); list.Add("♣J"); list.Add("♥J"); list.Add("♦J"); } else if (i == 12) { list.Add("♠Q"); list.Add("♣Q"); list.Add("♥Q"); list.Add("♦Q"); } else if (i == 13) { list.Add("♠K"); list.Add("♣K"); list.Add("♥K"); list.Add("♦K"); } else if (i == 14) { list.Add("♠A"); list.Add("♣A"); list.Add("♥A"); list.Add("♦A"); } } Random r = new Random(); for (int i = 0; i < 100; i++) { int n = r.Next(0, 51); int m = r.Next(0, 51); if (n != m) { string tmp = list[m]; list[m] = list[n]; list[n] = tmp; } } using (StreamWriter file = new StreamWriter("Poker.txt", false, Encoding.UTF8)) { foreach (string item in list) { file.WriteLine(item); } file.Close(); } }
上述算法中,首先生成一个顺序的扑克牌,再对扑克牌进行一个打乱——100次,随机两个扑克位置进行交换。注意:生成一副乱序的扑克牌算法有很多种,笔者可以想到的另外两种办法:直接生成一个乱序的序列,然后将此序列写入文件,请参照附注代码A;另一个方法是:生成一个顺序的序列,然后用随机算法写入文件,个人觉得这种算法最快,请参照附注代码B。
最后将生成好的扑克牌保存在文件Poker.txt中。然后针对这个文件进行排序:
private static void PokerSorter() { List list = new List(); using (StreamReader file = new StreamReader("Poker.txt", Encoding.UTF8)) { string line; while ((line = file.ReadLine()) != null) { if (line.Trim().Length > 0) { list.Add(line.Trim()); } } file.Close(); } list.Sort(PokerComparer); using (StreamWriter file = new StreamWriter("SortedPoker.txt", false, Encoding.UTF8)) { foreach (string item in list) { file.WriteLine(item); } file.Close(); } } private static int PokerComparer(string A, string B) { int a = GetPokerNumber(A); int b = GetPokerNumber(B); return a - b; } private static int GetPokerNumber(string poker) { string numberText = poker.Substring(1); int number = 0; switch (numberText) { case "A": number = 14; break; case "K": number = 13; break; case "Q": number = 12; break; case "J": number = 11; break; default: number = Convert.ToInt32(numberText); break; } number = (15 - number) * 100; char c = poker[0]; switch (c) { case '♠': number += 1; break; case '♣': number += 2; break; case '♥': number += 3; break; case '♦': number += 4; break; } return number; }
以上的方法主要包括3个主要过程:
- 将扑克牌全部读取到列表list中。
- 对list进行排序。
- 将排序后的list写入新文件中。
在以上代码中包含一个神奇数字“100”,这个100的用途在于区分数字和花式的权重,玩过扑克的同学都知道,扑克牌的比较首先应该比较数字,在数字相同的情况下,再进行花式比较。这个地方的100实际上可以是任何大于等于4的数字,这个例子中只是为了Debug方便,所以将数字设置100,方便Debug而已,并无他意。另外一个神奇数字“15”,这个数字的用途是因为我们排序是从大到小进行排序,数字越大的顺序越前,所以在这个地方用15进去实际的数字再进行进行。
运行结果:Poker.txt文件
♣8 ♠Q ♠J ♥7 ♣9 ♣4 ♣2 ♠8 ♦4 ♥4 ♠7 ♦9 ♥Q ♣5 ♠9 ♣10 ♠5 ♠4 ♥J ♦6 ♥5 ♦10 ♣Q ♥9 ♠3 ♥6 ♠6 ♣J ♦Q ♠K ♣6 ♦7 ♣A ♠A ♠10 ♣K ♦J ♦5 ♣3 ♦8 ♠2 ♣7 ♥8 ♥A ♥3 ♥10 ♦3 ♦2 ♦K ♥2 ♥K ♦A
SortedPoker.txt文件
♠A ♣A ♥A ♦A ♠K ♣K ♥K ♦K ♠Q ♣Q ♥Q ♦Q ♠J ♣J ♥J ♦J ♠10 ♣10 ♥10 ♦10 ♠9 ♣9 ♥9 ♦9 ♠8 ♣8 ♥8 ♦8 ♠7 ♣7 ♥7 ♦7 ♠6 ♣6 ♥6 ♦6 ♠5 ♣5 ♥5 ♦5 ♠4 ♣4 ♥4 ♦4 ♠3 ♣3 ♥3 ♦3 ♠2 ♣2 ♥2 ♦2
附注代码A:在写这快代码的时候遇到一个小问题值得注意,Next(min, max)中的min是可以包含的,但是max是不会包含的;例如Next(0, 15),那么最小返回0,最大返回15-1=14。
private static void GenerateRandPoker2() { List list = new List(); object[] numberArray = { 2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K", "A" }; object[] suitArray = { "♠", "♣", "♥", "♦" }; Random r = new Random(); while (list.Count < 52) { int n = r.Next(0, numberArray.Length); int m = r.Next(0, suitArray.Length ); string poker = string.Format("{0}{1}", suitArray[m], numberArray[n]); if (!list.Contains(poker)) { list.Add(poker); } } using (StreamWriter file = new StreamWriter("Poker.txt", false, Encoding.UTF8)) { foreach (var item in list) { file.WriteLine(item); } file.Close(); } }
附注代码B:(推荐最佳算法)
private static void GenerateRandPoker3() { object[] numberArray = { 2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K", "A" }; object[] suitArray = { "♠", "♣", "♥", "♦" }; List list = new List(); for (int i = 0; i < numberArray.Length; i++) { for (int j = 0; j < suitArray.Length; j++) { list.Add(string.Format("{0}{1}", suitArray[j], numberArray[i])); } } using (StreamWriter file = new StreamWriter("Poker.txt", false, Encoding.UTF8)) { Random r = new Random(); while (list.Count > 0) { int i = r.Next(0, list.Count - 1); file.WriteLine(list[i]); list.RemoveAt(i); } file.Close(); } }