LapTrinhBlockchain

Chia sẻ kiến thức về Lập Trình Blockchain

Chưa được phân loại

Nghịch lý Monty Hall Monty Hall: Khi cả nghìn Tiến sĩ Toán học bị một người phụ nữ “dạy dỗ”

Cú lừa Monty Hall: Khi cả nghìn Tiến sĩ Toán học bị một người phụ nữ "dạy dỗ"

Cú lừa Monty Hall: Khi cả nghìn Tiến sĩ Toán học bị một người phụ nữ "dạy dỗ"

Chia sẻ bài viết
5
(68)

Bạn tự tin bản thân là người sống lý trí và có tư duy logic tốt? Vậy hãy thử trả lời một câu hỏi: Nếu bạn đang đứng trước 3 cánh cửa, 1 bên là siêu xe, 2 bên là con dê vô giá trị. Sau khi bạn chọn cửa số 1, MC loại bỏ một cánh cửa có dê và hỏi bạn: “Có muốn đổi sang cửa còn lại không? Bộ não bạn sẽ lập tức hét lên: “Đổi hay giữ thì tỷ lệ vẫn là 50/50, khác gì nhau!”. Nhưng sự thật phũ phàng là: Nếu bạn giữ nguyên, bạn nắm chắc phần thua.

Câu chuyện điên rồ đằng sau bài toán Monty Hall này từng khiến 1.000 Tiến sĩ toán học phải muối mặt thừa nhận: Trực giác của con người hoàn toàn là một cú lừa!

Kịch bản Monty Hall

Đây là kịch bản của bài toán xác suất nổi tiếng mang tên Kịch bản Monty Hall (Monty Hall Problem). Bài toán này dựa trên trò chơi truyền hình thực tế của Mỹ mang tên Let’s Make a Deal.

  • Kịch bản
    • 3 cánh cửa đóng kín.
    • Phía sau 1 cánh cửa là một chiếc ô tô (phần thưởng lớn).
    • Phía sau 2 cánh cửa còn lại là con dê (phần thưởng vô giá trị).
  • Cách thức chơi:
    • Bạn chọn: Bạn chỉ định cửa số 1 (cơ hội trúng lúc này là 1/3).
    • Người dẫn chương trình (MC) hành động: MC biết rõ bí mật sau các cánh cửa. Ông ấy mở cửa số 3 và cho thấy một con dê.
    • Tình huống quyết định: Chỉ còn lại cửa số 1 (bạn chọn) và cửa số 2. MC hỏi: “Bạn có muốn đổi sang cửa số 2 không?”
  • Phân tích Xác suất Thực tế:
    Hầu hết mọi người nghĩ giữ nguyên hay đổi thì tỷ lệ thắng vẫn là 50/50. Thực tế toán học chứng minh điều ngược lại.
    • Nếu bạn GIỮ NGUYÊN lựa chọn ban đầu: Tỷ lệ thắng của bạn chỉ là 1/3.
    • Nếu bạn THAY ĐỔI lựa chọn: Tỷ lệ thắng của bạn tăng vọt lên 2/3.
  • Tại sao nên Đổi?
    • Ở bước 1, tỷ lệ bạn chọn sai (chọn trúng con dê) lên tới 2/3.
    • Nếu bạn chọn sai ở bước 1, khi MC mở con dê còn lại => Cánh cửa còn lại cuối cùng chắc chắn là chiếc ô tô.
    • Do đó, chiến thuật luôn luôn đổi biến xác suất chọn sai ban đầu (2/3) thành xác suất trúng ô tô.

Câu chuyện đằng sau Bài toán Monty Hall

Câu chuyện đằng sau Bài toán Monty Hall thực sự là một trong những vết bầm lớn nhất lịch sử toán học hiện đại. Nó chứng minh một sự thật phũ phàng: Trực giác của con người vô cùng tệ trước các con số, và ngay cả những bộ óc vĩ đại nhất cũng có thể bị đánh lừa.

Người phụ nữ thông minh nhất thế giới

