[音乐]
下面我们再来看一个 类的例子。
那么在这个例子里面我们要构建一个扑克牌的洗牌跟发牌的类, 然后完成这样的一个洗牌跟发牌的iii
我们知道这个扑克牌一共有 52 张牌,那么除去这个大王跟小王,
那么每个花色,每个花色,一共有四个花色, 每个花色是13张牌,分别是从这个J
Q K 一直到 two, three 一直到这个 A。
那么一共这样的一共 13 张牌,那么在这 13 张牌里面,
那么我们可以用这样的一共 4 个 13 张牌,是 52 张牌,我们将用一个
呃 我们将用这样的一个
52,这样用一个数组来模拟这样的一个扑克牌, 那么把这样的一个扑克牌放到这样的一个数组里面,那么洗牌
呢,我们是这样洗的,我们从一个,做一个循环,从 i 循环,一直循环到 从 0 一直循环到 51。
那么在每一步循环时候,是我们随机产生一个随机数 j,
那么产生完随机数 i 的时候,我们把 i 位置上的扑克牌跟
j 位置上的扑克牌 对调一下,就是交换一下,那么经过 52
次交换我们就完成了 随机的交换那么就完成了这样的有一个洗牌的过程。
随后我们会均匀地把这样的一个牌按照从
先到后的顺序发给这样的一个,4 个这样的一个 牌手。
那么将洗好的这样的 52 张牌就从这样的一个 0 到 51 依次地发给甲乙丙丁四个人。
那么也就是说如果第一张牌发给甲, 等第二张牌就会发给乙,然后就是稍后发给丙,等等依次这样把所有的牌都发完。
那么下面我们来看一下具体的这样的一个代码该怎么样做。
[空白音频]
[空白音频] 那么在这样的一个例子里面,我们首先
干这样的一些几件事情。
第一个事情是我们创建一个结构体, struct
那么这个结构体的名字我们把它称之为 称之为这样的一个
Card 称之为这样的一个
node, c Card,
node 的意思,就是我们对每一张牌的描述。
因为对于每一张来讲,我们要描述它这样的一个两个信息,
一个是它的这样的一个它的花色,一个是它的这样的一个大小,或者它的面值。
它到底是花色一共有四种,分别是黑桃、 红桃、 梅花或者方块。
那么对于面值来讲,我们说它应该是从1到 13
的,所以说一个简单的信息没有办法描述这样的一张牌,一张牌里面至少包含有两个信息。
我们把这两个信息组合为一个 struct,那么来描述这样的。
其中第一个信息是 对于第一个信息而言,对于第一个信息而言,那么它里面应该是这样的一个
char suit,那么
首先我们用一个,用一个字符来表示它的这样的一个花色。
那么这个花色分别是 四个这样的方式之一。
其次我们再用一个 string 字符串来表示它的这样的一个面值,
来表示它的这样的一个面值。
那么为什么不能用一个字符来表示面值呢?它可以是 A,然后或者是
1,2,3,4,5,6,7,8,9 或者是 Queen,King 等等。
那这中间唯一的问题就是用的字符串的问题,就是因为有这个面值 10, 10 里面是 1, 0,含了两个字符。
所以说为了 能够使它表示 10 的话,我们使用了这样的一个 string,而是没有用这个 char 这样的一个变量。
那么对于 struct 来讲,如果前面没有任何 这样的一个访问变量的话,它默认应该是 public 的访问变量。
当然我们也可以这样的一个明示它是这样的一个 public
的 可以由所有大家都能够直接访问的这样的两个变量,
那么完了之后我们就可以创建我们这样的一个 class,
[空白音频] class,然后我们通过这样的一个
class 来创建我们 class,card
Card,我们来创建我们这样的一个扑克牌的这样的一个类。
在扑克牌这样的一个类里面,
在创建这个扑克牌的类之前,我们首先在 根据我们,在类跟这个 struct
相同的时候,我们再定义一个这样的一个 枚举型的这样的一个常量。
我们需要定义几个常量,第一个常量是什么呢?第一个常量是扑克牌的张数,一共有 52 张。
第二常量是这样的,它的花色一共是 4 个花色,以及它的面值一共有 13 种面值,这是几个我们要用到的常数。
这样的常数当然我们可以分别通过 constant 这样定义这样的三个这样的常数出来。
我们也可以用到我们讲过的这个 enum 这样的一个枚举把它们枚举出来。
比如讲我们枚举这样的一个 Card CardNum
我们枚举出来这样的几个 我们枚举这样的几个常数也是可以的。
我们顺便也就是复习一下我们枚举的用法,我们枚举的第一个常数是这个
Card CARDNUMBER
那么它是整个扑克牌的张数,我们把它定义为 52 张。
那么我们第二个枚举的常数是这个花色, SUIT,SUIT
那么一共是什么样呢?具有 4 个花色。
那么我们枚举的第三个常数是这个值的变量, [空白音频]
每一个花色一共有 13 个不同的这样的一个值。
那么定义完了这样的
一个,当然这个枚举也可以,也可以把这个枚举定义在这个 class 里面。
定义在 class 里面的意思就是这个枚举只为这个
这个 class 所用,而不能够被其他的这样的一个成员所用。
[空白音频]
[空白音频] [空白音频]
这个枚举的这个写法应该是逗号,而不是这样的一个分号,
应该是逗号。
那么枚举之间是这样的一个逗号隔开,而不是这样的一个分号,我们注意一下。
那么有了这样的三个 枚举了之后,有了这样三个枚举了之后,那么在下面,在下面,
在这个 class 里面,我们注意这个是比较关键的,我们要定义一个这样的一个
定义扑克
牌的 数组。
我们要定义一个什么样的数组呢? 主要它是一个
private 型的,它应该是一个
CNode,它是一个 CNode
型的 数组,也就是说数组里面的每一个成员都应该是什么呢?都应该是一个 这样的一个 Node 型的这样的结构。
也就是说,数组里面的每一个成员都含有两个分量,一个是花色 一个是这样的一个面值。
那么这个数组没有,我们随便 随便起一个名字,假设叫做 deck,那么应该等于什么呢?
我们来分配一下空间, deck
我们在后面分配空间, 我们声明了这样的一个数组。
那么注意, 对于对于的一个声明,我们再强调一遍,它仅仅只是声明了一个指向这样的一个数组类型的
句柄,还并没有为这个数组真正地分配空间,凡是要见到 new 才能够真正地分配空间。
这时候呢内存的里面只会为这个 deck 分配一个 4
个字节的一个存放句柄也就是存放一个整数,句柄其实就是一个整数的空间。
这个整数将要代表一个这样的一个速度在内存里面的这样的空间的缩影。
但是现在还没有分配空间,所以说这个缩影的值,目前这个缩影的值 是一个空值,我们还没把它关联,正式关联到一块内存空间上来。
只是声明了一个将有这样的一个内存缩影的这样的一个 缩影值在这边。
那么,随后 [无声]
随后我们怎么样呢,随后我们将 创造这样的一个构造函数。
public
card,用这个构造函数怎么样呢,来初始化什么呀, 来初始化这样的一个 deck 这样的一个数组。
首先为这样的一个 deck 这样的一个数组怎么样呢, 来分配空间,deck
应该等于 new CNode。
在这样的一个 CNode 里面我们
需要为它一共分配多少个空间呢,一共分配 52 个空间,当然我们可以直接写上这样的 52。
但是我们应该有一些更好的写法,那么万一以后扑克牌不是 52 张了呢。
我们在这边定义了一个 card number 这样的一个常数它是
52, 所以说我们应该使用这样的一个常数,但是我前面讲枚举的时候
已经说过了,枚举它是一个整数没有问题,但是它 不能够直接把它就当成一个整数来用。
当你要非要把它当成一个整数来用的时候我们应该有一个强制的转换 int
把这个 number
card number card number
里面的这样的一个 card number 这样的一个常量,我们也
又是补上,我们分配来用来进行这样的一个内存的分配。
那么到此为止我们就在内存里面分配了一个 52 个大小的 CNode 型的数组。
这个数组的索引存在了这样的一个 deck 这样的一个 里面。
那么做完了这一步了之后,那么 首先我们再声明两个临时的这样的一个变量
来做这样的一个,为下一步赋值做一些准备。
第一个临时的变量就是这个花色。
我们创建一个字符型的数组。
那么这个字符型的数组应该等于这样的一个它们的花色。
花色我们利用这样的一个新的阿斯克码的字符集里面,其中阿斯克码的值是 3,4,5,6
的时候分别能够打印出来字符一样的这样的一个 红桃、 方块、
梅花和这样的一个黑桃,所以我们让这个 suit
它的值分别是 char 3,
因为我们在,我在键盘上 打不出来这个红桃、
梅花和方块的这样的一个字 所以说我只能把整数用这样的方式,把整数
3,4,5,6 强制转换为字符。
当然了,只有你计算机上对应了,有这样的一个对应的字符集
那么才能够正确地这样显示出来这样的一个字符串,否则的话是
打印出来的将会是其他的这样的一个乱码。
那么它分别是红桃, 红桃,红桃是
3,然后是方块,
diamod,方块,然后是梅花,
梅花和黑桃。
和黑桃,这样的一个字符串。
其次呢,其次我们在 在声明这样的一个字符型的这样的一个数组,字符型这样的数组
它是什么呢,它是这样的一个,我们的面值。
那么它分别是 A, 我们用 A 来表示, 然后是
2, 3
4,5
6,7
8,9
10 然后是
Jack, Queen
和这个 King。
一共 13 个面值。
诚如我说的,这里面其实每一个都只有一个字符,除了这个 10。
所以说我们还是用了一个 string 来表示,如果只有都是单个字符的话,那么完全可以使用一个
char 这样的一个东西来 表示了。
那么这是两个我们临时的变量,特别要注意的是 这个
suit 和这个 face 虽然名字和这个 suit 和这个 face 是一样的,但是完全是两码子事。
这个是,我们这个构造函数里面的一个局部变量, 这个
suit 和这个 face 可是这个 CNode 里面的分量的名字。
只是恰巧重名而已,没有什么任何的联系。
[无声]
那完了之后怎么样呢,完了之后我们做一个循环,把这些值分别赋到这样的一个 deck
里面,使得 deck 有一个初值,当然这样的一个循环,那么它应该是一个 for 循环。
int i = 0 i 小于,应该小于多少呢,当然应该小于 52。
52,也就是这个值,也就是我们还是,既然我们已经都用了这样的一个枚举的话。
那么我们当然应该是坚持这样的一个用法。
然后之后怎么样呢,之后应该是 i ++ 做这样的一个从
0 到 51 的这样的一个循环。
那么对于在每一个循环里面,对于这个 deck
[i] 来讲,应该为每一个
分量来进行赋值,首先是它的这个花色, face
应该等于什么呢,它应该等于从 1 开始一直
赋值赋值,一直赋值到 13 的时候再回来再循环再变成 1,也就是当
i = 0 的时候 这个 face 应该等于,face[0]
对吧,那么当 i = 12 的时候应该是 K,当
i = 13 的时候又回到了这样的一个 A 进行来赋值。
OK,那么它的这个计算公式应该是,等于什么呢, 等于
face 等于 face [i]。
当然了如果这个 i 超过 这个 13 的话,那么也就是说超过这样的一个花色数的话,应该怎么样呢,对它取个余。
把它加过来,应该是对于它的 13 的取余,对于 13 取余。
同样的我们 13 有一个常数,就是这个,face number。
那么我们也可以使用这样的,我们定义好的一个常数,以便我们的程序有更加的这样的一个
灵活性。
[无声] [无声]
当然了,我们对于这样的一个 deck,
对于这样的一个 i,
那么对于这个花色来说,它应该等于什么呢,它当然应该等于 它应该等于这个花色的这样的一个
这样的一个 i 值。
那么也同样的,也应该是对这样的一个 13 怎么样呢,进行取余。
[无声] 对应到这样的一个花色,这样的一个
值上,也就是说当这个 i 是
[无声] 当这个
i 是 它应该是除以这样的一个
这样的一个 13,这样的一个数。
那么也就是说当 i 分别是 1 到 12 的时候我们
应该是第一种花色,当 i 从这个 13 一直到 25
的时候应该开始的是第二个花色,那么刚好应该是 i 除以 13
的这样的一个 sharp 就是对应的这样的一个,我们上面定义的
suit 这样的下标,suit 一共是从 0,1,2,3 四个花色。
那么完了之后我们通过这样的一个循环, 我们通过这样的一个循环就完成了这样的一个
对这样的一个,deck这样的一个数组的初始化的这样的一个过程。
好了,那么有 了这样的一个初始化的这样的一个过程之后,下来我们再来写它的这样的一个,我们可以先把-
这样的一个 东西折叠起来,折叠起来,完了之后我们首先
来写一个这样的一个发牌的这样的一个函数。
public 它能够把这样的一个每一张牌按顺序发给这样的一个
四个人,分别是甲乙丙丁四个人,或者是ABCD四个人, 或者是什么什么什么四个人,都可以,那么我们把这个函数叫做deal
那么在这个发牌函数里面我们开始进行输出,
直接进行输出,cons console
并没有保留这个发牌的每个人的手里的东西。
[空白_录音] write,
我们首先输出一些等号,
来作为一些提示, [空白_录音]
[空白_录音]
[空白_录音] 52
张 [空白_录音]
次序,次序,
[空白_录音]
[空白_录音]
[空白_录音]
[空白_录音] [空白_录音]
[空白_录音]
[空白_录音] [空白_录音]
那么这个次序分别是甲乙 丙丁,甲乙丙丁我们简单的空几个格子,
一二三四五六,六七,七个
用汉字甲 乙,
[空白_录音] 丙,
丁,
来表示。
[空白_录音] 好了,下来怎么样呢?下来是正儿八经的发牌的这样
的一个程序,int,我们再做一个循环,i等于零,同样的应该是 i小于
小于这样的一个 CardNum,也就是说小于,说白了就是小于52,
然后应该是i加加, 那么在这样的一个里面,
[空白_录音]
那么来写
Console点 Write,我们把,从零开始把每个
牌依次发给这样的一个每个牌手就可以了。
然后第,第 [0,2]
张 冒号,
括号1,
2,空格,然后一个
t,这是一个输出的格式,如果大家对这个格式不满意的话,可以按照自己的格式
打的这样的一个更,更好一些,来进行来判断。
那么也就是说在这个里面我们首先输的是i加1,
表示的是第,第i张牌,那么发的这个东西,那么索性我们再打印出来这个deck
i点suit,就先打印它的这样的一个花色,
那么再打印出来它的这样的一个数值,面值,
点, 通过这样的,这样的一个语句我们来输出这样的一个发牌,
那么if,如果怎么样呢?每发 四张牌我们换一行,我如果这个i加1
i加1能够被 如果能够被4整除了的话,
我们输出一个换行,
[空白_录音]
那么
在整个程序把牌全部 都发完了之后,我们再输出一个换行,
我们多输一点换行,使得我们程序能够清楚一点,清楚一点, OK,OK。
下面我们先 不急着做我们的这样的一个洗牌的这样的一个程序,
那么我们先简单的测试一下我们这样刚才的初始化之后,因为
我们现在有了一个deal能够把五十二张牌按顺序在屏幕上打印出来,
那么还有我们有了这样的一个public的构造函数card,能够把这个deck也就是- 把这五十二张牌按照
顺序怎么样呢?先把它初始化成这样的一副新的这样的没有洗过的扑克牌。
OK,那么做程序的一个东西就是说如果我们 当取得了一个阶段性成果之后,我们先可以怎么样呢?先可以把它
测试一下,如果发现错误的话,我们可以及时的更正,这样可以把错误限制在更少的范围之内, 对后面的调试减轻一些难度。
所以说,在主函数里面怎么样呢?
在主函数里面,我们来,首先来初始化这样的一个
初始化一次这样的,这样扑克牌,我们来发一次牌来看看到底怎么样。
我们首先Card,声明一个这样的一个Card的变量,假设叫做
小写的card,那么它等于一个new
Card,我们的这个Card的构造函数不带有这样的任何的参数, 那么card这样的new
Card完了之后怎么样呢?我们调用card的这样的,直接调用它的这个
调用它的这样的一个deal这样的一个发牌函数,我们来看一下 它是不是发的正确,摁下这个ctrl
F5我们运行一下程序, 那么第一张
我们看到,这样的第一张牌它首先是这样的一个红心的 A,然后下来是第二张红心2,
红心3,红心4,一直到第十三张牌是红心K, 第十四张牌开始是方片的,到了第二十七张是
梅花A,一直到第四十张, 是黑桃,黑桃A,那到了第五十二张是黑桃K,
那么这就是怎么样呢?这就是第一次这样没有洗牌之后这样的一个发牌这样的一个结果。
那么这样的一个程序我们验证了通过了之后,我们可以继续
继续完了之后,在我们这样的一个扑克牌的洗牌程序完了之后,我们还应该把它,我们可以把- 它折叠起来,
我们也可以把这个折叠起来,这时我们一共写了这样的一个 写了这样的一个两个这样的一个
函数,一个构造函数,一个这样的一个发牌的函数, 还有一个private型的这样的一个数组。
完了之后怎么样呢?完了之后我们 增加我们的下一个这样的一个方法,那么它是一个洗牌的这样的一个方法,
public void
[空白_录音] 那么在这个洗牌的这样的一个方法里面,
int j,我们根据刚才我们的思路,我们做一次这样的一个
循环,对于每一次这样的一个循环来讲
那么我们把这两个牌进行怎么样呢,依次这样的一个交换 那么既然要交换这样的一个两张牌
这样交换两张牌呢,我们肯定需要一个 temp
这样的一个 临时的这样的一个变量
那么注意下,这个后面有没有 new 呢? CNode
temp 要不要写 CNode temp 等于 new 什么什么呢?
我们说不用,为什么不用呢?因为 CNode
它是一个 struct 类型的变量 对于 struct
类型的变量来讲,它是一个值变量 所以说,当你 struct 写了一个 CNode
temp 的时候,就会由内存空间的分配 给这两个分量的值,而不需要再用
new 来分配其他的内存空间 如同这个 int j 一样,一旦写了
int j ,就会为 j 分配空间 struct CNode
它是一个直类型的变量,所以说直接就写 CNode temp 就可以了。
接下来我们肯定还需要产生一个随机 数,所以说我们需要随机数这样的一个变量,r
应该等于我们 它是一个类,当然需要一个 new r 等于 random。
那么有了这样的一个 事情完了之后,我们只需要再一次做出
i 从 0 开始,i 对于这样的一个循环再进行做一下就可以了
那么也是 card number,对,这样的一个,从 0 到 52
做一次这样的一个循环 那么在这样的一个循环里面,我们
首先产生一个 0 到 51 之间的这样的一个随机数 这个随机数
j 应该等于什么呢,等于这个 r 点 next。
我们采用这样的一个 next 这样的一个,它一共
next 有三个这样的一个重载的函数 那其中第一个不带任何参数的这个函数返回这个非负的这样的一个随机数
而这个第二个返回一个这个 小于所指定最大值的非负的随机数
第三个是返回一个在指定范围内的随机数
那么明显我们只需要用第二个就行了,返回一个小于所指定最
大值的随机数,但是该随机数取不了最大值,但是它是可以取得零值的 刚好符合了要求。
我们要产生一个 0 到 52 之间的,但不包括 52
的随机数 所以我们只需要把这个常量的值拷贝过来就可以了
那么我们产生一个这样的一个 j
的随机数 那么有了这样 j 的随机数,下来就是要把 deck i 跟 deck
j 怎么样呢交换一下,那么这个事情就比较简单了 那么我们首先让 temp 等于这样的一个
deck i 其次让这个
deck i
等于 deck j ,那么
这个打错了,d e c k
那么完了之后,让这个 deck
j 等于 temp。
那么经过了这样的 一个 52 个循环之后,我们就进行了
52 次随机的交换 我们就做了我们,按照我们这个方式就做了这样一个发牌
那么有了这样的一个发牌了之后 那么我们在这个第一轮发牌完了之后,我们
card 我们把这个牌重新洗一下,我们调用这个
shuffle,完了之后怎么样呢,那我们再做一次发牌, card deal。
发牌,然后洗一次牌 我们再发一次牌,然后我们来测试一下我们这样的一个例子,按一下这个
Ctrl F5 再运行一下 哦,发生了一个错误,我们看一下错误错在哪呢?
嗯…括号,这个括号有些问题,括号没有匹配,应该多输了一个括号
好了,我们改正完这个错误之后,再按一下这样的一个 Ctrl F5 运行一下。
我们看到我们一共发了两次牌,其中第一次是 红桃
A ,我们这样的牌怎么样呢,是正确的这样的一个顺序,其中第四十张牌是黑桃
A 然后我们接着有了第二次这样的一个发牌 第二次发牌我们是看到它完全这样的已经被打乱了,被打乱了
那么,按照这样的一个基本上类似于随机的方式给甲乙丙丁四位牌手发了这样的一个
不同的这样的一个牌
好,关于这道例题我们就暂时讲到这