鱼C论坛

 找回密码
 立即注册
查看: 5124|回复: 20

[技术交流] 24 - 制作发牌器

[复制链接]
发表于 2021-9-16 18:15:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 鱼C-小师妹 于 2022-3-2 20:39 编辑

在线讲解:



关于递归的玩法,我们先告一段落。

从这讲开始,我们用 Python 来编写几个小游戏~

download.png

众所周知,一副扑克有 54 张牌,现在假设玩某种扑克游戏,要将去除大小王的 52 张牌分给 4 个人。

我们自己动手设计一个程序完成自动发牌的工作。

52 张牌分给 4 位朋友,每人应当有 13 张牌。

人工发牌时,先进行洗牌,然后将洗好的牌按一定的顺序发给每一个人对不对。

我们为了便于计算机模拟,我们要将上面的人工方式进行修改。

既然是计算机模拟,如果我们一上来就传入黑桃,计算机就只会认为这是一串字符。

先要来建立一个对应关系,例如按照“黑红梅方”的顺序,从 2~A,按照顺序排列。

花色\点数 2 3 4 5 6 7 8 9 10 J Q K A
黑桃 0 1 2 3 4 5 6 7 8 9 10 11 12
红桃 13 14 15 16 17 18 19 20 21 22 23 24 25
梅花 26 27 28 29 30 31 32 33 34 35 36 37 38
方块 39 40 41 42 43 44 45 46 47 48 49 50 51

按照上面表格中的对应顺序将每一张牌用一个数字代表。

这样如果生成 45 ,我们通过观察,查表可知代表方块 8。

但是计算机没有眼睛,怎么让它知道 45 是什么呢?

注意观察,四种花色区间有什么特点呢?

没错啦,黑桃小于 13,红桃大等于 13 但是小于 25,以此类推。

这个规律进一步分析就是“取整”啦~

四种花色对 13 进行 // ,只会得到 0,1,2,3 四个值~

还是拿 45 举例子,因为 45 // 13 == 3,3 就对应方块。

每张牌都包含两个特性:花色和点数。

花色有了,那么如何找到点数呢?

我们可以先来创建一个代表牌点数的列表:
n = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
这个列表中对应 13 个点数~

索引 0 对应点数 2,索引 1 对应点数 3,以此类推~

四种花色都遵循相同规则。

而这个规则背后是什么规律呢?

就是相同点数的余数一样!

拿第一列来说:

0,13,26,39

它们除以 13 的余数为 0。

第二列:

1,14,27,40

它们除以 13 的余数为 1。

没错啦可以直接拿 45 % 13,结果为 6,就对应 8。

这样就让计算机找到 45 为方块 8!

思路有了,我们来动手写代码吧。

发牌这个操作就可以变成将含有 0 到 51 个数的列表分成 4 个子列表的过程。

0 到 51 个数,就是生成一个随机数的过程,只不过随机数不能有重复。

还记得我们之前用的 random 模块吗?

这次又要用到它,生成 0~51 之间的共 52 个随机数,以产生洗牌的效果。

先来创建一个存放上面表格对应顺序的总长度列表:
 a = [0] * 52
要平均分成 4 个子列表,每个中都是 13 张牌:
card1 = [0] * 13    
card2 = [0] * 13    
card3 = [0] * 13    
card4 = [0] * 13
牌和点数需要建立对应关系,4 堆牌就需要四个索引。

创建一个变量 t 用来控制总的发牌数:
c1, c2, c3, c4, t = 0, 0, 0, 0, 0
接下来要控制发牌并产生 0 到 51 间的随机数:
while ( t <= 51):
    m = random.randint(0,52)
既然是随机数肯定是随机产生的,牌的点数虽然可以重复,但是同色不可能有两张。

也就是说上面对应关系的 52 个数都应该是唯一不重复的。

所以这里我们就要加一个去重操作:

  • flag = 1 表示产生的是新的随机数
  • flag = 0 表示新产生的随机数已经存在

这种去重方式也用过几次啦,还没记住的,务必要记住用法哦:
flag, i = True, 1
while i <= t and flag:
    if m == a[i]:
        flag = False
    i += 1
如果产生新的随机数,则存入数组:
if flag:
    a[t] == m
    t += 1
接下来就要将牌分到不同花色中,既然是 4 种花色,就可以用 “%” 取余来分配。

然后根据 t 的余数,判断当前的牌应存入哪个数组中:
while i <= t and flag:
    if m == a[i]:
        flag = 0
    i += 1
if flag:
    a[t] = m
    t += 1
    if t % 4 == 0:
        card1[c1] = a[t - 1]
        c1 += 1
    elif t % 4 == 1:
        card2[c2] = a[t - 1]
        c2 += 1
    elif t % 4 == 2:
        card3[c3] = a[t - 1]
        c3 += 1
    elif t % 4 == 3:
        card4[c4] = a[t - 1]
        c4 += 1
到这一步 4 个子列表就分好啦,我们可以先打印下:
print(card1)
    print(card2)
    print(card3)
    print(card4)