Năm 1990, một độc giả đã gửi câu hỏi về trò chơi chọn cửa này đến mục giải đáp “Ask Marilyn” của tạp chí Parade. Người phụ trách mục này là Marilyn vos Savant – người lúc đó đang nắm giữ kỷ lục Guinness là “Người có chỉ số IQ cao nhất thế giới” (IQ 228).

Marilyn trả lời rất ngắn gọn: Bạn bắt buộc phải đổi, vì tỷ lệ thắng khi đổi là 2/3, còn giữ nguyên chỉ là 1/3.

Làn sóng phẫn nộ và cơn bão 10.000 lá thư

Ngay sau khi bài báo phát hành, một làn sóng giận dữ chưa từng có bùng lên. Marilyn nhận về hơn 10.000 lá thư chỉ trích, trong đó có gần 1.000 bức thư đến từ các Tiến sĩ toán học và khoa học. Tất cả họ đều khẳng định bà sai.

Họ lập luận bằng trực giác cơ bản: “Khi chỉ còn 2 cánh cửa, tỷ lệ chia đều là 50/50. Đổi hay không đổi chẳng khác gì nhau.”. Các chuyên gia thậm chí còn dùng những lời lẽ vô cùng nặng nề và ngạo mạn để mỉa mai bà:

“Bà đã sai hoàn toàn!… Có vẻ như phụ nữ nhìn nhận các bài toán xác suất khác với nam giới.” – Tiến sĩ Scott Smith.

“Là một nhà toán học chuyên nghiệp, tôi rất lo ngại về sự thiếu hiểu biết toán học của công chúng. Xin bà hãy sửa sai bằng cách thừa nhận lỗi lầm của mình!” – Tiến sĩ Robert Sachs (Đại học George Mason).

“Nếu tất cả những Tiến sĩ này sai, thì quốc gia này đang rơi vào khủng hoảng giáo dục nghiêm trọng!” – Một lá thư khác châm biếm.

Cú lừa đối với “Vua Toán Học” Paul Erdős

Không chỉ các tiến sĩ gửi thư, ngay cả Paul Erdős – một trong những nhà toán học lỗi lạc và có nhiều công trình xuất bản nhất thế kỷ 20 – khi nghe bài toán này cũng khẳng định Marilyn đã sai.

Khi các đồng nghiệp giải thích bằng lý thuyết xác suất, Erdős vẫn lắc đầu từ chối tin vào kết quả 2/3. Chỉ đến vài ngày sau, khi một người bạn lập trình một đoạn code mô phỏng máy tính và chạy thử hàng nghìn lần, nhìn thấy tận mắt con số hiển thị ~66.7%, vị vua toán học mới chịu khuất phục và thừa nhận mình đã nhầm lẫn.

Cái kết và bài học lịch sử

Marilyn vos Savant không hề nao núng. Ở kỳ báo tiếp theo, bà không dùng công thức phức tạp nữa mà yêu cầu các trường học trên khắp nước Mỹ cùng làm một thí nghiệm nhỏ: Lấy 3 chiếc cốc, giấu một đồng xu bên dưới và tự chơi thử mô phỏng bằng tay.

Hàng trăm lớp học đã gửi kết quả về: Chiến thuật đổi luôn luôn thắng khoảng 66.7%. Các giáo sư toán học muối mặt viết thư xin lỗi Marilyn.

Vị Tiến sĩ Robert Sachs từng mắng bà thậm tệ đã phải gửi một lá thư xoa dịu: “Sau khi bị nuốt chửng bởi sự ngạo mạn của chính mình, tôi đã tự tính lại và nhận ra bà hoàn toàn đúng.”

Viết code Python mô phỏng bài toán và kiểm chứng kết quả

Bạn có thể dễ dàng nhờ Gemini hay bất kỳ AI nào giúp bạn viết code để kiểm chứng bài toán này.

Dưới đây là đoạn code Python tối ưu để mô phỏng trò chơi Monty Hall 10.000 lần. Bạn dễ dàng chạy thử code trên Programiz:

import random

