模拟一副扑克牌,根据点数、花色等分组、筛选为例子,详细讲解linq中筛选之后的集合到底是引用类型还是值类型,如何才能正确使用筛选后的集合和其中的元素。压缩的是一个项目文件,运行时,需要自己新建解决方案,我用的是VS2017。如果版本低于这个的话,只要把其中的program.cs文件中内容复制到自己新建的解决方案中,也可以运行。
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Poker{ class Program { static void Main(string[] args) { test07(); Console.ReadLine(); } /// <summary> /// 根据点数分组,每个组按照点数大小排序,每个组里面的内容,再根据color排序 /// </summary> static void test01() { var cards = Card.GetPack(); Card.Shuffle(cards); //cards = Card.RandomN(cards,40); var a1 = from n in cards group n by n.points into d1 orderby d1.Key descending select new { key = d1.Key, value = d1.OrderByDescending(p => p.color), number=d1.Count()//小组里面有几张牌 }; foreach (var b1 in a1) { foreach (var d1 in b1.value) { Console.Write(d1.name); } Console.WriteLine(); } } static void test02() { var card1 = Card.GetPack_BlackJack().First(p => p.name.Equals("红桃A")); var card2 = Card.GetPack_BlackJack().First(p => p.name.Equals("红桃K")); var card3 = Card.GetPack_BlackJack().First(p => p.name.Equals("黑桃3")); var playerCards = new List<Card>(); playerCards.Add(card1); playerCards.Add(card2); playerCards.Add(card3); var sss= Card.GetPack_BlackJack().Except(playerCards, new CardBlackJackComparer()); sss = sss.OrderBy(p => p.color).ThenBy(p => p.points); foreach (var b1 in sss) { Console.Write(b1.name " "); } } static void test03() { //var a1 = from n in dsds1 // group n by new { name1 = n.bankerCards[0].name, name2 = n.bankerCards[1].name, name3 = n.bankerCards[2].name } into d1 // select new // { // key = d1.Key, // Count = d1.Count() // }; } /// <summary> /// 测试,list是一个引用对象,引用传递,是可以改变整个list的属性的 /// </summary> static void test04() { var t1 = Card.GetPack_BlackJack(); test05(t1); var s = t1; } static void test05(List<Card> c1) { //c1.ForEach(p => p.points = p.points 100); c1.Where(p => p.points == 5).ToList().ForEach(p => p.points = p.points 1000); c1.AddRange(Card.GetPack_BlackJack()); } /// <summary> /// 测试 排序 /// 1.orderby总结,就是linq里面的一个方法,每次调用,都以list为参数,运行一次, /// 会产生一个结果,就是排序之后的list,这个过程对原来的list也就是参数没有影响, /// 如果你不获取这个结果,那么结果就没有了。 /// /// 2.修改自身与修改副本,比如传一个引用到一个函数里,普通的情况,是可以修改这个引用的里面的情况, /// 但是改不了引用本身,要是改本身,得在外面改,而如果是ref的情况下,是可以的 /// </summary> static void test06() { var t1 = Card.GetPack_BlackJack(); List<Card> s = null; //test061(t1); //test065(t1); //s = t1; //test064(ref t1); //s = t1; //test063(ref t1); //s = t1; //test062(t1); //s = t1; //t1=test062(t1); //s = t1; //test066(ref t1); //s = t1; test068(t1); s = t1; test067(t1); s = t1; } /// <summary> /// 假排序,因为传递了一个形参,改变形参,没用 /// </summary> /// <param name="c1"></param> static void test061(List<Card> t1) { t1 = t1.OrderBy(p => p.color).ThenBy(p => p.points).ToList(); } /// <summary> /// 假排序,同样是形参,改变形参没用,出了这个函数,还是没有排序的 /// </summary> /// <param name="t1"></param> static void test065(List<Card> t1) { var ss=t1.OrderBy(p => p.color).ThenBy(p => p.points).ToList().First(); var dd = ss; } /// <summary> /// 真排序,关键在于取得了返回值, /// </summary> /// <param name="c1"></param> static List<Card> test062(List<Card> t1) { t1 = t1.OrderBy(p => p.color).ThenBy(p => p.points).ToList(); return t1; } /// <summary> /// 真排序,首先传递的 不是形参,是真的,可以改变这个list的指向的, /// 而在里面,真的把这个指向了排号之后的东西 /// </summary> /// <param name="t1"></param> static void test063(ref List<Card> t1) { t1 = t1.OrderBy(p => p.color).ThenBy(p => p.points).ToList(); } /// <summary> /// 假排序,虽然是真参数,但是结果没有获取 /// </summary> /// <param name="t1"></param> static void test064(ref List<Card> t1) { t1.OrderBy(p => p.color).ThenBy(p => p.points).ToList(); } /// <summary> /// 真改了,从此以后 这个list就是空了 /// </summary> /// <param name="t1"></param> static void test066(ref List<Card> t1) { t1 = null; } /// <summary> /// 真改了,从此以后 这个list本身不是空,但是每一个项是空的了 /// </summary> /// <param name="t1"></param> static void test067(List<Card> t1) { for (int i = 0; i < t1.Count;i ) { t1[i] = null; } } /// <summary> /// 没有改 这个p是一个形参,改形参没用,只是形参指向空 /// 不像上一个 t1[i] 不是形参,是实参,而这个P 是形参 /// </summary> /// <param name="t1"></param> static void test068(List<Card> t1) { t1.ForEach(p => p = null); } /// <summary> /// 这个LIST是上面所说的了,但是里面具体的东西,比如用where筛选出来的一个子list /// 那个这个LIST和原始的LIST中有相同的对象,这个是值引用还是复制的, /// 这两个list中的对象,其实是共有的,比如你该了where 里面的每个对象的值,那个总的对应的对象,也都改变 /// </summary> /// <param name="t1"></param> static void test07() { var cards = Card.GetPack(); var t1 =cards.Where(p => p.points == 2).ToList(); foreach (var d1 in t1) { d1.pointsName = "已经修改了"; } foreach (var d1 in cards) { Console.Write(d1.pointsName); } Console.WriteLine(); } } /// <summary> /// 扑克类 /// color colorName points pointsName都是初始化的时候设置的, /// ///具体设置规则,可以选择 /// </summary> public class Card { /// <summary> /// 一副牌的唯一标记,数量 /// </summary> public int number; /// <summary> /// 3, 2, 1, 0 /// 黑桃>红桃>梅花>方块 /// </summary> public int color; /// <summary> /// 花色,红桃、黑桃 /// </summary> public string colorName; /// <summary> /// 2为2,3为3,J为11,Q为12,K为13,A为14 /// </summary> public int points; /// <summary> /// 就是JKQA2\3 /// </summary> public string pointsName; /// <summary> /// 返回比如说红桃3 /// </summary> public string name { get { return this.colorName this.pointsName; } } /// <summary> /// 构造方法 /// 默认构造方法, /// 0 1 2 3 /// 方块、梅花、红桃、黑桃 /// 2 3 K A /// 2 3 13 14 /// </summary> /// <param name="number"></param> public Card(int i) { this.number = i; if (i % 4 == 0) { this.color = 0; this.colorName = "方块"; } else if (i % 4 == 1) { this.color = 1; this.colorName = "梅花"; } else if (i % 4 == 2) { this.color = 2; this.colorName = "红桃"; } else { this.color = 3; this.colorName = "黑桃"; } if (i % 13 == 0) { this.points = 3; this.pointsName = "3"; } else if (i % 13 == 1) { this.points = 4; this.pointsName = "4"; } else if (i % 13 == 2) { this.points = 5; this.pointsName = "5"; } else if (i % 13 == 3) { this.points = 6; this.pointsName = "6"; } else if (i % 13 == 4) { this.points = 7; this.pointsName = "7"; } else if (i % 13 == 5) { this.points = 8; this.pointsName = "8"; } else if (i % 13 == 6) { this.points = 9; this.pointsName = "9"; } else if (i % 13 == 7) { this.points = 10; this.pointsName = "10"; } else if (i % 13 == 8) { this.points = 11; this.pointsName = "J"; } else if (i % 13 == 9) { this.points = 12; this.pointsName = "Q"; } else if (i % 13 == 10) { this.points = 13; this.pointsName = "K"; } else if (i % 13 == 11) { this.points = 14; this.pointsName = "A"; } else if (i % 13 == 12) { this.points = 2; this.pointsName = "2"; } } /// <summary> /// 比如梅花10,方块7,红桃A,黑桃K /// 红心 黑心 草花 钻石 /// </summary> /// <param name="name"></param> public Card(string name) { switch (name.Substring(0, 2)) { case "红桃": this.color = 0; this.colorName = "红桃"; break; case "红心": this.color = 0; this.colorName = "红桃"; break; case "黑桃": this.color = 1; this.colorName = "黑桃"; break; case "黑心": this.color = 1; this.colorName = "黑桃"; break; case "方块": this.color = 2; this.colorName = "方块"; break; case "钻石": this.color = 2; this.colorName = "方块"; break; case "方角": this.color = 2; this.colorName = "方块"; break; case "方片": this.color = 2; this.colorName = "方块"; break; case "梅花": this.color = 3; this.colorName = "梅花"; break; case "草花": this.color = 3; this.colorName = "梅花"; break; case "花子": this.color = 3; this.colorName = "梅花"; break; } if (name.Length == 4) { this.points = 10; this.pointsName = "10"; } else { switch (name.Substring(2, 1)) { case "2": this.points = 2; this.pointsName = "2"; break; case "3": this.points = 3; this.pointsName = "3"; break; case "4": this.points = 4; this.pointsName = "4"; break; case "5": this.points = 5; this.pointsName = "5"; break; case "6": this.points = 6; this.pointsName = "6"; break; case "7": this.points = 7; this.pointsName = "7"; break; case "8": this.points = 8; this.pointsName = "8"; break; case "9": this.points = 9; this.pointsName = "9"; break; case "J": this.points = 11; this.pointsName = "J"; break; case "Q": this.points = 12; this.pointsName = "Q"; break; case "K": this.points = 13; this.pointsName = "K"; break; case "A": this.points = 1; this.pointsName = "A"; break; } } } /// <summary> /// 没有大小王的,52张 /// points和color如下: /// 0 1 2 3 /// 方块 梅花 红桃 黑桃 /// 2 3 ……10 J Q K A /// 2 3 ……10 11 12 13 14 /// </summary> /// <returns></returns> public static List<Card> GetPack() { var resut = new List<Card>(); for (int i = 1; i <= 52; i ) { Card pokerCard = new Card(i); resut.Add(pokerCard); } return resut; } /// <summary> /// 取得一副21点扑克, /// JQK的points为10,A为11 /// </summary> /// <returns></returns> public static List<Card> GetPack_BlackJack() { var resut = Card.GetPack(); //JQK resut.Where(p => p.points == 11 || p.points == 12 || p.points == 13).ToList().ForEach(p => p.points = 10); //A resut.Where(p => p.points == 14).ToList().ForEach(p => p.points = 11); return resut; } /// <summary> /// 洗牌 /// </summary> /// <param name="pokerCards"></param> /// <returns></returns> public static void Shuffle(List<Card> pokerCards) { Random random = new Random(); int times = random.Next(0, pokerCards.Count * 3);//交换次数 Card templs = null; for (int i = 0; i < times; i ) { int t1 = random.Next(0, pokerCards.Count); int t2 = random.Next(0, pokerCards.Count); var c1 = pokerCards.ElementAt(t1); var c2 = pokerCards.ElementAt(t2); pokerCards[t1] = c2; pokerCards[t2] = c1; } } /// <summary> /// 随机抽取一张牌 /// </summary> /// <param name="pokerCards"></param> /// <returns></returns> public static Card RandomOne(List<Card> pokerCards) { Random ran = new Random(); int ranKey = ran.Next(0, pokerCards.Count); Card a1 = pokerCards.ElementAt(ranKey); pokerCards.RemoveAt(ranKey); return a1; } /// <summary> /// 随机抽取n张牌 /// </summary> /// <param name="pokerCards"></param> /// <returns></returns> public static List<Card> RandomN(List<Card> pokerCards, int n) { List<Card> results = new List<Card>(); while (n > 0) { results.Add(Card.RandomOne(pokerCards)); n--; } return results; } } /// <summary> /// BlackJack比较器 /// </summary> public class CardBlackJackComparer : IEqualityComparer<Card> { public bool Equals(Card x, Card y) { if (Object.ReferenceEquals(x, y)) return true; if (x.name.Equals(y.name)) { return true; } else { return false; } } public int GetHashCode(Card obj) { int CardName =obj.name.GetHashCode(); return CardName; } } /// <summary> /// 结构体,百家乐扑克 /// </summary> public struct Card_B { /// <summary> /// 一副牌的唯一标记,数量 /// </summary> public int number; /// <summary> /// 3, 2, 1, 0 /// 黑桃>红桃>梅花>方块 /// </summary> public int color; /// <summary> /// 花色,红桃、黑桃 /// </summary> public string colorName; /// <summary> /// 2为2,3为3,J为11,Q为12,K为13,A为14 /// </summary> public int points; /// <summary> /// 就是JKQA2\3 /// </summary> public string pointsName; /// <summary> /// 返回比如说红桃3 /// </summary> public string name { get { return this.colorName this.pointsName; } } /// <summary> /// 构造方法 /// 百家乐扑克,点数为 /// 0 1 2 3 /// 方块、梅花、红桃、黑桃 /// /// 2 3 10 K A /// 2 3 0 0 1 /// </summary> /// <param name="number"></param> public Card_B(int i) { this.number = i; if (i % 4 == 0) { this.color = 0; this.colorName = "方块"; } else if (i % 4 == 1) { this.color = 1; this.colorName = "梅花"; } else if (i % 4 == 2) { this.color = 2; this.colorName = "红桃"; } else { this.color = 3; this.colorName = "黑桃"; } if (i % 13 == 0) { this.points = 3; this.pointsName = "3"; } else if (i % 13 == 1) { this.points = 4; this.pointsName = "4"; } else if (i % 13 == 2) { this.points = 5; this.pointsName = "5"; } else if (i % 13 == 3) { this.points = 6; this.pointsName = "6"; } else if (i % 13 == 4) { this.points = 7; this.pointsName = "7"; } else if (i % 13 == 5) { this.points = 8; this.pointsName = "8"; } else if (i % 13 == 6) { this.points = 9; this.pointsName = "9"; } else if (i % 13 == 7) { this.points = 0; this.pointsName = "10"; } else if (i % 13 == 8) { this.points = 0; this.pointsName = "J"; } else if (i % 13 == 9) { this.points = 0; this.pointsName = "Q"; } else if (i % 13 == 10) { this.points = 0; this.pointsName = "K"; } else if (i % 13 == 11) { this.points = 1; this.pointsName = "A"; } else if (i % 13 == 12) { this.points = 2; this.pointsName = "2"; } else {//结构体必须被赋值 this.points = 0; this.pointsName = "0"; } } /// <summary> /// 没有大小王的,52张 /// points和color如下: /// 0 1 2 3 /// 方块 梅花 红桃 黑桃 /// 2 3 ……10 J Q K A /// 2 3 ……0 0 0 0 1 /// </summary> /// <returns></returns> public static List<Card_B> GetPack_B() { var resut = new List<Card_B>(); for (int i = 1; i <= 52; i ) { Card_B pokerCard = new Card_B(i); resut.Add(pokerCard); } return resut; } } /// <summary> /// 百家乐扑克比较器 /// </summary> public class BaccaratComparer : IEqualityComparer<Card_B> { public bool Equals(Card_B x, Card_B y) { if (Object.ReferenceEquals(x, y)) return true; if (x.number==y.number) { return true; } else { return false; } } public int GetHashCode(Card_B obj) { int CardName = obj.number.GetHashCode(); return CardName; } } /// <summary> /// 结构体,21点扑克 /// </summary> public struct Card_J { /// <summary> /// 一副牌的唯一标记,数量 /// </summary> public int number; /// <summary> /// 3, 2, 1, 0 /// 黑桃>红桃>梅花>方块 /// </summary> public int color; /// <summary> /// 花色,红桃、黑桃 /// </summary> public string colorName; /// <summary> /// 2为2,3为3,J为10,Q为10,K为10,A为11 /// </summary> public int points; /// <summary> /// 就是JKQA2\3 /// </summary> public string pointsName; /// <summary> /// 返回比如说红桃3 /// </summary> public string name { get { return this.colorName this.pointsName; } } /// <summary> /// 构造方法 /// 百家乐扑克,点数为 /// 0 1 2 3 /// 方块、梅花、红桃、黑桃 /// /// 2 3 10 K A /// 2 3 0 0 1 /// </summary> /// <param name="number"></param> public Card_J(int i) { this.number = i; if (i % 4 == 0) { this.color = 0; this.colorName = "方块"; } else if (i % 4 == 1) { this.color = 1; this.colorName = "梅花"; } else if (i % 4 == 2) { this.color = 2; this.colorName = "红桃"; } else { this.color = 3; this.colorName = "黑桃"; } if (i % 13 == 0) { this.points = 3; this.pointsName = "3"; } else if (i % 13 == 1) { this.points = 4; this.pointsName = "4"; } else if (i % 13 == 2) { this.points = 5; this.pointsName = "5"; } else if (i % 13 == 3) { this.points = 6; this.pointsName = "6"; } else if (i % 13 == 4) { this.points = 7; this.pointsName = "7"; } else if (i % 13 == 5) { this.points = 8; this.pointsName = "8"; } else if (i % 13 == 6) { this.points = 9; this.pointsName = "9"; } else if (i % 13 == 7) { this.points = 10; this.pointsName = "10"; } else if (i % 13 == 8) { this.points = 10; this.pointsName = "J"; } else if (i % 13 == 9) { this.points = 10; this.pointsName = "Q"; } else if (i % 13 == 10) { this.points = 10; this.pointsName = "K"; } else if (i % 13 == 11) { this.points = 11; this.pointsName = "A"; } else if (i % 13 == 12) { this.points = 2; this.pointsName = "2"; } else {//结构体必须被赋值 this.points = 0; this.pointsName = "0"; } } /// <summary> /// 没有大小王的,52张 /// points和color如下: /// 0 1 2 3 /// 方块 梅花 红桃 黑桃 /// 2 3 ……10 J Q K A /// 2 3 ……0 0 0 0 1 /// </summary> /// <returns></returns> public static List<Card_J> GetPack_J() { var resut = new List<Card_J>(); for (int i = 1; i <= 52; i ) { Card_J pokerCard = new Card_J(i); resut.Add(pokerCard); } return resut; } } /// <summary> /// 21点扑克比较器 /// </summary> public class BlackJackComparer : IEqualityComparer<Card_J> { public bool Equals(Card_J x, Card_J y) { if (Object.ReferenceEquals(x, y)) return true; if (x.number == y.number) { return true; } else { return false; } } public int GetHashCode(Card_J obj) { int CardName = obj.number.GetHashCode(); return CardName; } } /// <summary> /// 21点扑克,只有点数和name两个属性 /// </summary> public class Card21 { /// <summary> /// 2为2,3为3,J为10,Q为10,K为10,A为11 /// </summary> public int points; /// <summary> /// 就是JKQA2\3 /// </summary> public string name; /// <summary> /// 构造方法 /// 默认构造方法, /// 0 1 2 3 /// 方块、梅花、红桃、黑桃 /// 2 3 K A /// 2 3 13 14 /// </summary> /// <param name="number"></param> public Card21(string name) { switch (name) { case "2": this.points = 2; this.name = "2"; break; case "3": this.points = 3; this.name = "3"; break; case "4": this.points = 4; this.name = "4"; break; case "5": this.points = 5; this.name = "5"; break; case "6": this.points = 6; this.name = "6"; break; case "7": this.points = 7; this.name = "7"; break; case "8": this.points = 8; this.name = "8"; break; case "9": this.points = 9; this.name = "9"; break; case "10": this.points = 10; this.name = "10"; break; case "J": this.points = 10; this.name = "J"; break; case "Q": this.points = 10; this.name = "Q"; break; case "K": this.points = 10; this.name = "K"; break; case "A": this.points = 11; this.name = "A"; break; } } } /// <summary> ///百家乐扑克,只有点数和name两个属性 /// </summary> public class Card0 { /// <summary> /// 2为2,3为3,J为10,Q为10,K为10,A为11 /// </summary> public int points; /// <summary> /// 就是JKQA2\3 /// </summary> public string name; /// <summary> /// 构造方法 /// 默认构造方法, /// 0 1 2 3 /// 方块、梅花、红桃、黑桃 /// 2 3 K A /// 2 3 13 14 /// </summary> /// <param name="number"></param> public Card0(string name) { switch (name) { case "2": this.points = 2; this.name = "2"; break; case "3": this.points = 3; this.name = "3"; break; case "4": this.points = 4; this.name = "4"; break; case "5": this.points = 5; this.name = "5"; break; case "6": this.points = 6; this.name = "6"; break; case "7": this.points = 7; this.name = "7"; break; case "8": this.points = 8; this.name = "8"; break; case "9": this.points = 9; this.name = "9"; break; case "10": this.points = 10; this.name = "10"; break; case "J": this.points = 10; this.name = "J"; break; case "Q": this.points = 10; this.name = "Q"; break; case "K": this.points = 10; this.name = "K"; break; case "A": this.points = 1; this.name = "A"; break; } } }}
评论