【Python】命令行棋牌游戏:十一点

作业需求:
1、生成一副扑克牌(自己设计扑克牌的结构,小王和大王可以分别用14、15表示 )

2、3个玩家(玩家也可以自己定义)
user_list = ["alex","武沛齐","李路飞"]

3、发牌规则
默认先给用户发一张牌,其中 J、Q、K、小王、大王代表的值为0.5,其他就是则就是当前的牌面值。
用户根据自己的情况判断是否继续要牌。
    要,则再给他发一张。(可以一直要牌,但是如果自己手中的牌总和超过11点,你的牌就爆掉了(牌面变成0))
    不要,则开始给下个玩家发牌。(没有牌则则牌面默认是0)
如果用户手中的所有牌相加大于11,则表示爆了,此人的分数为0,并且自动开始给下个人发牌。

4、最终计算并获得每个玩家的分值,例如:
result = {
    "alex":8,
    "武沛齐":9,
    "李路飞":0
}
import random
import os

'''
思路:
    1、初始化卡牌和玩家
    2、进入回合循环
        2.1 是否抽牌,不抽:当前玩家游戏状态=0,为下一个玩家发牌,若此时场内玩家等于1结束游戏,打印结果,否则进入2.2
                      抽:直接进入2.2
        2.2 有无剩余牌,有:进入2.3
                       没有:结束游戏,打印结果
        2.3 当前玩家点数是否>11,是:当前玩家游戏状态=0,若此时场内玩家等于1结束游戏,打印结果,否则重新进入2.1,开始下一回合

- 扑克牌用 字典 存在全局变量 deck 中,key 是牌 ,value 是点数
    - 取牌:random_card = random.choice(list(deck.keys()))
    - 取值:card_value = deck[random_card]

- 玩家信息用列表嵌套字典的方式储存
    - 结构:[ {f'player {i}昵称': player_name, f'player {i}手牌': {}, f'player {i}得分':0.0 ,f'player {i}游戏状态': '1'},
             {f'player {i+1}昵称': player_name, f'player {i+1}手牌': {}, f'player {i+1}得分':0.0 ,f'player {i}游戏状态': '1'} ]
    - 取玩家手牌:current_player_deck = current_player_info[f'player {current_player_index + 1}手牌'] # 回合所在玩家手牌
        current_player_deck 是一个玩家的所有信息:
            {f'player {i}昵称': player_name, f'player {i}手牌': {}, f'player {i}得分':0.0 ,f'player {i}游戏状态': '1'}


'''

# 定义全局变量 DECK
global deck

# 创建一副扑克牌,并为所有牌面赋值
def create_pokers():  
    '''
    输入:空
    返回:一副用字典装的牌,他的值是对应的点数

    思路:
    - 创建一个字典,存放牌和对应的值
    - 向牌中添加内容采用 deck['卡牌名称'] = 对应点数 的方式

    '''
    deck = {}
    # 定义扑克牌的类型和点数
    types = ['♣', '♥', '♦', '♠']
    ranks = ['A','2', '3', '4', '5', '6', '7', '8', '9', '10']
    # 特殊牌面
    special_cards = ['J', 'Q', 'K']  
    Joker = ['Joker1', 'Joker2']
    # 使用嵌套循环来创建每张牌并将其添加到字典中
    for card_type in types:
        # 第一个循环,为普通牌面赋值
        for rank in ranks:
            # 用'f'格式化字符串输出
            card_name = f'{card_type}{rank}'  
            # 特殊情况,type = A
            if rank == 'A':
                card_value = 1.0
                deck[card_name] = card_value  # 将牌添加到字典,包括牌的属性和值
            else:
                card_value = float(rank)
                deck[card_name] = card_value  # 将牌添加到字典,包括牌的属性和值
        # 第二个循环,为J、Q、K赋值
        for rank in special_cards:
            card_name = f'{card_type}{rank}'  # 创建牌的名称
            card_value = 0.5
            deck[card_name] = card_value  # 将牌添加到字典,包括牌的属性和值
    # 为大小王赋值
    for Joker in Joker:
        card_name = f'{Joker}'
        card_value = 0.5
        deck[card_name] = card_value
    return deck