2022-02-28_23-24-20.png

不对!!

怎么不是每组中都是 13 个值呢?

竟然是从 1 到 51,51 个数,哪里出问题了呢?

在这里:
if m == a[i]:
我们原意是打算判断是否随机有重复~

初始化的 a 中全是 0!

0 这个数是我们需要的,那么 m 第一次有没有随机生成 0 的可能呢?

有!

所以 a 的初始化值不应该是 0 到 51 之间的整数,可以是其他的,我们就用 52:
 a = [52] * 52
现在再来打印看下:

2022-02-28_23-45-43.png

没错啦,各 13 个数,而且没有重复。

接下来只需将它们转换成对应的牌即可。

总共 4 种花色,52 张牌,由于每个花色的符号不一样,就需要进行划分。
card1 // 13 == 0
余数 0,1,2,3 对应 4种花色。

然后还要通过“取余”将值转换回对应牌值:
def finalPrint(card,n):
    print("\n♠",end='')
    for i in range(13):
        if card[i] // 13 == 0:
            print(n[card[i] % 13],end = '')

    print("\n♥",end='')
    for i in range(13):
        if card[i] // 13 == 1:
            print(n[card[i] % 13],end = '')

    print("\n♣",end='')
    for i in range(13):
        if card[i] // 13 == 2:
            print(n[card[i] % 13],end = '')

    print("\n♦",end='')
    for i in range(13):
        if card[i] // 13 == 3:
            print(n[card[i] % 13],end = '')
    print()
代码中的乱码是因为论坛暂时不支持字符编码,复制到本地就能看到啦。

好啦,打印看下结果吧:

2022-02-28_23-46-39.png

没错啦,是我们要的结果~

但是吧,作为一名负责任的开发者,要充分为用户考虑。

现在的排列顺序是乱的,可以不可以排序呢?

肯定可以啦,在打印前对 4 个 card 进行排序:
    card1 = sorted(card1)
    card2 = sorted(card2)
    card3 = sorted(card3)  
    card4 = sorted(card4)

现在看下结果:

2022-02-28_23-50-37.png

是不是好看很多啦!

源码: py25.py.zip (1.04 KB, 下载次数: 15, 售价: 10 鱼币)

搞定,下课!

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-9-16 18:54:25 | 显示全部楼层
本帖最后由 傻眼貓咪 于 2021-12-23 19:22 编辑

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-9-16 21:21:10 | 显示全部楼层
应该很有趣
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-7 19:14:51 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-10-9 17:30:41 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-11-20 22:17:59 | 显示全部楼层
random
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-21 01:41:43 From FishC Mobile | 显示全部楼层
人生的奔跑,不在于瞬间的爆发,而取决于途中的坚持。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-21 11:22:48 | 显示全部楼层
牛逼
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-11-21 11:52:24 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-11-24 00:28:51 From FishC Mobile | 显示全部楼层
看了看看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-27 18:11:56 | 显示全部楼层
学习下代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-2 16:58:35 | 显示全部楼层
学习一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-14 16:26:18 | 显示全部楼层
游戏中学习python
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-12-23 19:09:06 | 显示全部楼层

剧透警告!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-23 19:22:34 | 显示全部楼层

已删
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-24 15:10:30 | 显示全部楼层
Thanks&#9834;(&#65381;ω&#65381;)&#65417;
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-8 20:33:00 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-5-12 19:22:10 | 显示全部楼层
# 题干
# 动手设计一个程序完成自动发牌的工作, 分别将52 张牌分发给 4 位朋友,每人应当有 13 张牌。

def Print_result(Person):
    cardfacechar = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
    str1 = '&#9824; '
    str2 = '&#9829; '
    str3 = '&#9830; '
    str4 = '&#9827; '
    Person.sort()
    for index in range(13):
        number = Person[index]
        if 0 < number/13 <= 1:
            str1 += f'{cardfacechar[number%13 - 1]} '
        elif 1 < number/13 <= 2:
            str2 += f'{cardfacechar[number%13 - 1]} '
        elif 2 < number/13 <= 3:
            str3 += f'{cardfacechar[number%13 - 1]} '
        else:
            str4 += f'{cardfacechar[number%13 - 1]} '
    return (str1+'\n'+str2+'\n'+str3+'\n'+str4+'\n')


PersonTotal = ['*'] * 52
import random as r
index = 0
while index in range(52):
    each = r.randint(1, 52)
    if each not in PersonTotal:
        PersonTotal[index] = each
        index += 1
    else:
        continue
Person1 = PersonTotal[0:13]
Person2 = PersonTotal[13:26]
Person3 = PersonTotal[26:39]
Person4 = PersonTotal[39:52]


print(Print_result(Person1))
print(Print_result(Person2))
print(Print_result(Person3))
print(Print_result(Person4))
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-12 19:57:32 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-7-2 11:02:20 | 显示全部楼层
random.randint(a,b)函数包含a和b吧,如果是random.randint(0,52)的话就有53个值了,后续打印的过程会出问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-26 09:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表