def simulate_monty_hall(simulations=10000):
    stay_wins = 0
    switch_wins = 0
    
    for _ in range(simulations):
        # 3 cánh cửa: 0, 1, 2
        doors = [0, 1, 2]
        
        # Ngẫu nhiên vị trí ô tô và lựa chọn ban đầu của người chơi
        car_door = random.randint(0, 2)
        player_choice = random.randint(0, 2)
        
        # MC mở cửa có con dê (không phải cửa xe, không phải cửa người chơi chọn)
        host_can_open = [d for d in doors if d != player_choice and d != car_door]
        host_reveals = random.choice(host_can_open)
        
        # Cánh cửa còn lại nếu người chơi quyết định ĐỔI
        switch_choice = [d for d in doors if d != player_choice and d != host_reveals][0]
        
        # Tính toán kết quả
        if player_choice == car_door:
            stay_wins += 1
        if switch_choice == car_door:
            switch_wins += 1
            
    # Hiển thị kết quả ra màn hình
    print(f"Kết quả sau {simulations:,} lần mô phỏng:")
    print(f" - GIỮ NGUYÊN lựa chọn: {stay_wins} lần ({stay_wins/simulations:.2%})")
    print(f" - THAY ĐỔI lựa chọn: {switch_wins} lần ({switch_wins/simulations:.2%})")

# Chạy mô phỏng
simulate_monty_hall()

Tôi đã thử chạy đi chạy lại nhiều lần, kết quả đều ~67%:

Kết quả mô phỏng bài toán Monty Hall

Chúng ta có thể sửa code sử dụng thư viện matplotlib để hiển thị kết quả dưới dạng trực quan hơn. Code này yêu cầu bạn phải cài đặt thêm thư viện matplotlib bằng lệnh:

pip3 install matplotlib

Chi tiết code như sau:

import random
import matplotlib.pyplot as plt

def simulate_monty_hall_with_chart(simulations=10000):
    stay_wins = 0
    switch_wins = 0
    
    for _ in range(simulations):
        doors = [0, 1, 2]
        car_door = random.randint(0, 2)
        player_choice = random.randint(0, 2)
        
        host_can_open = [d for d in doors if d != player_choice and d != car_door]
        host_reveals = random.choice(host_can_open)
        
        switch_choice = [d for d in doors if d != player_choice and d != host_reveals][0]
        
        if player_choice == car_door:
            stay_wins += 1
        if switch_choice == car_door:
            switch_wins += 1
            
    # Tính toán tỷ lệ phần trăm
    stay_percentage = (stay_wins / simulations) * 100
    switch_percentage = (switch_wins / simulations) * 100
    
    # Cấu hình dữ liệu biểu đồ
    strategies = ['Giữ nguyên lựa chọn', 'Thay đổi lựa chọn']
    percentages = [stay_percentage, switch_percentage]
    colors = ['#ff6b6b', '#4cd137'] # Đỏ cho giữ nguyên, Xanh lá cho thay đổi
    
    # Khởi tạo khung vẽ
    plt.figure(figsize=(8, 6))
    bars = plt.bar(strategies, percentages, color=colors, width=0.5)
    
    # Hiển thị số liệu phần trăm chính xác trên đầu mỗi cột
    for bar in bars:
        height = bar.get_height()
        plt.text(bar.get_x() + bar.get_width()/2., height + 1.5,
                 f'{height:.2f}%',
                 ha='center', va='bottom', fontsize=12, fontweight='bold')
                 
    # Cài đặt tiêu đề và nhãn tọa độ
    plt.title(f'Mô phỏng bài toán Monty Hall ({simulations:,} lần chạy)', fontsize=14, fontweight='bold', pad=20)
    plt.ylabel('Tỷ lệ chiến thắng (%)', fontsize=12)
    plt.ylim(0, 100) # Giới hạn trục Y từ 0 đến 100%
    plt.grid(axis='y', linestyle='--', alpha=0.5) # Đường lưới ngang mờ
    
    # Hiển thị biểu đồ
    plt.tight_layout()
    plt.show()

# Chạy mô phỏng và vẽ biểu đồ
simulate_monty_hall_with_chart()

Kết quả chạy như sau:

