目录
实际上,如果pocker直接存储扑克牌,而不是扑克牌的编号,则程序更加简单,但是pocker列表创建书写麻烦一些。修改后代码如下:
请完成《4.6 游戏初步——发牌程序(控制台版)》,并完成以下修改/扩展内容
修改内容:仍然将52张牌发给4名牌手,但是只输出自己(牌手1)手上的牌,其他牌手的牌不需要输出
扩展内容:你有三张技能卡,每次可以对任意一名牌手使用(包括自己),技能详情如下:
技能一:显示手牌中对牌的数量,对牌的定义为数字相同而且刚好两张牌(注意,即3张或4张相同的不算对牌)
技能二:显示手牌中数量最多的花色,以及对应花色的牌数
技能三:显示手牌中的最大顺子(2张或以上数字连续的即为顺子,例如A-2-3-4、7-8-9-10-J-Q-K),如果这样的最大顺子有多个,输出任意一个
请补充代码,在发完牌显示了自己手牌之后,通过控制台/键盘输入输出实现以上功能,操作步骤如下:
(1)输入要使用技能的对象
(2)输入要使用哪一项技能
(3)程序执行该技能,输出结果
(4)重复以上步骤,直至三次技能用完之后,程序结束
进阶要求:你的扩展内容应该在一个独立的模块中实现。
- import random
- n=52
- def gen_pocker(n): #交换牌的顺序100此,达到洗牌目的
- x=100
- while(x>0):
- x=x-1
- p1=random.randint(0,n-1)
- p2=random.randint(0,n-1)
- t=pocker[p1]=pocker[p2]
- pocker[p2]=t
- return pocker
- def getColor(x): #获取牌的花色
- color=["草花","方块","红桃","黑桃"]
- c=int(x/13)
- if c<0 or c>=4:
- return "ERROR!"
- return color[c]
- def getValue(x): #获取牌的牌面大小
- value=x%13
- if value==0:
- return 'A'
- elif value>=1 and value<=9:
- return str(value+1)
- elif value==10:
- return 'J'
- elif value==11:
- return 'Q'
- elif value==12:
- return 'K'
-
- def getPuk(x):
- return getColor(x)+getValue(x)
- #主程序
- (a,b,c,d)=([],[],[],[])#a、b、c、d四个列表分别存储4个人的牌
- pocker=[i for i in range(n)]#未洗牌之前[0,1,2,3,...,51]
- pocker=gen_pocker(n)#洗牌目的
- print(pocker)
- for x in range(13):#发牌,每人13张牌
- m=x*4
- a.append(getPuk(pocker[m]))
- b.append(getPuk(pocker[m+1]))
- c.append(getPuk(pocker[m+2]))
- d.append(getPuk(pocker[m+3]))
- a.sort() #牌手的牌排序,就是相当于理解,同花色在一起
- b.sort()
- c.sort()
- d.sort()
- print("牌手1",end=":")
- for x in a:
- print(x,end=" ")
- print("\n牌手2",end=":")
- for x in b:
- print(x,end=" ")
- print("\n牌手3",end=":")
- for x in c:
- print(x,end=" ")
- print("\n牌手4",end=":")
- for x in d:
- print(x,end=" ")
- import random
- n=52
- def gen_pocker(n): #交换牌的顺序100此,达到洗牌目的
- x=100
- while(x>0):
- x=x-1
- p1=random.randint(0,n-1)
- p2=random.randint(0,n-1)
- t=pocker[p1]=pocker[p2]
- pocker[p2]=t
- return pocker
-
- def getColor(x): #获取牌的花色
- color=["草花","方块","红桃","黑桃"]
- c=int(x/13)
- if c<0 or c>=4:
- return "ERROR!"
- return color[c]
- def getValue(x): #获取牌的牌面大小
- value=x%13
- if value==0:
- return 'A'
- elif value>=1 and value<=9:
- return str(value+1)
- elif value==10:
- return 'J'
- elif value==11:
- return 'Q'
- elif value==12:
- return 'K'
-
- #主程序
- (a,b,c,d)=([],[],[],[]) #a,b,c,d四个列表分别存储4个人的牌
- #pocker=[getPuk(i) for i in range(n)] #未洗牌之前
- pocker=['草花A','草S花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']
- pocker=gen_pocker(n)
- print(pocker)
- for x in range (13):
- m=x*4
- a.append(pocker[m])
- b.append(pocker[m+1])
- c.append(pocker[m+2])
- d.append(pocker[m+3])
- print("牌手1",end=":")
- for x in a:
- print(x,end=" ")
- print("\n牌手2",end=":")
- for x in b:
- print(x,end=" ")
- print("\n牌手3",end=":")
- for x in c:
- print(x,end=" ")
- print("\n牌手4",end=":")
- for x in d:
- print(x,end=" ")
1.请写出实现“技能一”的思路与算法描述
答:创建一个空字典 card_count 用于记录每张牌的数量。
遍历玩家的手牌列表 player_hand,对于每张牌:如果该牌已经在 card_count 中,将其数量加一。
否则,在 card_count 中创建该牌的记录,并将数量设为1。
遍历完所有牌后,找出数量为2的牌,这些牌即为对牌。
输出对牌的数量和详细信息。
2.请写出实现“技能二”的思路与算法描述
答:创建一个空字典 color_count 用于记录每种花色的牌的数量。
遍历玩家的手牌列表 player_hand,对于每张牌:提取该牌的花色。
如果该花色已经在 color_count 中,将其数量加一。
否则,在 color_count 中创建该花色的记录,并将数量设为1。
找到数量最多的花色及其对应的牌数。
输出最多的花色和对应的牌数。
3.请写出实现“技能三”的思路与算法描述
答:将玩家手牌按照牌面值排序。
创建两个列表 longest_sequence 和 current_sequence 用于记录最长连续顺子和当前正在遍历的顺子。
遍历所有可能的起始点,找到最长的连续顺子:如果当前顺子为空,将当前牌加入到顺子中。
否则,将当前牌与上一张牌比较,如果是连续的,则加入当前顺子,否则开始新的顺子。
检查最后一个顺子,如果比当前记录的最长顺子还长,则更新最长顺子。
如果最长顺子长度小于2,则输出没有找到顺子。
否则,将顺子的值转换回原始形式,并输出最大顺子。
- import random
- n = 52
- def gen_poker(n):
- poker = [i for i in range(n)]
- x = 100
- while x > 0:
- x = x - 1
- p1 = random.randint(0, n - 1)
- p2 = random.randint(0, n - 1)
- t = poker[p1]
- poker[p1] = poker[p2]
- poker[p2] = t
- return poker
-
- def getColor(x):
- color = ["草花", "方块", "红桃", "黑桃"]
- c = int(x / 13)
- if c < 0 or c >= 4:
- return "ERROR!"
- return color[c]
-
- def getValue(x):
- value = x % 13
- if value == 0:
- return 'A'
- elif value >= 1 and value <= 9:
- return str(value + 1)
- elif value == 10:
- return 'J'
- elif value == 11:
- return 'Q'
- elif value == 12:
- return 'K'
-
- def getPuk(x):
- return getColor(x) + getValue(x)
-
- def skill_one(player_hand):
- card_count = {}
-
- for card in player_hand:
- if card in card_count:
- card_count[card] += 1
- else:
- card_count[card] = 1
-
- pairs = [card for card, count in card_count.items() if count == 2]
-
- print(f"对牌数量:{len(pairs)}")
- if len(pairs) > 0:
- print("对牌详细信息:")
- for pair in pairs:
- print(pair)
-
-
- def skill_two(player_hand):
- color_count = {}
-
- for card in player_hand:
- color = card.split()[0]
- if color in color_count:
- color_count[color] += 1
- else:
- color_count[color] = 1
-
- max_color = max(color_count, key=lambda k: color_count[k])
- max_count = color_count[max_color]
-
- print(f"数量最多的花色:{max_color}")
- print(f"{max_color}牌的数量:{max_count}")
-
-
- def skill_three(player_hand):
- player_hand_values = sorted(player_hand) # 将手牌排序
-
- # 遍历所有可能的起始点,找到最长的连续顺子
- longest_sequence = []
- current_sequence = []
-
- for value in player_hand_values:
- if not current_sequence:
- current_sequence.append(value)
- else:
- last_value = current_sequence[-1]
- if last_value is not None and ord(value[0]) == ord(last_value[0]) + 1:
- current_sequence.append(value)
- else:
- if len(current_sequence) > len(longest_sequence):
- longest_sequence = current_sequence
- current_sequence = [value]
-
- # 检查最后一个连续顺子
- if len(current_sequence) > len(longest_sequence):
- longest_sequence = current_sequence
-
- if len(longest_sequence) < 2:
- print("没有找到顺子")
- else:
- # 将顺子的值转换回原始形式
- longest_sequence_values = [card for card in player_hand if card in longest_sequence]
- print(f"最大顺子: {'-'.join(longest_sequence_values)}")
-
-
- # 主程序
- (a, b, c, d) = ([], [], [], [])
-
- poker = gen_poker(n)
-
- for x in range(13):
- m = x * 4
- a.append(getPuk(poker[m]))
- b.append(getPuk(poker[m + 1]))
- c.append(getPuk(poker[m + 2]))
- d.append(getPuk(poker[m + 3]))
- a.sort()
- b.sort()
- c.sort()
- d.sort()
- print("牌手1", end=":")
- for x in a:
- print(x, end=" ")
-
- skills_left = 3 # 剩余技能次数
-
- while skills_left > 0:
- print("\n剩余技能次数:", skills_left)
- target = int(input("选择要使用技能的对象(1-4):"))
- if target < 1 or target > 4:
- print("无效的目标,请重新选择。")
- continue
-
- skill_choice = int(input("选择要使用的技能(1-3):"))
- if skill_choice < 1 or skill_choice > 3:
- print("无效的技能选择,请重新选择。")
- continue
-
- if target == 1:
- player_hand = a
- elif target == 2:
- player_hand = b
- elif target == 3:
- player_hand = c
- else:
- player_hand = d
-
- if skill_choice == 1:
- skill_one(player_hand)
- elif skill_choice == 2:
- skill_two(player_hand)
- else:
- skill_three(player_hand)
-
- skills_left -= 1
-
- print("所有技能已经使用完毕。")
这段代码是一个模拟扑克牌游戏的程序,主要包括生成一副扑克牌、发牌给四名玩家、以及玩家可以使用的三种技能。我会逐步解释代码的各个部分:
- import random
- n = 52
这里导入了Python的随机模块,并初始化了牌堆的大小为52,代表一副标准扑克牌。
gen_poker(n)
:- def gen_poker(n):
- poker = [i for i in range(n)]
- x = 100
- while x > 0:
- x = x - 1
- p1 = random.randint(0, n - 1)
- p2 = random.randint(0, n - 1)
- t = poker[p1]
- poker[p1] = poker[p2]
- poker[p2] = t
- return poker
这个函数生成一副打乱顺序的扑克牌,并将它们存储在一个列表 poker
中。在生成牌堆时,通过多次随机交换牌的位置来打乱顺序。
定义获取牌的花色和牌面值的函数 getColor(x)
和 getValue(x)
,以及获取完整扑克牌名字的函数 getPuk(x)
。
定义三种技能函数:
skill_one(player_hand)
:计算玩家手中的对子数量并打印出来。skill_two(player_hand)
:计算玩家手中数量最多的花色,并打印出来。skill_three(player_hand)
:找出玩家手中的最长连续顺子,并打印出来。初始化四名玩家的手牌:
(a, b, c, d) = ([], [], [], [])
- poker = gen_poker(n)
-
- for x in range(13):
- m = x * 4
- a.append(getPuk(poker[m]))
- b.append(getPuk(poker[m + 1]))
- c.append(getPuk(poker[m + 2]))
- d.append(getPuk(poker[m + 3]))
- a.sort()
- b.sort()
- c.sort()
- d.sort()
这个部分将一副牌分发给四名玩家,每名玩家获得13张牌,并按照花色和牌面值排序。
- skills_left = 3 # 剩余技能次数
-
- while skills_left > 0:
- print("\n剩余技能次数:", skills_left)
- target = int(input("选择要使用技能的对象(1-4):"))
- if target < 1 or target > 4:
- print("无效的目标,请重新选择。")
- continue
-
- skill_choice = int(input("选择要使用的技能(1-3):"))
- if skill_choice < 1 or skill_choice > 3:
- print("无效的技能选择,请重新选择。")
- continue
-
- if target == 1:
- player_hand = a
- elif target == 2:
- player_hand = b
- elif target == 3:
- player_hand = c
- else:
- player_hand = d
-
- if skill_choice == 1:
- skill_one(player_hand)
- elif skill_choice == 2:
- skill_two(player_hand)
- else:
- skill_three(player_hand)
-
- skills_left -= 1
-
- print("所有技能已经使用完毕。")
这部分允许玩家选择目标玩家和技能,并调用相应的技能函数来处理玩家的手牌。游戏循环会持续3轮,每轮玩家可以使用一个技能。一旦技能次数用完,游戏结束。
当玩家选择使用技能时,根据他们的选择,会调用相应的技能函数来处理玩家手中的扑克牌。下面分别详细解释技能1、技能2和技能3的代码:
技能1的函数为 skill_one(player_hand)
,其目标是在玩家的手牌中查找对子并打印出来。
- def skill_one(player_hand):
- card_count = {}
-
- for card in player_hand:
- if card in card_count:
- card_count[card] += 1
- else:
- card_count[card] = 1
-
- pairs = [card for card, count in card_count.items() if count == 2]
-
- print(f"对牌数量:{len(pairs)}")
- if len(pairs) > 0:
- print("对牌详细信息:")
- for pair in pairs:
- print(pair)
这个函数的主要步骤包括:
card_count
,用于记录每张牌在玩家手中的数量。card_count
字典中,并更新数量。这个技能用于查找玩家手牌中的对子并报告它们的数量和详细信息。
下面是对技能1中的每一句代码的详细解释:
card_count = {}
这一行创建一个空字典 card_count
,用于记录每张牌在玩家手中出现的次数。字典将被用于统计每张牌的数量。
for card in player_hand:
这是一个 for 循环,它会遍历玩家手中的每张牌,其中 player_hand
是作为参数传递给函数的玩家手牌列表。
if card in card_count:
这一行检查当前遍历到的牌 card
是否已经在 card_count
字典中存在,即是否已经被计数过。
card_count[card] += 1
如果牌已经在 card_count
字典中存在,那么这一行会将该牌对应的计数值加一,表示该牌又出现了一次。
else: card_count[card] = 1
如果牌还没有在 card_count
字典中出现过,那么这一行会将该牌添加到字典,并将其计数值初始化为1,表示该牌第一次出现。
pairs = [card for card, count in card_count.items() if count == 2]
这一行使用列表推导式,从 card_count
字典中筛选出所有计数值为2的牌。具体地,它遍历字典中的每个键值对,其中 card
是牌的名称,count
是该牌的计数值。然后,它只选择那些计数值等于2的牌,将它们存储在 pairs
列表中。
print(f"对牌数量:{len(pairs)}")
这一行打印出对子的数量,使用 f-string 格式化输出。len(pairs)
返回 pairs
列表中对子的数量,并将其打印出来。
if len(pairs) > 0:
这一行检查是否有对子存在,即 pairs
列表是否非空。
print("对牌详细信息:")
如果存在对子,这一行打印出一条消息,指示下面将要打印出对子的详细信息。
for pair in pairs:
这是一个 for 循环,它会遍历 pairs
列表中的每个对子,其中 pair
表示一个对子的牌。
print(pair)
这一行打印出当前对子的牌,即将对子的详细信息逐个打印出来。
总的来说,技能1的代码的作用是统计玩家手牌中的对子数量,并打印出对子的数量和对子的详细信息。这通过创建一个字典来记录每张牌的数量,并通过筛选字典中计数值为2的牌来找到对子。然后,它打印出对子的数量以及每个对子的具体牌面。
技能2的函数为 skill_two(player_hand)
,其目标是在玩家的手牌中找出数量最多的花色,并打印出来。
- def skill_two(player_hand):
- color_count = {}
-
- for card in player_hand:
- color = card.split()[0] # 获取牌的花色
- if color in color_count:
- color_count[color] += 1
- else:
- color_count[color] = 1
-
- max_color = max(color_count, key=lambda k: color_count[k])
- max_count = color_count[max_color]
-
- print(f"数量最多的花色:{max_color}")
- print(f"{max_color}牌的数量:{max_count}")
这个函数的主要步骤包括:
color_count
,用于记录每种花色在玩家手中的数量。color_count
字典中,并更新数量。max
函数找出数量最多的花色,key=lambda k: color_count[k]
用于指定比较的关键字,即花色的数量。这个技能用于找到玩家手牌中数量最多的花色并报告它们。
下面是对技能2中的每一句代码的详细解释:
color_count = {}
这一行创建一个空字典 color_count
,用于记录每种花色在玩家手中出现的次数。字典将被用于统计每种花色的数量。
for card in player_hand:
这是一个 for 循环,它会遍历玩家手中的每张牌,其中 player_hand
是作为参数传递给函数的玩家手牌列表。
color = card.split()[0] # 获取牌的花色
这一行首先使用 split()
方法将牌的字符串分割成两部分,即花色和牌面值,然后通过 [0]
索引获取花色部分。这样,变量 color
就包含了当前牌的花色信息。
if color in color_count:
这一行检查当前遍历到的花色 color
是否已经在 color_count
字典中存在,即是否已经被计数过。
color_count[color] += 1
如果花色已经在 color_count
字典中存在,那么这一行会将该花色对应的计数值加一,表示该花色又出现了一次。
else: color_count[color] = 1
如果花色还没有在 color_count
字典中出现过,那么这一行会将该花色添加到字典,并将其计数值初始化为1,表示该花色第一次出现。
max_color = max(color_count, key=lambda k: color_count[k])
这一行使用 max()
函数找出在 color_count
字典中具有最大值的键,即数量最多的花色。key=lambda k: color_count[k]
指定了比较的关键字,即根据花色的数量来比较。
max_count = color_count[max_color]
这一行通过 max_color
找到了数量最多的花色,然后从 color_count
字典中获取该花色对应的数量,并将其存储在 max_count
变量中。
print(f"数量最多的花色:{max_color}")
这一行使用 f-string 格式化输出,打印出数量最多的花色,即 max_color
变量中存储的花色信息。
print(f"{max_color}牌的数量:{max_count}")
这一行也使用 f-string 格式化输出,打印出具有最大数量的花色的数量,即 max_count
变量中存储的数量信息。
总的来说,技能2的代码的作用是统计玩家手牌中数量最多的花色,并打印出最多的花色和相应的数量。这通过创建一个字典来记录每种花色的数量,然后使用 max()
函数找到具有最大数量的花色,并输出相关信息。
技能3的函数为 skill_three(player_hand)
,其目标是在玩家的手牌中找出最长的连续顺子,并打印出来。
- def skill_three(player_hand):
- player_hand_values = sorted(player_hand) # 将手牌排序
-
- # 遍历所有可能的起始点,找到最长的连续顺子
- longest_sequence = []
- current_sequence = []
-
- for value in player_hand_values:
- if not current_sequence:
- current_sequence.append(value)
- else:
- last_value = current_sequence[-1]
- if last_value is not None and ord(value[0]) == ord(last_value[0]) + 1:
- current_sequence.append(value)
- else:
- if len(current_sequence) > len(longest_sequence):
- longest_sequence = current_sequence
- current_sequence = [value]
-
- # 检查最后一个连续顺子
- if len(current_sequence) > len(longest_sequence):
- longest_sequence = current_sequence
-
- if len(longest_sequence) < 2:
- print("没有找到顺子")
- else:
- # 将顺子的值转换回原始形式
- longest_sequence_values = [card for card in player_hand if card in longest_sequence]
- print(f"最大顺子: {'-'.join(longest_sequence_values)}")
这个函数的主要步骤包括:
这个技能用于查找玩家手牌中最长的连续顺子并报告它们。
下面是对技能三中的每一句代码的详细解释:
player_hand_values = sorted(player_hand) # 将手牌排序
这一行首先将玩家的手牌 player_hand
进行排序,以便后续可以更容易地查找连续的顺子。sorted()
函数返回一个新的列表,其中包含按升序排序的手牌。
- # 遍历所有可能的起始点,找到最长的连续顺子
- longest_sequence = []
- current_sequence = []
这两行代码创建了两个列表,longest_sequence
用于存储找到的最长连续顺子,current_sequence
用于存储当前正在检查的连续顺子。
for value in player_hand_values:
这是一个 for 循环,它会遍历已排序的玩家手牌 player_hand_values
中的每张牌。
- if not current_sequence:
- current_sequence.append(value)
这个条件检查 current_sequence
是否为空,如果为空,表示当前没有正在检查的连续顺子,那么将当前的牌 value
添加到 current_sequence
中,作为可能的起始点。
- else:
- last_value = current_sequence[-1]
- if last_value is not None and ord(value[0]) == ord(last_value[0]) + 1:
- current_sequence.append(value)
这段代码是在检查当前牌 value
是否能够扩展当前的连续顺子 current_sequence
。让我逐步详细解释这段代码的每一部分:
last_value = current_sequence[-1]
:这一行将变量 last_value
设置为当前连续顺子 current_sequence
中的最后一张牌。通过使用索引 [-1]
,我们可以访问列表 current_sequence
的最后一个元素,即最后一张牌。
if last_value is not None and ord(value[0]) == ord(last_value[0]) + 1:
:这是一个条件语句,它有两个条件需要同时满足才会执行以下的代码块。
last_value is not None
检查 last_value
是否不为 None
。这是为了确保 current_sequence
中至少有一张牌,因为如果没有牌,last_value
可能为 None
。ord(value[0]) == ord(last_value[0]) + 1
检查当前牌 value
的第一个字符的 ASCII 值是否比 last_value
的第一个字符的 ASCII 值大 1。这个条件用于检查牌是否连续,因为在大多数常见的牌类游戏中,连续的牌的字符值是相邻的。current_sequence.append(value)
:如果上述两个条件都满足,那么当前的牌 value
就会被添加到连续顺子 current_sequence
的末尾,以扩展这个连续顺子。
综合起来,这段代码的作用是检查当前的牌 value
是否与前一张牌 last_value
连续,如果是,就将当前牌添加到连续顺子中,以继续构建最长的连续顺子。如果当前牌与前一张牌不连续,那么将重新开始检查下一个可能的连续顺子。这有助于找到玩家手牌中的最长
简单来说就是如果 current_sequence
不为空,那么这一部分代码会检查当前的牌 value
是否能够扩展当前的连续顺子。它通过比较当前牌的值与上一张牌的值来判断是否连续。如果连续,就将当前牌添加到 current_sequence
中。
- else:
- if len(current_sequence) > len(longest_sequence):
- longest_sequence = current_sequence
- current_sequence = [value]
如果当前的牌 value
不与上一张牌连续,那么这一部分代码会检查当前的 current_sequence
是否比之前找到的最长顺子 longest_sequence
更长。如果是,就将 current_sequence
更新为新的最长顺子,并重新开始检查连续顺子。
- # 检查最后一个连续顺子
- if len(current_sequence) > len(longest_sequence):
- longest_sequence = current_sequence
这一部分代码用于检查循环结束后最后一个连续顺子是否比之前找到的最长顺子 longest_sequence
更长。如果是,就将 longest_sequence
更新为新的最长顺子。
- if len(longest_sequence) < 2:
- print("没有找到顺子")
这一行检查最长顺子的长度是否小于2,如果是,则表示没有找到顺子,会打印出相应的消息。
- else:
- # 将顺子的值转换回原始形式
- longest_sequence_values = [card for card in player_hand if card in longest_sequence]
- print(f"最大顺子: {'-'.join(longest_sequence_values)}")
如果找到了顺子,这一部分代码会将顺子的牌值转换回原始形式,并使用 -
连接起来,然后打印出最大顺子的信息。
总的来说,技能3的代码的作用是在玩家手牌中查找最长的连续顺子,并将其输出。它通过将手牌排序并遍历检查连续的牌来实现这一目标。找到最长顺子后,将其转换回原始形式,并打印出来。