def set_players_num():  # 初始化游戏玩家

    ''' 
    输入:空
    返回:玩家列表

    - 创建一个列表,用来存放所有玩家信息
    [    
        {
            f'player {i}昵称': player_name, 
            f'player {i}手牌': {}, 
            f'player {i}得分':0.0 ,
            f'player {i}游戏状态': '1'
        },{
            f'player {i+1}昵称': player_name, 
            f'player {i+1}手牌': {}, 
            f'player {i+1}得分':0.0 ,
            f'player {i+1}游戏状态': '1'
        },
        
        ...
    ]
    - 添加玩家: players.append(player_information) 
        - 其中 players 是玩家列表,player_information是单个玩家信息的字典,结构为:
        {
            f'player {i}昵称': player_name, 
            f'player {i}手牌': {}, 
            f'player {i}得分':0.0 ,
            f'player {i}游戏状态': '1'
        }
    - 取玩家信息:
        - 取第 n 个玩家昵称: player1_name = players[n-1][f'player {n-1}昵称']
        ...

    '''
    while True:
        players_num = input('请输入玩家人数:')
        players_num = players_num.strip()
        if players_num.isdecimal():
            players_num = int(players_num)
            if int(players_num) < 2:
                print('\n至少需要两名玩家!,重新输入\n')
            else:
                break
        else:
            print('请输入整数')

    players = []  # 创建一个空列表来保存玩家信息
    for i in range(1, players_num + 1):
        while True:
            player_name = input(f'\n玩家{i}/{players_num}的昵称是:')
            if player_name.strip():
                player_information = {f'player {i}昵称': player_name, f'player {i}手牌': {}, f'player {i}得分': 0.0,
                                      f'player {i}游戏状态': '1'}  # 创建包含玩家信息的字典
                players.append(player_information)
                break
            else:
                print('请重新输入')

    # 返回包含玩家信息的列表
    return players


def get_poker(deck, player_deck):  # 发牌
    """
    deck:牌库
    player_deck:玩家手牌库
    """
    # 随机给某个玩家抽牌
    if deck:  # 检查deck是否为空
        random_card = random.choice(list(deck.keys()))
        card_value = deck[random_card]
        print(f'\n抽到了一张:{random_card}')
        del deck[random_card]  # 从牌库中删除抽到的牌
        player_deck[random_card] = card_value  # 将抽到的牌添加到玩家的牌堆
        return True
    else:
        print("扑克牌已经抽完了!游戏结束!")
        input("\n按下任意键继续...")
        return False


def calculate_total_value(player_deck):  # 计算玩家手牌总点数
    '''
    player_deck:玩家手牌库
    '''
    total_value = sum(player_deck.values())
    return total_value


def print_player_decks(current_player_info, index):  # 打印玩家手牌及得分
    '''
        current_player_info:当前玩家的所有信息
        index:回合索引(从0开始)
        '''
    print(f'你的手牌:', end=' ')
    player_deck = current_player_info[f'player {index + 1}手牌']
    card_list_temp = []

    for card, value in player_deck.items():
        card_list_temp.append(card)

    output_string = ' '.join(card_list_temp)

    print(output_string.ljust(30, ' '), end='')  # 打印格式化后的玩家手牌

    total_value = calculate_total_value(player_deck)  # 统计手牌的value和

    formatted_total_value = f'{total_value:.1f}'

    print(formatted_total_value.rjust(4, ' '), end='')

    print('点')

    temp = float(formatted_total_value)
    current_player_info[f'player {index + 1}得分'] = temp