Kết quả mô phỏng bài toán Monty Hall

Tạo trò chơi từ Nghịch lý Monty Hall

Từ nghịch lý Monty Hall ở trên, chúng ta sẽ xây dựng một trò chơi có tên: “Trò chơi của kẻ phán xét“.

Kịch bản: Trò chơi của Kẻ phán xét

  • Thể loại: Giật gân, Tâm lý học, Sinh tồn.
  • Bối cảnh: Một căn phòng tối tối giản. Ở giữa có 3 cánh cửa sắt khổng lồ được đánh số 1, 2, 3.
  • Nhân vật:
    • Khánh: Người chơi. Một gã đàn ông nợ nần, đang tìm cơ hội đổi đời.
    • Quản trò (The Host): Một thực thể đeo mặt nạ cười, giọng nói méo mó qua loa phóng thanh. Kẻ nắm rõ bí mật sau các cánh cửa.

🎬 PHÂN CẢNH 1: LỰA CHỌN ĐẦU TIÊN

(Tiếng xích sắt nặng nề kéo lên. Ba cánh cửa phát ra ánh sáng đèn neon đỏ rực).

  • Quản trò: “Chào mừng đến với vòng chung kết, Khánh. Luật chơi rất đơn giản. Sau một trong ba cánh cửa này là 10 triệu USD tiền mặt. Sau hai cánh cửa còn lại… là hố chông chết chóc. Cơ hội là 1/3. Chọn đi.”
  • Khánh: (Mồ hôi chảy ròng ròng, nhìn chằm chằm vào các con số. Trực giác mách bảo gã chọn con số may mắn của mình). “Tôi chọn… Cửa số 1!
  • Quản trò: “Cửa số 1 đã được khóa lại cho cậu. Cậu có chắc chắn với lựa chọn trị giá 1/3 cơ hội sống sót này không?”
  • Khánh: (Nghiến răng) “Tôi chắc chắn.”

🎬 PHÂN CẢNH 2: SỰ CAN THIỆP CỦA KẺ BIẾT TRƯỚC

(Tiếng cười rùng rợn của Quản trò vang lên qua loa).

  • Quản trò: “Tốt lắm. Nhưng trò chơi của tôi không kết thúc tẻ nhạt như vậy. Để tăng phần kịch tính, tôi – kẻ biết rõ thần chết đang ẩn nấp ở đâu – sẽ giúp cậu loại bỏ một mối nguy hiểm.”

(RẦM! Cánh cửa số 3 tự động mở toang. Bên trong là một hố chông nhọn hoắt, nhuốm máu).

  • Khánh: (Rùng mình, thở phào nhẹ nhõm) “May quá… không phải cửa mình chọn.”
  • Quản trò: “Bây giờ, cuộc chơi chỉ còn lại Cửa số 1 cậu đang giữ, và Cửa số 2 đang đóng chặt. Một bên là thiên đường, một bên là địa ngục.”

🎬 PHÂN CẢNH 3: ĐIỂM QUYẾT ĐỊNH (NÚT THẮT TÂM LÝ)

(Tiếng đồng hồ đếm ngược vang lên: Tách… Tách… Tách…)

  • Quản trò: “Khánh. Tôi cho cậu một cơ hội cuối cùng để thay đổi số phận. Cậu muốn GIỮ NGUYÊN cửa số 1, hay THAY ĐỔI sang cửa số 2?
  • Khánh: (Suy nghĩ điên cuồng): “Bây giờ chỉ còn 2 cửa. Tỷ lệ là 50/50. Nếu mình đổi mà lại trúng hố chông, mình sẽ hận bản thân cả đời. Giữ nguyên vẫn an toàn hơn. Nhưng tại sao gã lại cho mình đổi? Gã đang dụ mình từ cửa Đúng sang cửa Sai, hay gã đang thương hại mình?”

🎮 CÁC LỰA CHỌN CỦA NGƯỜI CHƠI (PLAYER CHOICES)

