蒙蒂霍尔问题的 Pygame 模拟
原文:https://www . geesforgeks . org/monty-hall-problems-simulation-use-pygame/
在本文中,我们将看到如何使用 Python 中的 Pygame 创建 Monty Hall 游戏。蒙蒂霍尔是美国电视游戏节目《让我们做笔交易》的游戏节目。
假设你在一个游戏节目中,你可以选择三扇门,一扇门后是一辆车;在其他人后面,是山羊。你挑一扇门,说 1 号,知道门后是什么的主人,打开另一扇门,说 3 号,里面有一只山羊。然后他对你说:“你想选 2 号门吗?”转换选择对你有利吗?
展示最终产品的样子:
山羊出现在 1 号门后面。最初的选择是 2 号门。
由于决定留下来,比赛就赢了。
请确保使用的图像和音频与 Python 文件存在于同一文件夹中。图像和音频可以从这里下载。
工作流程和逻辑
整个模拟可以归纳为以下几点:
- 因为有三扇门,所以会产生数字 1、2、3 的随机排列,每个数字代表门的号码。这个随机生成的排列的前两个数字对应山羊所在的门,第三个数字是汽车所在的门。
- 一旦生成了配置,就可以通过图像以图形方式表示。每个配置都有一个映像。
- 有一点需要注意——根据谜题,在用户选择了门牌号之后,只有后面有山羊的门才会被显示出来。因此,如果用户选择了后面有汽车的门,那么剩下的两个门中的任何一个都可以被显示出来。然而,如果用户选择了后面有山羊的门,则剩下的两扇门中只有一扇门可以被打开(因为不允许打开用户选择的门)。
进行导入和生成配置
Python 3
import pygame
import random
pygame.init()
white = (255, 255, 255)
X = 1200
Y = 650
doors = random.sample(range(1, 4), 3)
goat1 = doors[0]
goat2 = doors[1]
goats = [goat1, goat2]
car = doors[2]
这个模拟 pygame 和 random 只需要两个外部模块。在每个 Pygame 程序的开始,都需要通过编写 pygame.init()来初始化 Pygame。X 和 Y 值是指运行模拟的窗口的尺寸。这些值可以根据所需的分辨率和使用的图像进行更改。列表“门”的值介于 1 和 3 之间(含 1 和 3)。每次运行程序时,这些值的顺序都会混乱。这样做是为了指定门,后面会有山羊。根据问题,这两扇门后面总共有三扇门,会有山羊,第三扇门后面会有汽车。变量山羊 1 和山羊 2 保存着门号,门号后面会有山羊。这些数字然后被添加到一个名为山羊的列表中。第三个数字分配给变量 car。
添加背景和音乐
Python 3
display_surface = pygame.display.set_mode((X, Y))
pygame.display.set_caption('Simulation')
image = pygame.image.load('all_doors.jpg')
change = False
def music():
file = 'click.mp3'
pygame.mixer.init()
pygame.mixer.music.load(file)
pygame.mixer.music.play()
display_surface 变量就像一张画布,我们将在上面添加实体(图像、文本等)。)按照要求。通过 display.set_caption 函数传递的参数将是模拟窗口的标题。首先要显示的图像——所有三扇门都已关闭,已加载。一个布尔变量,变化,用于记录变化。功能音乐是可选的。它的功能是当用户按下一扇门时产生点击的声音。一定要有任何想要播放的音乐的 mp3 文件。该函数执行初始化、加载和播放三个步骤。
基于用户输入更新图像
Python 3
def show_car(car, state):
my_font = pygame.font.SysFont("latoblack", 26)
display_surface = pygame.display.set_mode((X, Y))
car1 = pygame.image.load('car_1.jpg')
car2 = pygame.image.load('car_2.jpg')
car3 = pygame.image.load('car_3.jpg')
if car == 1:
display_surface.blit(car1, (0, 0))
pygame.display.update()
elif car == 2:
display_surface.blit(car2, (0, 0))
pygame.display.update()
elif car == 3:
display_surface.blit(car3, (0, 0))
pygame.display.update()
if state == 1:
the_text = my_font.render("You won by switching!", True, (231, 0, 10))
display_surface.blit(the_text, (350, 180))
pygame.display.update()
elif state == 2:
the_text = my_font.render(
"You could've won by staying!", True, (231, 0, 0))
display_surface.blit(the_text, (350, 180))
pygame.display.update()
elif state == 3:
the_text = my_font.render("You won by staying!", True, (231, 0, 0))
display_surface.blit(the_text, (350, 180))
pygame.display.update()
elif state == 4:
the_text = my_font.render(
"You could've won by switcing!", True, (231, 0, 0))
display_surface.blit(the_text, (350, 180))
pygame.display.update()
def draw_rect():
pygame.draw.rect(display_surface, (20, 24, 11),
(300, 220, 300, 40), 1)
pygame.display.update()
pygame.draw.rect(display_surface, (14, 2, 200),
(300, 260, 300, 40), 1)
pygame.display.update()
show_car 功能可能看起来有点麻烦,但是它的功能相当琐碎。它旨在显示适当方向的图像,即,如果汽车在门 3 后面,则显示对应于该方向(汽车在位置 3)的图像。所有的图片(以及代码中使用的名称)都在本文的末尾。状态参数告诉模拟的结果。
有四种可能的结果:
| **结果** | **决定** | | 获胜 | 逗留 | | 获胜 | 转换 | | 遗失 | 逗留 | | 遗失 | 转换 | 必须使用 **pygame.display.update()** 才能进行任何显示更改。可以通过更改 **my_font** 变量中的参数来更改字体和字号。 **display_surface.blit** 的第一个参数是要渲染的图像,第二个参数是表示 X 和 Y 坐标的元组。 **my_font** 有一个属性 **render** 用于显示文本。第一个参数是要显示的文本,第三个参数是包含用于指定文本颜色的 RGB 值的元组。 **display_surface.blit** 用于将**指定的文本渲染到画布上。第一个参数是文本的规格,第二个参数有 X 和 Y 坐标。要找到坐标,请使用:** ## Python 3x, y = pygame.mouse.get_pos()
这将创建一个十字准线,点击点的坐标将是已知的。
## 主循环和处理点击
## Python 3
while True:
music()
if change == False:
display_surface.fill(white)
display_surface.blit(image, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
pygame.display.update()
clicked = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Check if door 1 is pressed.
if(event.pos[0] >= 71 and event.pos[0] <= 203
and event.pos[1] >= 387 and event.pos[1] <= 632):
user = 1
clicked = True
music()
# Check if door 2 is pressed.
elif(event.pos[0] >= 353 and event.pos[0] <= 485
and event.pos[1] >= 386 and event.pos[1] <= 635):
user = 2
clicked = True
music()
# Check if door 3 is pressed.
elif(event.pos[0] >= 938 and event.pos[0] <= 1100
and event.pos[1] >= 387 and event.pos[1] <= 633):
user = 3
# print("Clicked on door 3.")
clicked = True
music()
每个游戏都包含一个无限循环(当为真时为**)。**检查注册的事件类型是否为**退出,**即用户关闭了 Pygame 窗口。在这种情况下,程序终止。**侏儒怪。**鼠标左键点击鼠标的事件。if 条件用于确定用户已按下的门(基于坐标),门号被分配给变量**用户**。例如,如果发生点击的点的 X 坐标( **event.pos[0]** )在 71 和 203 之间,Y 坐标( **event.pos[1]** )在 387 和 633 之间,则登记点击在门 1 上有点击。单击**布尔型设置为真,只要单击三扇门中的一扇门。**
## **加载所有有效配置(图像)并生成山羊位置**
## **Python 3**
if clicked:
image1 = pygame.image.load('goat_1.jpg')
image2 = pygame.image.load('goat_2.jpg')
image3 = pygame.image.load('goat_3.jpg')
image4 = pygame.image.load('car_1.jpg')
image5 = pygame.image.load('car_2.jpg')
image6 = pygame.image.load('car_3.jpg')
wr = random.randint(0, 1)
if(goats[0] == user):
g = goats[1]
elif(goats[1] == user):
g = goats[0]
else:
g = goats[wr]
if g == 1:
change = True
display_surface.blit(image1, (0, 0))
pygame.display.update()
elif g == 2:
change = True
display_surface.blit(image2, (0, 0))
pygame.display.update()
elif g == 3:
change = True
display_surface.blit(image3, (0, 0))
pygame.display.update()
print(u"There is a goat behind door {}".format(g))
my_font = pygame.font.SysFont("mvboli", 26)
the_text = my_font.render("Do you want to:", True, (231, 0, 0))
display_surface.blit(the_text, (350, 180))
the_text2 = my_font.render("1.Switch", True, (0, 0, 190))
display_surface.blit(the_text2, (350, 220))
the_text3 = my_font.render("2.Stay", True, (190, 0, 0))
display_surface.blit(the_text3, (350, 260))
draw_rect()
clicked2 = False
print(u"The car is behind door {}".format(car))
clicked2 = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Compare click coordinates with
# coordinates where it says 'Switch' and 'Stay'.
if(event.pos[0] >= 299 and event.pos[0] <= 597
and event.pos[1] >= 220
and event.pos[1] <= 260):
# user2 = 1 means user has chosen to switch.
user2 = 1
clicked2 = True
elif(event.pos[0] >= 301 and event.pos[0] <= 598
and event.pos[1] >= 259 and event.pos[1] <= 297):
user2 = 2 # user2 = 2 means user has chosen to stay.
clicked2 = True
**注册有效点击后,将加载六个图像。检查用户是否点击了后面有山羊的门。由于用户选择的门无法打开,并且可以打开的门后面必须包含山羊,因此只有一个可能的门可以打开。比方说,山羊在门 1 和门 2 的后面,用户点击门 1,因为门 1 不能打开,所以门 2 是唯一可以打开的门。变量 **g** 存储可以打开的有效门。如果用户没有选择后面有山羊的门,则使用**随机点**功能随机分配山羊,并在变量 **wr** 中存储 1 或 0。**
**变量 **user2** 存储用户是选择停留还是切换。布尔型,**点击 2** ,存储用于确定选择(停留或切换)的点击是否已注册。**
## **基于用户输入显示结果(文本)**
## **Python 3**
if clicked2:
if user2 == 1:
print("You chose to switch!")
if user in goats:
my_font = pygame.font.SysFont("mvboli", 26)
the_text = my_font.render(
"You won by switching!", True, (231, 0, 0))
state = 1
display_surface.blit(the_text, (350, 180))
pygame.display.update()
print("You won by switching!")
else: # User has chosen the door behind which there is a car.
my_font = pygame.font.SysFont("mvboli", 26)
the_text2 = my_font.render(
"You could've won by staying!", True, (231, 0, 0))
state = 2
display_surface.blit(the_text2, (350, 180))
pygame.display.update()
print("You could have won by switching!")
elif user2 == 2:
print("You chose to stay!")
if user == car:
my_font = pygame.font.SysFont("mvboli", 26)
the_text3 = my_font.render(
"You won by staying!", True, (231, 0, 0))
display_surface.blit(the_text3, (350, 180))
state = 3
pygame.display.update()
print("You won by staying!")
else:
my_font = pygame.font.SysFont("mvboli", 26)
the_text4 = my_font.render(
"You could've won by switching!", True, (231, 0, 0))
display_surface.blit(the_text4, (350, 180))
state = 4
pygame.display.update()
print("You could have won by switching!")
show_car(car, state)
**一旦用户选择了,就确定他们是否赢了(他们最终选择的门后是否有车)。确定获胜者可以通过下表理解:**
| **动作** | **初始选择(山羊或汽车)** | **结果** |
| 转换 | 山羊 | 获胜 |
| 转换 | 汽车 | 遗失 |
| 逗留 | 汽车 | 获胜 |
| 逗留 | 山羊 | 遗失 |
## **下面是完整的实现:**
## **Python 3**
import pygame
import random
pygame.init()
white = (255, 255, 255)
X = 1200
Y = 650
doors = random.sample(range(1, 4), 3)
goat1 = doors[0]
goat2 = doors[1]
goats = [goat1, goat2]
car = doors[2]
display_surface = pygame.display.set_mode((X, Y))
pygame.display.set_caption('Simulation')
image = pygame.image.load('all_doors.jpg')
change = False
msg_disp = False
def music():
file = 'click.mp3'
pygame.mixer.init()
pygame.mixer.music.load(file)
pygame.mixer.music.play()
def show_car(car, state):
my_font = pygame.font.SysFont("latoblack", 26)
display_surface = pygame.display.set_mode((X, Y))
car1 = pygame.image.load('car_1.jpg')
car2 = pygame.image.load('car_2.jpg')
car3 = pygame.image.load('car_3.jpg')
if car == 1:
display_surface.blit(car1, (0, 0))
pygame.display.update()
elif car == 2:
display_surface.blit(car2, (0, 0))
pygame.display.update()
elif car == 3:
display_surface.blit(car3, (0, 0))
pygame.display.update()
if state == 1:
the_text = my_font.render("You won by switching!",
True, (231, 0, 10))
display_surface.blit(the_text, (350, 180))
pygame.display.update()
elif state == 2:
the_text = my_font.render(
"You could've won by staying!", True,
(231, 0, 0))
display_surface.blit(the_text, (350, 180))
pygame.display.update()
elif state == 3:
the_text = my_font.render("You won by staying!",
True, (231, 0, 0))
display_surface.blit(the_text, (350, 180))
pygame.display.update()
elif state == 4:
the_text = my_font.render(
"You could've won by switcing!", True,
(231, 0, 0))
display_surface.blit(the_text, (350, 180))
pygame.display.update()
def draw_rect():
pygame.draw.rect(display_surface, (20, 24, 11),
(300, 220, 300, 40), 1)
pygame.display.update()
pygame.draw.rect(display_surface, (14, 2, 200),
(300, 260, 300, 40), 1)
pygame.display.update()
while True:
music()
if change == False:
display_surface.fill(white)
display_surface.blit(image, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
pygame.display.update()
clicked = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Check if door 1 is pressed.
if(event.pos[0] >= 71 and event.pos[0] <= 203
and event.pos[1] >= 387 and event.pos[1] <= 632):
user = 1
clicked = True
music()
# Check if door 2 is pressed.
elif(event.pos[0] >= 353 and event.pos[0] <= 485
and event.pos[1] >= 386 and event.pos[1] <= 635):
user = 2
clicked = True
music()
# Check if door 3 is pressed.
elif(event.pos[0] >= 938 and event.pos[0] <= 1100
and event.pos[1] >= 387 and event.pos[1] <= 633):
user = 3
clicked = True
music()
if clicked:
image1 = pygame.image.load('goat_1.jpg')
image2 = pygame.image.load('goat_2.jpg')
image3 = pygame.image.load('goat_3.jpg')
image4 = pygame.image.load('car_1.jpg')
image5 = pygame.image.load('car_2.jpg')
image6 = pygame.image.load('car_3.jpg')
wr = random.randint(0, 1)
if(goats[0] == user):
g = goats[1]
elif(goats[1] == user):
g = goats[0]
else:
g = goats[wr]
if g == 1:
change = True
display_surface.blit(image1, (0, 0))
pygame.display.update()
elif g == 2:
change = True
display_surface.blit(image2, (0, 0))
pygame.display.update()
elif g == 3:
change = True
display_surface.blit(image3, (0, 0))
pygame.display.update()
print(u"There is a goat behind door {}".format(g))
my_font = pygame.font.SysFont("mvboli", 26)
the_text = my_font.render("Do you want to:", True, (231, 0, 0))
display_surface.blit(the_text, (350, 180))
the_text2 = my_font.render("1.Switch", True, (0, 0, 190))
display_surface.blit(the_text2, (350, 220))
the_text3 = my_font.render("2.Stay", True, (190, 0, 0))
display_surface.blit(the_text3, (350, 260))
draw_rect()
clicked2 = False
print(u"The car is behind door {}".format(car))
# for event in pygame.event.get():
clicked2 = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Compare click coordinates with coordinates
# where it says 'Switch' and 'Stay'.
if(event.pos[0] >= 299 and event.pos[0] <= 597
and event.pos[1] >= 220 and event.pos[1] <= 260):
# user2 = 1 means user has chosen to switch.
user2 = 1
clicked2 = True
elif(event.pos[0] >= 301 and event.pos[0] <= 598
and event.pos[1] >= 259 and event.pos[1] <= 297):
# user2 = 2 means user has chosen to stay.
user2 = 2
clicked2 = True
if clicked2:
if user2 == 1:
print("You chose to switch!")
if user in goats:
my_font = pygame.font.SysFont("mvboli", 26)
the_text = my_font.render(
"You won by switching!", True, (231, 0, 0))
state = 1
display_surface.blit(the_text, (350, 180))
pygame.display.update()
print("You won by switching!")
# User has chosen the door behind which there is a car.
else:
my_font = pygame.font.SysFont("mvboli", 26)
the_text2 = my_font.render(
"You could've won by staying!", True, (231, 0, 0))
state = 2
display_surface.blit(the_text2, (350, 180))
pygame.display.update()
print("You could have won by switching!")
elif user2 == 2:
print("You chose to stay!")
if user == car:
my_font = pygame.font.SysFont("mvboli", 26)
the_text3 = my_font.render(
"You won by staying!", True, (231, 0, 0))
display_surface.blit(the_text3, (350, 180))
state = 3
pygame.display.update()
print("You won by staying!")
else:
my_font = pygame.font.SysFont("mvboli", 26)
the_text4 = my_font.render(
"You could've won by switching!", True, (231, 0, 0))
display_surface.blit(the_text4, (350, 180))
state = 4
pygame.display.update()
print("You could have won by switching!")
show_car(car, state)
****输出:****
**![](img/3b043a12d8391264d576490aedbed3eb.png)**
版权属于:月萌API www.moonapi.com,转载请注明出处