def print_allplayer_decks(players_list):  # 打印所有玩家手牌及得分,找到赢家
    '''
    players_list:所有玩家的信息
    '''
    print('\n\n')
    list_all_players_score = []
    winning_players_names = []  # 用于存储共同获胜的玩家昵称

    for player, index in zip(players_list, range(1, len(players_list) + 1)):

        player_name = next(iter(player.values()))  # 获取玩家的昵称
        player_deck = player[f'player {index}手牌']  # 获取玩家的手牌

        print(f'{player_name}的手牌:', end=' ')
        card_list_temp = []

        for card, value in player_deck.items():
            card_list_temp.append(card)

        output_string = ' '.join(card_list_temp)  # 将玩家手牌格式化为字符串

        print(output_string.ljust(20, ' '), end='')  # 打印格式化后的玩家手牌

        total_value = player[f'player {index}得分']  # 计算玩家总得分
        
        if total_value > 11:
            total_value = 0.0

        list_all_players_score.append(total_value)  # 将玩家得分添加到列表中

        formatted_total_value = f'{total_value:.1f}'  # 格式化成一位小数的字符串

        print(formatted_total_value.rjust(4, ' '), end='')  # 打印玩家得分
        print('点')

    max_score = max(list_all_players_score)

    # 找到最大分值对应的玩家
    winning_players = [index for index, score in enumerate(
        list_all_players_score, start=1) if score == max_score]

    # 打印共同获胜的玩家昵称
    for index in winning_players:
        winning_player_name = next(
            iter(players_list[index - 1].values()))  # 减去1以匹配列表索引
        winning_players_names.append(winning_player_name)

    if len(winning_players) == 1:
        print(f'\n玩家 {winning_players_names[0]} 获胜!,手牌共计{max_score}点')
    else:
        print(f'平局! 共同获胜的玩家: {", ".join(winning_players_names)}')


def count_active_players(players_list):  # 获得游戏状态=1的玩家数
    '''
    players_list:所有玩家的信息
    '''
    count = 0
    for player_info, index in zip(players_list, range(1, len(players_list) + 1)):
        if player_info[f'player {index}游戏状态'] == '1':
            count += 1
    return count


def Round_action(players_list, current_player_index_round, game_continue):  # 上一个玩家选择不要牌后直接为下一个玩家发牌
    '''
    players_list:所有玩家的信息
    current_player_index_round:当前回合的索引(start:0)
    game_continue:游戏状态标识符(=0游戏结束)
    '''
    # 直接复制主函数里的代码
    current_player_info_round = players_list[current_player_index_round]
    current_player_name_round = current_player_info_round[
        f'player {current_player_index_round + 1}昵称']
    print(f'\n轮到玩家{current_player_name_round}')

    if_remain_poker = get_poker(
        deck, current_player_info_round[f'player {current_player_index_round + 1}手牌'])
    print_player_decks(current_player_info_round, current_player_index_round)
    # 判断能否抽到(否表示没牌了)
    if if_remain_poker == True:  # 有剩余
        # 判断该玩家当前分数
        current_player_score = current_player_info_round[
            f'player {current_player_index_round + 1}得分']
        # >11
        if current_player_score > 11.0:
            # 该玩家游戏状态=0,current_player_info[f'player {current_player_index+1}得分']='0''
            current_player_info_round[f'player {current_player_index_round + 1}游戏状态'] = '0'
            current_player_info_round[f'player {current_player_index_round + 1}得分'] = 0.0
            print('你的点数超过11了,最终得分为0!')
            input("\n按下任意键继续...")
            count_players_equal_1 = count_active_players(players_list)
            # 判断游戏状态=1的玩家数,是否>=2
            if count_players_equal_1 >= 2:
                # 是,pass
                pass
            # 否,game_continue=0,游戏结束
            else:
                game_continue = 0
                # <11 pass,继续游戏
        else:
            input("\n按下任意键继续...")
            pass
    return game_continue


