您当前的位置:首页 > 计算机 > 编程开发 > Python

AI做五印一当猜牌游戏Python代码与成品分享

时间:04-26来源:作者:点击数:

本人纯小白,看恶魔游戏里面的五印一当感觉挺有意思挑战做一个。

代码全用ai做的。大约问了30余次完成,基本无bug。电脑猜牌逻辑为随机,正常逻辑太复杂做不出来,希望有大佬解惑。默认玩家先手,更改player_first = True可设置。牌面资源复刻原版。

成品与源码:https://pan.baidu.com/s/1jBeupZ51GyVKNR1SCVAG_A?pwd=rsj2

资源路径说明:

/img(5正面 1背面 1背景 2按钮 共9png)

/music(2音效mp3)

/font(SmileySans-Oblique.ttf)

import pygame
import random
 
pygame.init()
 
window_width = 1600
window_height = 950
screen = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption('五印一当')
 
font_path = resource_path(r'font\SmileySans-Oblique.ttf')
font = pygame.font.Font(font_path, 36)
small_font = pygame.font.Font(font_path, 12)
 
card_original_width = 300
card_original_height = 460
player_card_scale = 0.3
deck_card_scale = 0.2
 
player_card_width = int(card_original_width * player_card_scale)
player_card_height = int(card_original_height * player_card_scale)
deck_card_width = int(card_original_width * deck_card_scale)
deck_card_height = int(card_original_height * deck_card_scale)
 
target_card_width = int(card_original_width * player_card_scale)
target_card_height = int(card_original_height * player_card_scale)
 
open_card_area_width = player_card_width * 3 + 40
open_card_area_height = player_card_height + 10
 
top_open_card_area_x = (window_width - open_card_area_width) / 2 - 100 - 90
top_open_card_area_y = 50
bottom_open_card_area_x = (window_width - open_card_area_width) / 2 - 100 - 90
bottom_open_card_area_y = window_height - open_card_area_height - 50 - 100
player_hand_card_x = bottom_open_card_area_x + open_card_area_width + 40
player_hand_card_y = bottom_open_card_area_y
player_hand_card_positions = [
    (player_hand_card_x, player_hand_card_y),
    (player_hand_card_x + player_card_width + 20, player_hand_card_y),
    (player_hand_card_x + (player_card_width + 20) * 2, player_hand_card_y)
]
computer_hand_card_x = top_open_card_area_x + open_card_area_width + 40
computer_hand_card_y = top_open_card_area_y
computer_hand_card_positions = [
    (computer_hand_card_x, computer_hand_card_y),
    (computer_hand_card_x + player_card_width + 20, computer_hand_card_y),
    (computer_hand_card_x + (player_card_width + 20) * 2, computer_hand_card_y)
]
 
deck_x = (window_width - 4 * deck_card_width) / 3
deck_y = window_height / 3
deck_positions = []
for i in range(2):
    for j in range(4):
        x = deck_x + j * (deck_card_width + 20)
        y = deck_y + i * (deck_card_height + 20)
        deck_positions.append((x, y))
 
target_card_x = (window_width - target_card_width) * 2 / 3
target_card_y = window_height / 3
target_card_position = (target_card_x, target_card_y)
 
button_width = 150
button_height = 70
button_x1 = (window_width - 2 * button_width - 40) / 2
button_y1 = window_height - button_height - 40
button_x2 = button_x1 + button_width + 40
button_y2 = button_y1
button_positions = [
    (button_x1, button_y1),
    (button_x2, button_y2)
]
 
