游戏介绍
- 在5X5的数字宫格里翻牌,翻出所有的2和3即可获胜
- 每一格只能是0、1、2、3,
- 第六列和最第六行为
X | Y
,X代表该列或该行的数字总和,Y代表该列或该行的0的个数 - 控制难度,每行每列的数字总和不超过9
- 该游戏需要一定运气及技巧
核心代码
生成二维数字列表
def createNumList() -> list:
arr = []
for i in range(6):
row = []
row_sum = 0
col_sum = 0
row_zeros = 0
col_zeros = 0
for j in range(5):
# 从第二行开始计算每列当前和
col_sum = sum([arr[s - 1][j] for s in range(i)]) if i > 0 else None
if i < 5:
num = random.randint(0, 3)
if col_sum:
while row_sum + num > 9 or col_sum + num > 9: # 控制总和
num = random.randint(0, 3)
else:
while row_sum + num > 9: # 控制总和
num = random.randint(0, 3)
row.append(num)
row_sum += num
row_zeros = row_zeros + 1 if num == 0 else row_zeros
else:
# 第六行开始计算每列0的数量
col_zeros = [arr[s][j] for s in range(5)].count(0)
row.append((col_sum, col_zeros))
row.append((row_sum, row_zeros))
arr.append(row)
return arr
绘制宫格
def makePalace(numList, window, screen, click_list=[]):
"""
绘制宫格,根据是否被点击来更改样式
:param click_list: 被点击的格子,默认没有
:param numList: 数字列表
:param window: surface
:param screen: screen
:return: 宫格列表(一维)
"""
palace_list = []
for i in range(6):
for j in range(6):
# 特殊格子的内容
if i == 5 or j == 5:
text = f'{numList[i][j][0]} | {numList[i][j][1]}'
if i == 5 and j == 5:
text = ' '
else:
text = numList[i][j]
# 每一个的样式
border = 2
palace_color = color_dict['black']
if (i, j) in click_list:
if text == '0':
border = 0
palace_color = color_dict['red']
text_color = color_dict['white']
else:
border = 1
text_color = color_dict['black']
else:
text_color = color_dict['white']
if i == 5 or j == 5:
text_color = color_dict['black']
palace = makeAndDrawRect(surface=window,
x=(screen.width - screen.height) / 2 + j * screen.height / 6,
y=i * screen.height / 6,
width=screen.height / 6,
height=screen.height / 6,
border=border,
color=palace_color,
text=text,
text_color=text_color,
font_size=70)
palace_list.append({
'rect': palace,
'click': False,
'index': (i, j),
'data': text if len(text) == 1 else None
})
return palace_list
完整代码
import pygame
import screeninfo
import gameNum
from color import color_dict
pygame.init()
def makeText(surface, txt, x, y, text_color=color_dict['white'], size=40):
"""
绘制以(x, y)为中心的文本
:param size:
:param surface:
:param txt:
:param x:
:param y:
:param text_color:
:return:
"""
font_name = pygame.font.match_font('Microsoft YaHei')
font = pygame.font.Font(font_name, size)
text = font.render(txt, True, text_color)
text_rect = text.get_rect(center=(x, y))
surface.blit(text, text_rect)
def makeAndDrawRect(surface, x, y, width, height, text=None, border=0, color=color_dict['white'],
text_color=color_dict['white'], font_size=40, border_radius=0):
"""
生成按钮,生成以(x, y)为顶点,文本在中间的按钮
:param border_radius:
:param font_size:
:param text_color:
:param color:
:param border:
:param surface:
:param x:
:param y:
:param width:
:param height:
:param text:
:return: button
"""
button = pygame.Rect(x, y, width, height)
pygame.draw.rect(surface, color, rect=button, width=border, border_radius=border_radius)
if text:
makeText(surface, text, x + width / 2, y + height / 2, text_color, font_size)
return button
def makePalace(numList, window, screen, click_list=[]):
"""
绘制宫格,根据是否被点击来更改样式
:param click_list: 被点击的格子,默认没有
:param numList: 数字列表
:param window: surface
:param screen: screen
:return: 宫格列表(一维)
"""
palace_list = []
for i in range(6):
for j in range(6):
# 特殊格子的内容
if i == 5 or j == 5:
text = f'{numList[i][j][0]} | {numList[i][j][1]}'
if i == 5 and j == 5:
text = ' '
else:
text = numList[i][j]
# 每一个的样式
border = 2
palace_color = color_dict['black']
if (i, j) in click_list:
if text == '0':
border = 0
palace_color = color_dict['red']
text_color = color_dict['white']
else:
border = 1
text_color = color_dict['black']
else:
text_color = color_dict['white']
if i == 5 or j == 5:
text_color = color_dict['black']
palace = makeAndDrawRect(surface=window,
x=(screen.width - screen.height) / 2 + j * screen.height / 6,
y=i * screen.height / 6,
width=screen.height / 6,
height=screen.height / 6,
border=border,
color=palace_color,
text=text,
text_color=text_color,
font_size=70)
palace_list.append({
'rect': palace,
'click': False,
'index': (i, j),
'data': text if len(text) == 1 else None
})
return palace_list
def main():
screen = screeninfo.get_monitors()[0]
window = pygame.display.set_mode((screen.width, screen.height))
pygame.display.set_caption('炸弹牌')
Gameplay = "每一个格子的数字只能是1、2、3, \n" \
"'X | Y' 代表了该行或该列的数字之和为X,炸弹数量为Y\n" \
"找出所有的2和3即为胜利"
numList = [] # 每一局的数字列表
clickPalace_indexList = [] # 被点击的格子
now_2_3_Count = 0
bt_again = None
sound_click = pygame.mixer.Sound('turn.wav')
sound_over = pygame.mixer.Sound('dedede.wav')
sound_win = pygame.mixer.Sound('win.mp3')
running = True
playing = False
result = None # True则赢,False则输
while running:
window.fill(color_dict['black'])
# 开始界面
if playing is False:
bt_start = makeAndDrawRect(surface=window,
x=(screen.width - 200) / 2,
y=screen.height * 0.7,
width=200,
height=80,
text='开始游戏',
border=5,
border_radius=5)
bt_exit = makeAndDrawRect(surface=window,
x=(screen.width - 200) / 2,
y=screen.height * 0.7 + 120,
width=200,
height=80,
text='退出游戏',
border=5,
border_radius=5)
lines = Gameplay.split('\n')
offset = -60
for line in lines:
makeText(window, line, screen.width / 2, screen.height / 2 + offset)
offset += 60
else:
# 生成当局数字
if numList:
pass
else:
numList = gameNum.elementToStr()
bt_exit = makeAndDrawRect(surface=window,
x=50,
y=screen.height * 0.7 + 120,
width=200,
height=80,
text='退出游戏',
border=5,
border_radius=5)
# 正方形白色背景
makeAndDrawRect(surface=window,
x=(screen.width - screen.height) / 2,
y=0,
width=screen.height,
height=screen.height)
# 根据是否被点击显示内容
palace_list = makePalace(numList, window, screen, clickPalace_indexList if clickPalace_indexList else [])
# 游戏结束所显示的内容
if result is not None:
bt_again = bt_start = makeAndDrawRect(surface=window,
x=50,
y=screen.height * 0.7,
width=200,
height=80,
text='再玩一局',
border=5,
border_radius=5)
if result is True:
makeText(window, '你赢了!', screen.width * 0.1, screen.height * 0.5)
else:
makeText(window, '翻到炸弹了!', screen.width * 0.1, screen.height * 0.5)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
if bt_exit.collidepoint(event.pos):
sound_click.play()
running = False
if playing is False:
if bt_start.collidepoint(event.pos):
sound_click.play()
playing = True
del bt_start
else:
# 点击宫格
count_2_3 = len([x for x in palace_list if x['data'] in ['2', '3']])
for palace in palace_list:
if palace['rect'].collidepoint(event.pos) and result is None: # 被点击且游戏还没有结束
if palace['index'] not in clickPalace_indexList and palace['data']: # 去重插入数字区数据
if palace['data'] == '0':
sound_over.play()
result = False
else:
sound_click.play()
if palace['data'] != '1':
now_2_3_Count += 1
clickPalace_indexList.append(palace['index'])
# 所有2和3被找出
if count_2_3 == now_2_3_Count and result is not True:
sound_win.play()
result = True
# 游戏结束
if result is not None and bt_again:
if bt_again.collidepoint(event.pos):
sound_click.play()
result = None
now_2_3_Count = 0
numList = []
clickPalace_indexList = []
bt_again = None
pygame.display.flip()
pygame.quit()
if __name__ == '__main__':
main()