🛑 LỰA CHỌN A: GIỮ NGUYÊN CỬA SỐ 1 (Chiến thuật dựa vào trực giác)

  • Diễn biến: Khánh hét lớn: “Tôi giữ nguyên! Tôi tin vào lựa chọn đầu tiên của mình!”
  • Kết cục: Cửa số 1 mở ra. Một dàn chông sập xuống. Khánh gục ngã. Tiếng Quản trò cười lớn: “Đáng thương thay cho kẻ tin vào trực giác. Tỷ lệ thắng của ngươi ngay từ đầu đã cố định là 1/3. Khi ta mở cửa số 3, xác suất 2/3 sai lầm đã dồn hết sang cửa số 2. Ngươi vừa từ chối cơ hội sống sót lớn gấp đôi chỉ vì sự bướng bỉnh.”
  • GAME OVER.

🔄 LỰA CHỌN B: THAY ĐỔI SANG CỬA SỐ 2 (Chiến thuật dựa vào toán học)

  • Diễn biến: Khánh nhớ lại một bài toán xác suất từng đọc trên mạng. Gã gạt đi nỗi sợ hãi, nhìn thẳng vào mặt nạ của Quản trò: “Tôi ĐỔI sang cửa số 2!”
  • Kết cục: Cửa số 1 mở ra trước, để lộ hố sâu hoắm. Khánh đứng tim. Ngay sau đó, cửa số 2 từ từ hé lộ các cọc tiền USD cao ngất ngưởng.
  • Quản trò: (Vỗ tay trầm trồ) “Xuất sắc. Cậu là người hiếm hoi chiến thắng được nỗi sợ hãi của bộ não. Bằng cách thay đổi, cậu đã biến 2/3 tỷ lệ chọn sai ban đầu thành tỷ lệ chiến thắng.”
  • YOU WIN!

Mã nguồn bằng Python của “Trò chơi của Kẻ phán xét”

Bây giờ, bạn vào trang web Online Python, copy mã nguồn bên dưới và chạy thử:

import random
import time
import sys

def type_effect(text, speed=0.03):
    """Tạo hiệu ứng gõ chữ từng ký tự để tăng tính kịch tính"""
    for char in text:
        sys.stdout.write(char)
        sys.stdout.flush()
        time.sleep(speed)
    print()

