牛牛游戏,本程序中模拟2名玩家参与。游戏的目标是通过比较手中的牌点数来决定胜负。下面是详细的游戏规则说明:
游戏规则
- 牌的点数规则
A(Ace):1点
2-10:牌面点数
J(Jack)、Q(Queen)、K(King):10点 - 牌的花色规则
花色大小顺序为:黑桃(♠)> 红桃(♥)> 梅花(♣)> 方块(♦)
游戏流程
python代码
import random
from itertools import combinations
# 定义牌的数值
NUM_VALUES = {'A': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 'J': 11, 'Q': 12, 'K': 13}
# 定义花色的顺序
FLOWER_ORDER = {'♠': 4, '♥': 3, '♣': 2, '♦': 1}
def gameNiuNiu():
"""
运行牛牛游戏的主要函数。
"""
# ... 游戏逻辑代码 ...
print('-'*15 + ' 牛牛游戏 ' + '-'*15)
print('\t每人发5张牌,若其中三张被10整除的话比较剩余两张跟10取余的大小,')
print('\t若都不能被10整除则取最大的一张牌跟对方比较大小,点数大的赢,若点数相同则比较点数最大牌的花色大小')
print('\tA为1点,JQK为10点,其余按牌面大小计算点数,花色大小为:♠>♥>♣>♦')
print('\t若点数较大的一方点数大于5点,每多一个点数分数加1')
print('\t例如:玩家是牛9,系统是牛6,则玩家得分4(9-5)')
score = 0
cards = generate_deck()
print('-' * 40)
n = get_shuffle_position()
cards = shuffle_cards(cards, n)
player, sysNPC = deal_cards(cards)
print('玩家的牌是:', ' '.join(player))
print('系统的牌是:', ' '.join(sysNPC))
is_win, player_point, sysNPC_point, score = compare_points(player, sysNPC)
print('玩家的结果是:牛', player_point if player_point != 10 else '牛')
print('系统的结果是:牛', sysNPC_point if sysNPC_point != 10 else '牛')
if is_win:
print(f'玩家赢了,得分{score}')
else:
print('系统赢了,得分0')
print('-'*40)
def generate_deck():
"""
生成一副标准的扑克牌。
:return: 包含所有牌的列表,每张牌由花色和数字组成。
"""
flowers = ['♠', '♥', '♣', '♦']
numbers = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
return [flower + number for flower in flowers for number in numbers]
def shuffle_cards(cards, n):
"""
洗牌函数,根据给定的起始位置打乱牌序。
:param cards: 一副牌的列表。
:param n: 开始发牌的位置(整数)。
:return: 根据给定的起始位置重新排列的牌。
"""
random.shuffle(cards)
return cards[n-1:] + cards[:n-1]
def get_shuffle_position():
"""
获取用户输入的洗牌起始位置。
:return: 用户输入的有效位置。
"""
while True:
try:
n = int(input('请输入开始发牌的位置(必须在1到52之间):'))
if 1 <= n <= 52:
return n
else:
print('输入的位置不在1到52之间,请重新输入。')
except ValueError:
print('输入无效,请输入一个整数。')
def deal_cards(cards):
"""
发牌函数,将一副牌分成玩家和系统的手牌。
:param cards: 一副牌的列表。
:return: 包含两个元素的元组,第一个元素是玩家的手牌,第二个元素是系统的手牌。
"""
player = cards[0:10:2]
sysNPC = cards[1:10:2]
return player, sysNPC
def get_point(cards):
"""
计算给定手牌的牛牛点数。
:param cards: 玩家或系统的手牌列表。
:return: 计算得到的牛牛点数。
"""
point_list = [NUM_VALUES[card[1:]] if card[1:] in NUM_VALUES else int(card[1:]) for card in cards]
for comb in combinations(point_list, 3):
if sum(comb) % 10 == 0:
remaining_nums = [x for x in point_list if x not in comb]
return sum(remaining_nums) % 10 if sum(remaining_nums) % 10 != 0 else 10
return 0
def compare_points(player, sysNPC):
"""
比较玩家和系统的牛牛点数,并计算得分。
:param player: 玩家的手牌列表。
:param sysNPC: 系统的手牌列表。
:return: 包含四个元素的元组:是否赢,玩家点数,系统点数,得分。
"""
player_point = get_point(player)
sysNPC_point = get_point(sysNPC)
score = 0
is_win = player_point > sysNPC_point
if is_win and player_point > 5:
score = player_point - 5
elif player_point == sysNPC_point:
score, is_win = compare_hands(player, sysNPC)
return is_win, player_point, sysNPC_point, score
def compare_hands(hand1, hand2):
"""
比较两手牌的大小,用于在点数相同的情况下确定胜者。
:param hand1: 第一手牌列表。
:param hand2: 第二手牌列表。
:return: 包含两个元素的元组:比较结果(True为第一手牌大),最大牌的牌面。
"""
combined_dict = {card: NUM_VALUES[card[1:]] + FLOWER_ORDER[card[0]] for card in hand1 + hand2}
max_card1 = max(combined_dict.values())
max_card2 = max(combined_dict.values(), key=lambda x: (-x, combined_dict.index(x)))
if combined_dict[max_card1] > combined_dict[max_card2]:
return True, max_card1
else:
return False, max_card2
# ... 测试用例代码 ...
if __name__ == '__main__':
gameNiuNiu() # 运行游戏
模块功能说明
1. gameNiuNiu()
这个函数是游戏的入口点,它负责启动游戏流程。首先,它打印出游戏的基本信息和规则,然后生成一副牌,洗牌,发牌,并比较玩家和系统(NPC)的牌点数,最后输出游戏结果。
2. generate_deck()
这个函数生成一副标准的扑克牌,包括所有花色和数值的组合。
flowers = ['♠', '♥', '♣', '♦'] # 定义花色
numbers = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'] # 定义数值
return [flower + number for flower in flowers for number in numbers] # 通过列表推导式生成所有牌的组合
3. shuffle_cards(cards, n)
这个函数用于洗牌,它接受一副牌和一个起始位置,然后根据这个位置对牌进行随机打乱。
random.shuffle(cards) # 随机打乱牌的顺序
return cards[n-1:] + cards[:n-1] # 根据起始位置重新排列牌
4. get_shuffle_position()
这个函数获取用户输入的洗牌起始位置,并确保这个位置是有效的(即在1到52之间)。
while True: # 无限循环直到获得有效输入
try:
n = int(input('请输入开始发牌的位置(必须在1到52之间):')) # 读取用户输入并尝试转换为整数
if 1 <= n <= 52: # 检查输入是否在有效范围内
return n # 如果是,返回这个位置
else:
print('输入的位置不在1到52之间,请重新输入。') # 如果不是,提示用户重新输入
except ValueError: # 如果输入不是整数,则捕获异常
print('输入无效,请输入一个整数。') # 提示用户输入一个有效的整数
5. deal_cards(cards)
这个函数负责发牌,将一副牌分成玩家和系统的手牌,每人5张。
player = cards[0:10:2] # 给玩家发牌,取索引为偶数的牌
sysNPC = cards[1:10:2] # 给系统发牌,取索引为奇数的牌
return player, sysNPC # 返回玩家和系统的手牌
6. get_point(cards)
这个函数计算给定手牌的牛牛点数,根据牛牛游戏的规则,如果三张牌的数值之和能被10整除,则这三张牌的数值之和为10点,剩余两张牌的数值之和为剩余点数。
point_list = [NUM_VALUES[card[1:]] if card[1:] in NUM_VALUES else int(card[1:]) for card in cards] # 将牌转换为数值
for comb in combinations(point_list, 3): # 遍历所有三张牌的组合
if sum(comb) % 10 == 0: # 如果三张牌的数值之和能被10整除
remaining_nums = [x for x in point_list if x not in comb] # 获取剩余的牌
return sum(remaining_nums) % 10 if sum(remaining_nums) % 10 != 0 else 10 # 返回剩余牌的数值之和,如果不能被10整除
return 0 # 如果没有三张牌的数值之和能被10整除,则返回0
7. compare_points(player, sysNPC)
这个函数比较玩家和系统的牛牛点数,并计算得分。
player_point = get_point(player) # 计算玩家的点数
sysNPC_point = get_point(sysNPC) # 计算系统的点数
score = 0 # 初始化得分为0
is_win = player_point > sysNPC_point # 比较点数,确定是否赢
if is_win and player_point > 5: # 如果玩家赢并且点数超过5点
score = player_point - 5 # 计算得分
elif player_point == sysNPC_point: # 如果点数相同
score, is_win = compare_hands(player, sysNPC) # 比较牌面大小和花色
return is_win, player_point, sysNPC_point, score # 返回比较结果
8. compare_hands(hand1, hand2)
这个函数在点数相同的情况下比较两手牌的大小,并确定胜者。
combined_dict = {card: NUM_VALUES[card[1:]] + FLOWER_ORDER[card[0]] for card in hand1 + hand2} # 将牌转换为一个综合数值(数值+花色)
max_card1 = max(combined_dict.values()) # 获取第一手牌中数值最大的牌
max_card2 = max(combined_dict.values(), key=lambda x: (-x, combined_dict.index(x))) # 获取两手牌中数值最大的牌
if combined_dict[max_card1] > combined_dict[max_card2]: # 比较最大牌的数值
return True, max_card1 # 如果第一手牌的大,返回True和最大牌
else:
return False, max_card2 # 否则返回False和第二手牌的最大牌
9. if __name__ == '__main__':
这是Python中的一个常用模式,用于判断当前脚本是否作为主程序运行。如果是,则执行gameNiuNiu()
函数启动游戏。
if __name__ == '__main__':
gameNiuNiu() # 运行游戏
这个脚本通过模拟发牌、计算点数和比较牌的大小来模拟牛牛游戏的过程。用户可以输入开始发牌的位置,然后程序会根据这个位置洗牌、发牌,并输出游戏结果。
测试用例
import unittest
from unittest.mock import patch
from itertools import combinations
import random
# 引入游戏模块的代码
class TestGameNiuNiu(unittest.TestCase):
def setUp(self):
# 在每个测试用例之前设置测试环境
self.deck = generate_deck()
self.shuffle_pos = 27 # 假设用户输入的洗牌起始位置为27
self.cards = shuffle_cards(self.deck, self.shuffle_pos)
self.player, self.sysNPC = deal_cards(self.cards)
def test_generate_deck(self):
# 测试 generate_deck 函数
deck = generate_deck()
self.assertEqual(len(deck), 52)
for card in deck:
self.assertIn(card[0], '♠♥♣♦')
self.assertIn(card[1], 'A23456789TJQK')
def test_shuffle_cards(self):
# 测试 shuffle_cards 函数
original_deck = self.deck.copy()
shuffled_deck = shuffle_cards(original_deck, self.shuffle_pos)
self.assertNotEqual(shuffled_deck, original_deck)
self.assertEqual(len(shuffled_deck), 52)
def test_get_shuffle_position(self):
# 测试 get_shuffle_position 函数
with patch('builtins.input', return_value='27'):
self.assertEqual(get_shuffle_position(), 27)
with patch('builtins.input', side_effect=(ValueError, 'a', '53', '27')):
self.assertEqual(get_shuffle_position(), 27)
def test_deal_cards(self):
# 测试 deal_cards 函数
player, sysNPC = deal_cards(self.cards)
self.assertEqual(len(player), 5)
self.assertEqual(len(sysNPC), 5)
def test_get_point(self):
# 测试 get_point 函数
test_cases = [
(['A', 'A', 'A', '5', 'K'], 0),
(['A', 'A', '10', '5', 'K'], 0),
(['2', '3', '4', '5', '6'], 1),
(['9', '10', 'J', 'Q', 'K'], 10),
(['K', 'Q', 'J', '10', 'A'], 1)
]
for hand, expected in test_cases:
self.assertEqual(get_point(hand), expected)
def test_compare_points(self):
# 测试 compare_points 函数
test_cases = [
([], [], 0, False), # 无效输入
(['A', 'A', 'A', '5', 'K'], ['A', '2', '3', '4', '5'], 0, True), # 玩家赢
(['A', 'A', '10', '5', 'K'], ['A', 'A', 'A', 'K', 'J'], 1, False), # 系统赢
(['A', 'A', 'A', '5', 'K'], ['A', 'A', 'A', '5', 'K'], 0, False) # 点数相同
]
for player_hand, sys_hand, expected_score, expected_win in test_cases:
player_point = get_point(player_hand)
sys_point = get_point(sys_hand)
win, score, _, _ = compare_points(player_hand, sys_hand)
self.assertEqual(win, expected_win)
self.assertEqual(score, expected_score)
def test_compare_hands(self):
# 测试 compare_hands 函数
test_cases = [
(['10', 'J', 'A'], ['A', '2', '3'], True, 'A'), # 玩家最大牌A大于系统2
(['10', 'J', 'A'], ['A', 'K', 'Q'], False, 'A'), # 玩家最大牌A小于系统A
(['10', 'J', 'A'], ['A', 'A', 'A'], True, 'A') # 玩家和系统最大牌相同,但玩家有J
]
for hand1, hand2, expected_win, expected_max_card in test_cases:
win, max_card = compare_hands(hand1, hand2)
self.assertEqual(win, expected_win)
self.assertEqual(max_card, expected_max_card)
if __name__ == '__main__':
unittest.main()
更多问题,可咨询