def draw_dashed_rect(surface, color, rect, width=1, dash_length=10, border_radius=20):
    x, y, w, h = rect
    r = border_radius
    for i in range(r, w - r, dash_length * 2):
        pygame.draw.line(surface, color, (x + i, y), (x + i + dash_length, y), width)
    for i in range(r, w - r, dash_length * 2):
        pygame.draw.line(surface, color, (x + i, y + h), (x + i + dash_length, y + h), width)
    for i in range(r, h - r, dash_length * 2):
        pygame.draw.line(surface, color, (x, y + i), (x, y + i + dash_length), width)
    for i in range(r, h - r, dash_length * 2):
        pygame.draw.line(surface, color, (x + w, y + i), (x + w, y + i + dash_length), width)
    for angle in range(180, 270, 10):
        rad = pygame.math.Vector2(r, 0).rotate(angle)
        pygame.draw.circle(surface, color, (int(x + r + rad.x), int(y + r + rad.y)), 1)
    for angle in range(270, 360, 10):
        rad = pygame.math.Vector2(r, 0).rotate(angle)
        pygame.draw.circle(surface, color, (int(x + w - r + rad.x), int(y + r + rad.y)), 1)
    for angle in range(90, 180, 10):
        rad = pygame.math.Vector2(r, 0).rotate(angle)
        pygame.draw.circle(surface, color, (int(x + r + rad.x), int(y + h - r + rad.y)), 1)
    for angle in range(0, 90, 10):
        rad = pygame.math.Vector2(r, 0).rotate(angle)
        pygame.draw.circle(surface, color, (int(x + w - r + rad.x), int(y + h - r + rad.y)), 1)
 
bg_image = pygame.image.load(resource_path(r'img\bg.png'))
bg_image = pygame.transform.scale(bg_image, (window_width, window_height))
 
card_images = {}
for card in ["bm", "em", "fk", "ht", "hx", "mh"]:
    original = pygame.image.load(resource_path(f'img\{card}.png'))
    player_scaled = pygame.transform.smoothscale(
        original,
        (player_card_width, player_card_height)
    )
    deck_scaled = pygame.transform.smoothscale(
        original,
        (deck_card_width, deck_card_height)
    )
    card_images[card] = {
        "original": original,
        "player": player_scaled,
        "deck": deck_scaled
    }
button_images = {
    "normal": pygame.image.load(resource_path(r'img/an1.png')),
    "clicked": pygame.image.load(resource_path(r'img/an2.png'))
}
button_images["normal"] = pygame.transform.smoothscale(button_images["normal"], (button_width, button_height))
button_images["clicked"] = pygame.transform.smoothscale(button_images["clicked"], (button_width, button_height))
 
card_list = ["em", "fk", "ht", "hx", "mh"] * 3
random.shuffle(card_list)
 
all_positions = computer_hand_card_positions + player_hand_card_positions + [target_card_position] + deck_positions
card_assignments = dict(zip(all_positions, card_list))
 
player_first = True  # 可修改为False让电脑先手/True为玩家先手
current_turn = "player" if player_first else "computer"
player_round = 1  # 玩家当前回合
computer_round = 1  # 电脑当前回合
mingpai_used = {"player": False, "computer": False}
has_guessed = False
 
guess_box_width = player_card_width * 5 + 40 + 80
guess_box_height = player_card_height + 40
guess_box_x = (window_width - guess_box_width) / 2
guess_box_y = (window_height - guess_box_height) / 2
guess_box_visible = False
player_is_guessing = False
 
top_open_card_available_positions = [(top_open_card_area_x + i * (player_card_width + 20), top_open_card_area_y) for i
                                     in range(3)]
bottom_open_card_available_positions = [
    (bottom_open_card_area_x + i * (player_card_width + 20), bottom_open_card_area_y) for i in range(3)]
 
selected_player_cards = []
button1_clicked = False
button2_clicked = False
result_box_visible = False
result_text = ""
result_box_width = 660
result_box_height = 150
result_box_x = (window_width - result_box_width) // 2
result_box_y = (window_height - result_box_height) // 2
restart_button_visible = False
restart_button_width = button_width
restart_button_height = button_height
restart_button_x = result_box_x + (result_box_width - restart_button_width) // 2
restart_button_y = result_box_y + result_box_height - restart_button_height - 20 + 50  # 
restart_button_clicked = False
 
card_name_mapping = {
    "em": "恶魔",
    "fk": "方块",
    "ht": "黑桃",
    "hx": "红心",
    "mh": "梅花"
}
 