if __name__ == '__main__':
    os.system('cls')
    print('\n\n-------------《扑克十一点》-------------\n\n')
    deck = create_pokers()  # 初始化扑克牌
    players_list = set_players_num()  # 初始化玩家
    num_players = len(players_list)  # 获得玩家数量
    current_player_index = 0  # 当前玩家的索引
    game_continue = 1  # 标识符,等于1游戏可以继续

    input('\n按下任意键开始游戏...')
    # 开始游戏,清除终端中的文字
    os.system('cls')

    # 开始抽卡循环  game_continue == 0时break
    while True:
        current_player_info = players_list[current_player_index]  # 回合所在玩家全部信息
        # 回合所在玩家昵称
        current_player_name = current_player_info[f'player {current_player_index + 1}昵称']
        # 回合所在玩家手牌
        current_player_deck = current_player_info[f'player {current_player_index + 1}手牌']

        # 判断游戏状态,=1可以参与本回合
        # 状态=1可以参与本回合
        if current_player_info[f'player {current_player_index + 1}游戏状态'] == '1':
            # TODO 这里放玩家回合内的行动:
            # 是否抽卡
            print(f'\n\n轮到玩家:{current_player_name}\n\n')
            print_player_decks(current_player_info, current_player_index)
            Draw_or_not = input('是否继续抽牌?(输入1:是 其他:否)  ')
            
            # (是否抽卡)是,抽一张
            if Draw_or_not == '1':
                if_remain_poker = get_poker(deck, current_player_deck)
                print_player_decks(current_player_info, current_player_index)
                
                # 判断能否抽到(否表示没牌了)
                if if_remain_poker == True:  # (判断能否抽到)有剩余
                    # 判断该玩家当前分数
                    current_player_score = current_player_info[f'player {current_player_index + 1}得分']
                    
                    # >11
                    if current_player_score > 11.0:  # (是否超11)是
                        # 该玩家游戏状态=0,current_player_info[f'player {current_player_index+1}得分']='0''
                        current_player_info[f'player {current_player_index + 1}游戏状态'] = '0'
                        tempscore = float(0)
                        current_player_info[f'player {current_player_index + 1}得分'] = tempscore
                        print('你的点数超过11了,最终得分为0!')
                        input("\n按下任意键继续...")

                        # 判断游戏状态=1的玩家数,是否 <= 1
                        count_players_equal_1 = count_active_players(
                            players_list)
                        if count_players_equal_1 <= 1:  # <= 1,结束游戏
                            game_continue = 0

                    else:  # (是否超11)否
                        input("\n按下任意键继续...")

                else:  # (判断能否抽到) 无剩余,pass,game_continue=0,游戏结束
                    print('游戏结束!')
                    game_continue = 0

            else:  # (是否抽卡)否,不抽,为下一位玩家发牌
                
                # 该玩家游戏状态=0
                print('玩家选择不再抽牌!')
                # 当前玩家踢出游戏
                current_player_info[f'player {current_player_index + 1}游戏状态'] = '0'
                input("\n按下任意键继续...")

                # 下一位玩家发牌
                os.system('cls')
                print('\n\n上回合玩家选择不抽牌,立即为下一位玩家发牌!')
                current_player_index = (
                    current_player_index + 1) % num_players  # 索引+1
                game_continue = Round_action(
                    players_list, current_player_index, game_continue)  # 不询问直接发牌

                # 判断游戏状态=1的玩家数,是否>=2
                count_players_equal_1 = count_active_players(players_list)
                if count_players_equal_1 <= 1:  # 是,pass
                    print('游戏结束!')
                    game_continue = 0

        # 游戏状态=0,该玩家本轮不行动
        else:
            print(f'\n\n本轮玩家{current_player_name}无法行动')
            print_player_decks(current_player_info, current_player_index)
            input("\n按下任意键继续...")
            pass

            # 增加索引+1,进行下一个玩家回合
        current_player_index = (current_player_index + 1) % num_players

        # 清除终端中的文字
        os.system('cls')
        # 如果游戏结束,退出循环
        if game_continue == 0:
            # 打印游戏结果
            print_allplayer_decks(players_list)
            input("\n按下任意键继续...")
            break

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值