def play_game():
    # Khởi tạo bối cảnh
    print("=" * 60)
    type_effect("⚡ TRÒ CHƠI CỦA KẺ PHÁN XÉT - NGHỊCH LÝ MONTY HALL ⚡", 0.02)
    print("=" * 60)
    time.sleep(1)
    
    type_effect("\n[Bối cảnh]: Bạn tỉnh dậy trong một căn phòng tối tăm, nồng nặc mùi sắt rỉ.")
    type_effect("Trước mặt bạn là 3 cánh cửa khổng lồ được đánh số: [1], [2], [3].")
    type_effect("Một giọng nói méo mó, lạnh lẽo vang lên từ chiếc loa phóng thanh treo trên trần...\n")
    time.sleep(1.5)
    
    type_effect("Quản trò: 'Chào mừng Khánh. Sau một trong ba cánh cửa kia là 10 TRIỆU USD.'")
    type_effect("Quản trò: 'Sau hai cánh cửa còn lại... là HỐ CHÔNG CHẾT CHÓC. Cơ hội sống là 1/3.'")
    type_effect("Quản trò: 'Hãy đưa ra lựa chọn đầu tiên của ngươi!'")
    
    # Bước 1: Người chơi chọn cửa ban đầu
    doors = [1, 2, 3]
    car_door = random.randint(1, 3) # Vị trí phần thưởng thực tế
    
    while True:
        try:
            player_choice = int(input("\n👉 Nhập số cánh cửa bạn chọn (1, 2 hoặc 3): "))
            if player_choice in doors:
                break
            print("Cửa không hợp lệ! Chỉ chọn 1, 2 hoặc 3.")
        except ValueError:
            print("Vui lòng chỉ nhập số ký tự từ 1 đến 3.")
            
    type_effect(f"\nKhánh: 'Tôi chọn... Cánh cửa số {player_choice}!'")
    type_effect(f"Quản trò: 'Cửa số {player_choice} đã được khóa. Lựa chọn mang tỷ lệ thắng 1/3.'")
    time.sleep(1.5)
    
    # Bước 2: MC mở một cánh cửa sai (chứa chông / dê)
    # MC phải mở cửa KHÔNG PHẢI cửa người chơi chọn và KHÔNG PHẢI cửa có xe
    host_can_open = [d for d in doors if d != player_choice and d != car_door]
    host_reveals = random.choice(host_can_open)
    
    type_effect("\n*RẦM!!!* Tiếng xích sắt nặng nề kéo lên...")
    type_effect(f"Cánh cửa số {host_reveals} tự động mở toang. Bên dưới là một hố chông nhọn hoắt nhuốm máu!")
    type_effect("Khánh rùng mình, tim đập loạn nhịp vì nhận ra mình vừa thoát chết trong gang tấc.")
    time.sleep(1.5)
    
    # Bước 3: Đưa ra lựa chọn quyết định (Giữ nguyên hay Thay đổi)
    remaining_door = [d for d in doors if d != player_choice and d != host_reveals][0]
    
    type_effect(f"\nQuản trò bước đến, chiếc mặt nạ cười nhìn chằm chằm vào bạn...")
    type_effect(f"Quản trò: 'Bây giờ, chỉ còn lại Cửa số [{player_choice}] ngươi đang chọn và Cửa số [{remaining_door}].'")
    type_effect("Quản trò: 'Ta cho ngươi một cơ hội cuối cùng để viết lại số phận...'")
    type_effect(f"Quản trò: 'Ngươi muốn GIỮ NGUYÊN cửa số {player_choice} hay THAY ĐỔI sang cửa số {remaining_door}?'")
    
    while True:
        decision = input("\n👉 Nhập [G] để GIỮ NGUYÊN hoặc [D] để THAY ĐỔI: ").strip().upper()
        if decision in ['G', 'D']:
            break
        print("Lựa chọn không hợp lệ! Chỉ gõ G hoặc D.")
        
    # Áp dụng logic thay đổi lựa chọn
    if decision == 'D':
        player_choice = remaining_door
        type_effect(f"\nKhánh nghiến răng, gạt đi nỗi sợ hãi: 'Tôi quyết định... ĐỔI sang cửa số {player_choice}!'")
    else:
        type_effect(f"\nKhánh đổ mồ hôi hột, ôm chặt lấy cột mốc: 'Tôi giữ vững lập trường! Không đổi!'")
        
    time.sleep(2)
    type_effect("\nQuản trò: 'Quyết định cuối cùng đã được ghi nhận. Hãy xem thần chết gọi tên ai...'")
    print("\n*3...*")
    time.sleep(1)
    print("*2...*")
    time.sleep(1)
    print("*1...*\n")
    time.sleep(1)
    
    # Bước 4: Kiểm tra kết quả chung cuộc
    if player_choice == car_door:
        print("🎉" * 20)
        type_effect(f"KẾT CỤC: Cửa số {player_choice} mở ra... Ánh đèn vàng rực rỡ chiếu sáng hàng triệu cọc tiền USD!")
        type_effect("Quản trò hét lên qua loa: 'XUẤT SẮC! Ngươi đã chiến thắng trò chơi của ta!'")
        if decision == 'D':
            type_effect("Quản trò: 'Bằng cách chọn THAY ĐỔI, ngươi đã nâng tỷ lệ thắng từ 33.3% lên 66.7%! Toán học đã cứu mạng ngươi!'")
        else:
            type_effect("Quản trò: 'Ngươi cực kỳ may mắn khi trúng vào ô 33.3% ít ỏi đó! Thần may mắn đã mỉm cười với ngươi hôm nay.'")
        print("🎉" * 20)
    else:
        print("💀" * 20)
        type_effect(f"KẾT CỤC: Cửa số {player_choice} sập xuống... Hệ thống chông nhọn hoắt từ trần nhà đâm thẳng xuống vị trí của bạn!")
        type_effect("Quản trò cười lớn đầy man rợ: 'Hahaha! GAME OVER!'")
        if decision == 'G':
            type_effect(f"Quản trò: 'Đáng thương cho kẻ tin vào trực giác. Lẽ ra ngươi nên ĐỔI sang cửa số {car_door} để tăng gấp đôi cơ hội sống!'")
        else:
            type_effect(f"Quản trò: 'Đen đủi thay, lựa chọn đầu tiên của ngươi đã trúng ngay cửa an toàn, nhưng việc ĐỔI CỬA xui xẻo đã hại ngươi.'")
        print("💀" * 20)