pygame.mixer.music.load(resource_path(r'music\bgm.mp3')) # 加载背景音乐文件
pygame.mixer.music.set_volume(0.5)  # 设置背景音乐音量(可根据需要调整)
pygame.mixer.music.play(-1)  # 循环播放背景音乐
 
click_sound = pygame.mixer.Sound(resource_path(r'music\yx.mp3'))  # 加载点击音效文件
 
def handle_mingpai(turn):
    global mingpai_used, selected_player_cards
    if (turn == "player" and player_round > 1) or \
            (turn == "computer" and computer_round > 1) or \
            mingpai_used[turn] or has_guessed:
        return
    if turn == "player":
        if not selected_player_cards:
            return
        for card_pos in selected_player_cards:
            card_name = card_assignments[card_pos]
            new_pos = bottom_open_card_available_positions.pop(0)
            card_assignments[new_pos] = card_name
            del card_assignments[card_pos]
            if deck_positions:
                new_deck_pos = random.choice(deck_positions)
                new_card_name = card_assignments[new_deck_pos]
                card_assignments[card_pos] = new_card_name
                del card_assignments[new_deck_pos]
                deck_positions.remove(new_deck_pos)
        selected_player_cards = []
        mingpai_used[turn] = True
    elif turn == "computer":
        num_to_mingpai = random.choice([1, 2, 3])
        selected_cards = random.sample(computer_hand_card_positions, num_to_mingpai)
        for card_pos in selected_cards:
            card_name = card_assignments[card_pos]
            new_pos = top_open_card_available_positions.pop(0)
            card_assignments[new_pos] = card_name
            del card_assignments[card_pos]
            if deck_positions:
                new_deck_pos = random.choice(deck_positions)
                new_card_name = card_assignments[new_deck_pos]
                card_assignments[card_pos] = new_card_name
                del card_assignments[new_deck_pos]
                deck_positions.remove(new_deck_pos)
        mingpai_used[turn] = True
 
def handle_guess(turn):
    global has_guessed, current_turn, result_box_visible, result_text, player_round, computer_round, guess_box_visible, player_is_guessing
    if has_guessed:
        return
    if turn == "player":
        guess_box_visible = True
        player_is_guessing = True
    elif turn == "computer":
        guess_card = random.choice(["em", "fk", "ht", "hx", "mh"])
        target_card = card_assignments[target_card_position]
        if guess_card == target_card:
            result_text = f"对手猜中目标牌为:{card_name_mapping[target_card]},游戏结束"
        else:
            result_text = f"对手猜测目标牌为:{card_name_mapping[guess_card]},猜测错误,游戏继续"
        result_box_visible = True
        has_guessed = guess_card == target_card
        if not has_guessed:
            current_turn = "player"
            computer_round = 2  # 新增行
 
def reset_game():
    global card_list, card_assignments, all_positions, current_turn, player_round, computer_round, mingpai_used, has_guessed, \
        guess_box_visible, result_box_visible, result_text, selected_player_cards, top_open_card_available_positions, bottom_open_card_available_positions, deck_positions, restart_button_visible, player_is_guessing
 
    card_list = ["em", "fk", "ht", "hx", "mh"] * 3
    random.shuffle(card_list)
    deck_positions.clear() 
    for i in range(2):
        for j in range(4):
            x = deck_x + j * (deck_card_width + 20)
            y = deck_y + i * (deck_card_height + 20)
            deck_positions.append((x, y))
    all_positions = computer_hand_card_positions + player_hand_card_positions + [target_card_position] + deck_positions
    card_assignments = dict(zip(all_positions, card_list))
    current_turn = "player" if player_first else "computer"
    player_round = 1
    computer_round = 1
    mingpai_used = {"player": False, "computer": False}
    has_guessed = False
    guess_box_visible = False
    result_box_visible = False
    result_text = ""
    selected_player_cards = []
    restart_button_visible = False
    player_is_guessing = False
 
    top_open_card_available_positions = [(top_open_card_area_x + i * (player_card_width + 20), top_open_card_area_y) for
                                         i in range(3)]
    bottom_open_card_available_positions = [
        (bottom_open_card_area_x + i * (player_card_width + 20), bottom_open_card_area_y) for i in range(3)]
 
