本人纯小白,看恶魔游戏里面的五印一当感觉挺有意思挑战做一个。
代码全用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()