# Khởi chạy trò chơi
if __name__ == "__main__":
    play_game()
Phiên bản 1 "Trò chơi của Kẻ phán xét"

Phiên bản đồ họa trực quan của “Trò chơi của Kẻ phán xét”

import tkinter as tk
from tkinter import messagebox
import random

class MontyHallGame:
    def __init__(self, root):
        self.root = root
        self.root.title("Trò chơi Monty Hall - Kẻ Phán Xét")
        self.root.geometry("600x450")
        self.root.configure(bg="#2c3e50")

        # Khởi tạo trạng thái game
        self.doors = [1, 2, 3]
        self.car_door = random.randint(1, 3)
        self.player_choice = None
        self.host_revealed = None
        self.game_stage = "CHỌN_CỬA" # Các giai đoạn: CHỌN_CỬA, QUYẾT_ĐỊNH, KẾT_THÚC

        # Thành phần giao diện
        self.create_widgets()

    def create_widgets(self):
        # Tiêu đề chính
        self.title_label = tk.Label(
            self.root, text="TRÒ CHƠI CỦA KẺ PHÁN XÉT", 
            font=("Helvetica", 18, "bold"), fg="#1abc9c", bg="#2c3e50"
        )
        self.title_label.pack(pady=15)

        # Hướng dẫn người chơi
        self.status_label = tk.Label(
            self.root, text="Hãy chọn 1 trong 3 cánh cửa bên dưới để tìm Ô tô 🚗", 
            font=("Helvetica", 12), fg="#ecf0f1", bg="#2c3e50", wraplength=500
        )
        self.status_label.pack(pady=10)

        # Khung chứa 3 cánh cửa
        self.door_frame = tk.Frame(self.root, bg="#2c3e50")
        self.door_frame.pack(pady=20)

        self.door_buttons = {}
        for i in range(1, 4):
            btn = tk.Button(
                self.door_frame, text=f"Cửa\n{i}", font=("Helvetica", 14, "bold"),
                width=10, height=5, bg="#34495e", fg="#ffffff",
                activebackground="#16a085", activeforeground="#ffffff",
                command=lambda num=i: self.select_door(num)
            )
            btn.pack(side=tk.LEFT, padx=15)
            self.door_buttons[i] = btn

        # Khung điều khiển (Nút Đổi / Giữ / Chơi lại)
        self.control_frame = tk.Frame(self.root, bg="#2c3e50")
        self.control_frame.pack(pady=15)

        self.btn_stay = tk.Button(
            self.control_frame, text="GIỮ NGUYÊN", font=("Helvetica", 12, "bold"),
            bg="#e74c3c", fg="white", width=12, state=tk.DISABLED, command=self.action_stay
        )
        self.btn_stay.pack(side=tk.LEFT, padx=10)

        self.btn_switch = tk.Button(
            self.control_frame, text="THAY ĐỔI", font=("Helvetica", 12, "bold"),
            bg="#2ecc71", fg="white", width=12, state=tk.DISABLED, command=self.action_switch
        )
        self.btn_switch.pack(side=tk.LEFT, padx=10)

        self.btn_reset = tk.Button(
            self.root, text="Chơi Lại Vòng Mới 🔁", font=("Helvetica", 11),
            bg="#f1c40f", fg="#2c3e50", width=18, command=self.reset_game
        )
        self.btn_reset.pack(pady=10)

    def select_door(self, num):
        if self.game_stage != "CHỌN_CỬA":
            return

        self.player_choice = num
        self.door_buttons[num].configure(bg="#2980b9", text=f"Cửa {num}\n(Bạn chọn)")

        # MC mở cửa có dê (không phải cửa người chơi, không phải cửa ô tô)
        host_can_open = [d for d in self.doors if d != self.player_choice and d != self.car_door]
        self.host_revealed = random.choice(host_can_open)

        # Hiển thị cửa MC mở
        self.door_buttons[self.host_revealed].configure(bg="#95a5a6", text=f"Cửa {self.host_revealed}\nCon dê 🐐", state=tk.DISABLED)

        # Chuyển giai đoạn, kích hoạt nút bấm quyết định
        self.game_stage = "QUYẾT_ĐỊNH"
        self.status_label.configure(
            text=f"MC đã mở cửa {self.host_revealed} là Con dê 🐐.\nBạn muốn GIỮ NGUYÊN hay THAY ĐỔI lựa chọn?"
        )
        self.btn_stay.configure(state=tk.NORMAL)
        self.btn_switch.configure(state=tk.NORMAL)

    def action_stay(self):
        self.reveal_final_result(self.player_choice, "GIỮ NGUYÊN")

    def action_switch(self):
        # Lấy cánh cửa còn lại duy nhất
        remaining_door = [d for d in self.doors if d != self.player_choice and d != self.host_revealed][0]
        self.reveal_final_result(remaining_door, "THAY ĐỔI")

    def reveal_final_result(self, final_choice, strategy_name):
        self.game_stage = "KẾT_THÚC"
        self.btn_stay.configure(state=tk.DISABLED)
        self.btn_switch.configure(state=tk.DISABLED)

        # Mở tất cả các cửa để hiển thị kết quả
        for d in self.doors:
            if d == self.car_door:
                self.door_buttons[d].configure(bg="#2ecc71", text=f"Cửa {d}\nÔ tô 🚗")
            else:
                if d != self.host_revealed:
                    self.door_buttons[d].configure(bg="#e74c3c", text=f"Cửa {d}\nCon dê 🐐")

        # Hiển thị thông báo hộp thoại kết quả
        if final_choice == self.car_door:
            msg = f"Chúc mừng! Bạn chọn {strategy_name} và trúng Ô tô 🚗!\nToán học chứng minh chiến thuật ĐỔI CỬA mang lại 66.7% chiến thắng."
            messagebox.showinfo("CHIẾN THẮNG! 🎉", msg)
            self.status_label.configure(text="Bạn đã THẮNG phần thưởng lớn! Đỉnh cao trí tuệ! 😎")
        else:
            msg = f"Rất tiếc! Bạn chọn {strategy_name} và dính phải Con dê 🐐.\nLưu ý: Luôn ĐỔI CỬA sẽ cho bạn tỷ lệ thắng gấp đôi (2/3) đó!"
            messagebox.showerror("THẤT BẠI! 💀", msg)
            self.status_label.configure(text="Bạn đã THUA cuộc. Thử lại để chứng minh xác suất toán học nhé!")

    def reset_game(self):
        self.car_door = random.randint(1, 3)
        self.player_choice = None
        self.host_revealed = None
        self.game_stage = "CHỌN_CỬA"
        
        self.status_label.configure(text="Hãy chọn 1 trong 3 cánh cửa bên dưới để tìm Ô tô 🚗")
        self.btn_stay.configure(state=tk.DISABLED)
        self.btn_switch.configure(state=tk.DISABLED)

        for i in range(1, 4):
            self.door_buttons[i].configure(bg="#34495e", text=f"Cửa\n{i}", state=tk.NORMAL)

if __name__ == "__main__":
    root = tk.Tk()
    game = MontyHallGame(root)
    root.mainloop()
Phiên bản đồ họa "Trò chơi của Kẻ phán xét"

Bài viết này có hữu ích với bạn?

Kích vào một biểu tượng ngôi sao để đánh giá bài viết!

Xếp hạng trung bình 5 / 5. Số phiếu: 68

Bài viết chưa có đánh giá! Hãy là người đầu tiên đánh giá bài viết này.

Trả lời

Giao diện bởi Anders Norén