def computer_action():
    global current_turn, computer_round, mingpai_used
    if computer_round == 1:
        if random.random() < 0.8:
            handle_mingpai("computer")
            handle_guess("computer")
        else:
            handle_guess("computer")
    else:
        handle_guess("computer")
# 游戏主循环
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y = event.pos
 
            if restart_button_visible and restart_button_x <= mouse_x <= restart_button_x + restart_button_width and restart_button_y <= mouse_y <= restart_button_y + restart_button_height:
                reset_game()
                continue
 
            if guess_box_visible:
                if not (guess_box_x <= mouse_x <= guess_box_x + guess_box_width and guess_box_y <= mouse_y <= guess_box_y + guess_box_height):
                    guess_box_visible = False
                    player_is_guessing = False
                else:
                    card_names = ["em", "fk", "ht", "hx", "mh"]
                    start_x = guess_box_x + (guess_box_width - (player_card_width * 5 + 20 * 4)) // 2
                    start_y = guess_box_y + (guess_box_height - player_card_height) // 2
                    for i, card_name in enumerate(card_names):
                        card_x = start_x + i * (player_card_width + 20)
                        card_y = start_y
                        if card_x <= mouse_x <= card_x + player_card_width and card_y <= mouse_y <= card_y + player_card_height:
                            target_card = card_assignments[target_card_position]
                            if card_name == target_card:
                                result_text = "恭喜你猜中!"
                            else:
                                result_text = f"你猜测目标牌为:{card_name_mapping[card_name]},猜测错误,游戏继续"
                            result_box_visible = True
                            has_guessed = card_name == target_card
                            if not has_guessed:
                                current_turn = "computer"
                                player_round = 2
                            guess_box_visible = False
                            player_is_guessing = False
                            break
            elif result_box_visible:
                result_box_visible = False
                if current_turn == "computer" and not has_guessed:
                    computer_action()
            elif button_x1 <= mouse_x <= button_x1 + button_width and button_y1 <= mouse_y <= button_y1 + button_height:
                if current_turn == "player":
                    button1_clicked = True
                    handle_mingpai("player")
                    click_sound.play()
            elif button_x2 <= mouse_x <= button_x2 + button_width and button_y2 <= mouse_y <= button_y2 + button_height:
                if current_turn == "player" and not player_is_guessing:
                    button2_clicked = True
                    if not has_guessed and not guess_box_visible and not result_box_visible:
                        handle_guess("player")
                        click_sound.play() 
            elif not guess_box_visible and not result_box_visible:
                for pos in player_hand_card_positions:
                    if pos[0] <= mouse_x <= pos[0] + player_card_width and pos[1] <= mouse_y <= pos[1] + player_card_height:
                        if pos in selected_player_cards:
                            selected_player_cards.remove(pos)
                        else:
                            selected_player_cards.append(pos)
        elif event.type == pygame.MOUSEBUTTONUP:
            button1_clicked = False
            button2_clicked = False
 
    screen.fill((150, 120, 50))
    screen.blit(bg_image, (0, 0))
 
    draw_dashed_rect(screen, (255, 255, 255),
                     (top_open_card_area_x, top_open_card_area_y, open_card_area_width, open_card_area_height), width=2,
                     border_radius=20)
    draw_dashed_rect(screen, (255, 255, 255),
                     (bottom_open_card_area_x, bottom_open_card_area_y, open_card_area_width, open_card_area_height),
                     width=2, border_radius=20)
 
    for pos in player_hand_card_positions:
        pygame.draw.rect(screen, (0, 0, 0), (pos[0], pos[1], player_card_width, player_card_height), 2,
                         border_radius=10)
    for pos in computer_hand_card_positions:
        pygame.draw.rect(screen, (0, 0, 0), (pos[0], pos[1], player_card_width, player_card_height), 2,
                         border_radius=10)
    for pos in deck_positions:
        pygame.draw.rect(screen, (0, 0, 0), (pos[0], pos[1], deck_card_width, deck_card_height), 2, border_radius=10)
 
    pygame.draw.rect(screen, (0, 0, 0),
                     (target_card_position[0], target_card_position[1], target_card_width, target_card_height), 2,
                     border_radius=10)
 
    screen.blit(button_images["clicked" if button1_clicked else "normal"], button_positions[0])
    screen.blit(button_images["clicked" if button2_clicked else "normal"], button_positions[1])
 
    texts = [
        ('明牌区', (top_open_card_area_x + open_card_area_width / 2, top_open_card_area_y + open_card_area_height / 2)),
        ('明牌区',
         (bottom_open_card_area_x + open_card_area_width / 2, bottom_open_card_area_y + open_card_area_height / 2)),
        ('电脑', (window_width / 2 + 400, top_open_card_area_y + 80)),  
        ('玩家', (window_width / 2 + 400, bottom_open_card_area_y + 80)), 
        ('牌堆', (deck_x + deck_card_width * 4 / 2 + 30, deck_y - 50)),
        ('目标牌', (target_card_x + target_card_width / 2, target_card_y - 50)),
        ('明牌', (button_positions[0][0] + button_width / 2, button_positions[0][1] + button_height / 2)),
        ('猜牌', (button_positions[1][0] + button_width / 2, button_positions[1][1] + button_height / 2))
    ]
    for text, pos in texts:
        text_surface = font.render(text, True, (255, 255, 255))
        text_rect = text_surface.get_rect(center=pos)
        screen.blit(text_surface, text_rect)
 
    player_visible_positions = player_hand_card_positions + [(top_open_card_area_x, top_open_card_area_y),
                                                             (bottom_open_card_area_x, bottom_open_card_area_y)]
    computer_visible_positions = computer_hand_card_positions + [(top_open_card_area_x, top_open_card_area_y),
                                                                 (bottom_open_card_area_x, bottom_open_card_area_y)]
 
    top_open_card_used_positions = [pos for pos in card_assignments if top_open_card_area_x <= pos[
        0] <= top_open_card_area_x + open_card_area_width and top_open_card_area_y <= pos[
                                        1] <= top_open_card_area_y + open_card_area_height]
    bottom_open_card_used_positions = [pos for pos in card_assignments if bottom_open_card_area_x <= pos[
        0] <= bottom_open_card_area_x + open_card_area_width and bottom_open_card_area_y <= pos[
                                           1] <= bottom_open_card_area_y + open_card_area_height]
 
    for pos, card_name in card_assignments.items():
        is_selected = pos in selected_player_cards
        scale_factor = 1.1 if is_selected else 1
        if pos in deck_positions:
            scaled_width = int(deck_card_width * scale_factor)
            scaled_height = int(deck_card_height * scale_factor)
        else:
            scaled_width = int(player_card_width * scale_factor)
            scaled_height = int(player_card_height * scale_factor)
        if pos in player_visible_positions or pos in top_open_card_used_positions or pos in bottom_open_card_used_positions:
            if pos in deck_positions:
                base_image = card_images[card_name]["deck"]
                base_width = deck_card_width
                base_height = deck_card_height
            else:  
                base_image = card_images[card_name]["player"]
                base_width = player_card_width
                base_height = player_card_height
 
            scaled_width = int(base_width * scale_factor)
            scaled_height = int(base_height * scale_factor)
            if scale_factor != 1:
                scaled_image = pygame.transform.smoothscale(base_image, (scaled_width, scaled_height))
            else:
                scaled_image = base_image
        else:
            scaled_image = pygame.transform.scale(card_images["bm"]["player"], (scaled_width, scaled_height))
        if is_selected:
            pygame.draw.rect(screen, (255, 215, 0), (pos[0] - 5, pos[1] - 5, scaled_width + 1, scaled_height + 1), 3,
                             border_radius=10)
        screen.blit(scaled_image,
                    (pos[0] - (scaled_width - (deck_card_width if pos in deck_positions else player_card_width)) // 2,
                     pos[1] - (scaled_height - (
                         deck_card_height if pos in deck_positions else player_card_height)) // 2))
 
    if guess_box_visible:
        s = pygame.Surface((guess_box_width, guess_box_height), pygame.SRCALPHA)
        s.fill((0, 0, 0, 0))
        pygame.draw.rect(s, (0, 0, 0, 200), (0, 0, guess_box_width, guess_box_height), border_radius=20)  
        screen.blit(s, (guess_box_x, guess_box_y))
        card_names = ["em", "fk", "ht", "hx", "mh"]
        start_x = guess_box_x + (guess_box_width - (player_card_width * 5 + 20 * 4)) // 2
        start_y = guess_box_y + (guess_box_height - player_card_height) // 2
        mouse_x, mouse_y = pygame.mouse.get_pos()
        for i, card_name in enumerate(card_names):
            card_x = start_x + i * (player_card_width + 20)
            card_y = start_y
            is_hovered = card_x <= mouse_x <= card_x + player_card_width and card_y <= mouse_y <= card_y + player_card_height
            scale = 1.1 if is_hovered else 1
            scaled_width = int(player_card_width * scale)
            scaled_height = int(player_card_height * scale)
            scaled_image = pygame.transform.scale(card_images[card_name]["player"], (scaled_width, scaled_height))
            draw_x = card_x - (scaled_width - player_card_width) // 2
            draw_y = card_y - (scaled_height - player_card_height) // 2
            screen.blit(scaled_image, (draw_x, draw_y))
            if is_hovered:
                pygame.draw.rect(screen, (255, 215, 0), (draw_x - 5, draw_y - 5, scaled_width + 10, scaled_height + 10),
                                 3, border_radius=10)
 
    if result_box_visible:
        s = pygame.Surface((result_box_width, result_box_height), pygame.SRCALPHA)
        s.fill((0, 0, 0, 0))
        pygame.draw.rect(s, (0, 0, 0, 200), (0, 0, result_box_width, result_box_height), border_radius=20)
        screen.blit(s, (result_box_x, result_box_y))
        text_x = result_box_x + 20
        text_y = result_box_y + (result_box_height - font.get_height()) // 2
        for card_chinese in card_name_mapping.values():
            if card_chinese in result_text:
                start_idx = result_text.find(card_chinese)
                end_idx = start_idx + len(card_chinese)
                if start_idx > 0:
                    prefix = result_text[0:start_idx]
                    text_surface = font.render(prefix, True, (255, 255, 255))
                    screen.blit(text_surface, (text_x, text_y))
                    text_x += text_surface.get_width()
                text_surface = font.render(card_chinese, True, (255, 100, 100))
                screen.blit(text_surface, (text_x, text_y))
                text_x += text_surface.get_width()
                suffix = result_text[end_idx:]
                text_surface = font.render(suffix, True, (255, 255, 255))
                screen.blit(text_surface, (text_x, text_y))
                break
        else:
            text_surface = font.render(result_text, True, (255, 255, 255))
            screen.blit(text_surface, (text_x, text_y))
        if has_guessed:
            if restart_button_visible:
                screen.blit(button_images["clicked" if restart_button_clicked else "normal"],
                            (restart_button_x, restart_button_y))
            text_surface = font.render("再来一局", True, (255, 255, 255))
            text_rect = text_surface.get_rect(
                center=(restart_button_x + restart_button_width / 2, restart_button_y + restart_button_height / 2))
            screen.blit(text_surface, text_rect)
            restart_button_visible = True
 
    # 电脑先手处理
    if current_turn == "computer" and not has_guessed and computer_round == 1 and not mingpai_used[
        "computer"] and not result_box_visible and not guess_box_visible:
        computer_action()
        current_turn = "player"
 
    pygame.display.flip()
 
pygame.quit()

 

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