Python实现消消乐小游戏
作者:Python新世界 发布时间:2021-02-19 19:37:42
标签:Python,消消乐
提到开心消消乐这款小游戏,相信大家都不陌生,其曾在 2015 年获得过玩家最喜爱的移动单机游戏奖,受欢迎程度可见一斑,本文我们使用 Python 来做个简单的消消乐小游戏。
实现
消消乐的构成主要包括三部分:游戏主体、计分器、计时器,下面来看一下具体实现。
先来看一下游戏所需 Python 库。
import os
import sys
import time
import pygame
import random
定义一些常量,比如:窗口宽高、网格行列数等,代码如下:
WIDTH = 400
HEIGHT = 400
NUMGRID = 8
GRIDSIZE = 36
XMARGIN = (WIDTH - GRIDSIZE * NUMGRID) // 2
YMARGIN = (HEIGHT - GRIDSIZE * NUMGRID) // 2
ROOTDIR = os.getcwd()
FPS = 30
接着创建一个主窗口,代码如下:
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('消消乐')
看一下效果:
再接着在窗口中画一个 8 x 8 的网格,代码如下:
screen.fill((255, 255, 220))
# 游戏界面的网格绘制
def drawGrids(self):
for x in range(NUMGRID):
for y in range(NUMGRID):
rect = pygame.Rect((XMARGIN+x*GRIDSIZE, YMARGIN+y*GRIDSIZE, GRIDSIZE, GRIDSIZE))
self.drawBlock(rect, color=(255, 165, 0), size=1
# 画矩形 block 框
def drawBlock(self, block, color=(255, 0, 0), size=2):
pygame.draw.rect(self.screen, color, block, size)
看一下效果:
再接着在网格中随机放入各种拼图块,代码如下:
while True:
self.all_gems = []
self.gems_group = pygame.sprite.Group()
for x in range(NUMGRID):
self.all_gems.append([])
for y in range(NUMGRID):
gem = Puzzle(img_path=random.choice(self.gem_imgs), size=(GRIDSIZE, GRIDSIZE), position=[XMARGIN+x*GRIDSIZE, YMARGIN+y*GRIDSIZE-NUMGRID*GRIDSIZE], downlen=NUMGRID*GRIDSIZE)
self.all_gems[x].append(gem)
self.gems_group.add(gem)
if self.isMatch()[0] == 0:
break
看一下效果:
再接着加入计分器和计时器,代码如下:
# 显示得分
def drawScore(self):
score_render = self.font.render('分数:'+str(self.score), 1, (85, 65, 0))
rect = score_render.get_rect()
rect.left, rect.top = (55, 15)
self.screen.blit(score_render, rect)
# 显示加分
def drawAddScore(self, add_score):
score_render = self.font.render('+'+str(add_score), 1, (255, 100, 100))
rect = score_render.get_rect()
rect.left, rect.top = (250, 250)
self.screen.blit(score_render, rect)
# 显示剩余时间
def showRemainingTime(self):
remaining_time_render = self.font.render('倒计时: %ss' % str(self.remaining_time), 1, (85, 65, 0))
rect = remaining_time_render.get_rect()
rect.left, rect.top = (WIDTH-190, 15)
self.screen.blit(remaining_time_render, rect)
看一下效果:
当设置的游戏时间用尽时,我们可以生成一些提示信息,代码如下:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYUP and event.key == pygame.K_r:
flag = True
if flag:
break
screen.fill((255, 255, 220))
text0 = '最终得分: %s' % score
text1 = '按 R 键重新开始'
y = 140
for idx, text in enumerate([text0, text1]):
text_render = font.render(text, 1, (85, 65, 0))
rect = text_render.get_rect()
if idx == 0:
rect.left, rect.top = (100, y)
elif idx == 1:
rect.left, rect.top = (100, y)
y += 60
screen.blit(text_render, rect)
pygame.display.update()
看一下效果:
说完了游戏图形化界面相关的部分,我们再看一下游戏的主要处理逻辑。
我们通过鼠标来操纵拼图块,因此程序需要检查有无拼图块被选中,代码实现如下:
def checkSelected(self, position):
for x in range(NUMGRID):
for y in range(NUMGRID):
if self.getGemByPos(x, y).rect.collidepoint(*position):
return [x, y]
return None
我们需要将鼠标连续选择的拼图块进行位置交换,代码实现如下:
def swapGem(self, gem1_pos, gem2_pos):
margin = gem1_pos[0] - gem2_pos[0] + gem1_pos[1] - gem2_pos[1]
if abs(margin) != 1:
return False
gem1 = self.getGemByPos(*gem1_pos)
gem2 = self.getGemByPos(*gem2_pos)
if gem1_pos[0] - gem2_pos[0] == 1:
gem1.direction = 'left'
gem2.direction = 'right'
elif gem1_pos[0] - gem2_pos[0] == -1:
gem2.direction = 'left'
gem1.direction = 'right'
elif gem1_pos[1] - gem2_pos[1] == 1:
gem1.direction = 'up'
gem2.direction = 'down'
elif gem1_pos[1] - gem2_pos[1] == -1:
gem2.direction = 'up'
gem1.direction = 'down'
gem1.target_x = gem2.rect.left
gem1.target_y = gem2.rect.top
gem1.fixed = False
gem2.target_x = gem1.rect.left
gem2.target_y = gem1.rect.top
gem2.fixed = False
self.all_gems[gem2_pos[0]][gem2_pos[1]] = gem1
self.all_gems[gem1_pos[0]][gem1_pos[1]] = gem2
return True
每一次交换拼图块时,我们需要判断是否有连续一样的三个及以上拼图块,代码实现如下:
def isMatch(self):
for x in range(NUMGRID):
for y in range(NUMGRID):
if x + 2 < NUMGRID:
if self.getGemByPos(x, y).type == self.getGemByPos(x+1, y).type == self.getGemByPos(x+2, y).type:
return [1, x, y]
if y + 2 < NUMGRID:
if self.getGemByPos(x, y).type == self.getGemByPos(x, y+1).type == self.getGemByPos(x, y+2).type:
return [2, x, y]
return [0, x, y]
当出现三个及以上拼图块时,需要将这些拼图块消除,代码实现如下:
def removeMatched(self, res_match):
if res_match[0] > 0:
self.generateNewGems(res_match)
self.score += self.reward
return self.reward
return 0
将匹配的拼图块消除之后,我们还需要随机生成新的拼图块,代码实现如下:
def generateNewGems(self, res_match):
if res_match[0] == 1:
start = res_match[2]
while start > -2:
for each in [res_match[1], res_match[1]+1, res_match[1]+2]:
gem = self.getGemByPos(*[each, start])
if start == res_match[2]:
self.gems_group.remove(gem)
self.all_gems[each][start] = None
elif start >= 0:
gem.target_y += GRIDSIZE
gem.fixed = False
gem.direction = 'down'
self.all_gems[each][start+1] = gem
else:
gem = Puzzle(img_path=random.choice(self.gem_imgs), size=(GRIDSIZE, GRIDSIZE), position=[XMARGIN+each*GRIDSIZE, YMARGIN-GRIDSIZE], downlen=GRIDSIZE)
self.gems_group.add(gem)
self.all_gems[each][start+1] = gem
start -= 1
elif res_match[0] == 2:
start = res_match[2]
while start > -4:
if start == res_match[2]:
for each in range(0, 3):
gem = self.getGemByPos(*[res_match[1], start+each])
self.gems_group.remove(gem)
self.all_gems[res_match[1]][start+each] = None
elif start >= 0:
gem = self.getGemByPos(*[res_match[1], start])
gem.target_y += GRIDSIZE * 3
gem.fixed = False
gem.direction = 'down'
self.all_gems[res_match[1]][start+3] = gem
else:
gem = Puzzle(img_path=random.choice(self.gem_imgs), size=(GRIDSIZE, GRIDSIZE), position=[XMARGIN+res_match[1]*GRIDSIZE, YMARGIN+start*GRIDSIZE], downlen=GRIDSIZE*3)
self.gems_group.add(gem)
self.all_gems[res_match[1]][start+3] = gem
start -= 1
之后反复执行这个过程,直至耗尽游戏时间,游戏结束。
最后,我们动态看一下游戏效果。
来源:https://blog.csdn.net/weixin_46089319/article/details/107694226
0
投稿
猜你喜欢
- 如何只取数据库的前3条记录?怎么控制只取得前3行数据 这要看是什么类型的数据库了,对于Access和SQ
- 本文实例为大家分享了Python3连接MySQL模拟转账的具体实现代码,供大家参考,具体内容如下# coding:utf8import sy
- 本文实例为大家分享了基于信息增益的决策树归纳的Python实现代码,供大家参考,具体内容如下# -*- coding: utf-8 -*-i
- 在这里,我不打算介绍使用SQL Server的窍门,也不能提供一个包治百病的方案,我所做的是总结一些经验----关于如何形成一个好的设计。这
- 很多程序绕过这个问题,往往人工来决定在何处截断,太麻烦了。 实现内容:截断一段含有HTML代码的文本,但是不会出现围堵标记没有封闭的问题。
- 【OpenCV】⚠️高手勿入! 半小时学会基本操作⚠️边界填充概述OpenCV 是一个跨平台的计算机视觉库, 支持多语言, 功能强大. 今天
- 本文实例讲述了Python实现查找二叉搜索树第k大的节点功能。分享给大家供大家参考,具体如下:题目描述给定一个二叉搜索树,找出其中第k大的节
- 大部分情况下,这种动态生成的sql查询语句写法如下: 代码如下:select A表.字段1,A表.字段2,B表.字段返回,C表.字段返回 f
- 一、基本概述目前电脑上已经下载了MongoDB数据库、navicat for mongodb作为mongoDB的可视化工具,形如navica
- 进程概述? 进程(Process)是计算机中已运行程序的实体。进程与程序不同,程序本身只是指令、数据及器组织形式的描述,进程才是程序(那些指
- 摘要: 当你想快速共享一个目录的时候,这是特别有用的,只需要1行代码即可实现。当你想快速共享一个目录的时候,这是特别有用的,只需
- python书籍信息爬虫示例,供大家参考,具体内容如下背景说明需要收集一些书籍信息,以豆瓣书籍条目作为源,得到一些有效书籍信息,并保存到本地
- GO1.7之后,新增了context.Context这个package,实现goroutine的管理。Context基本的用法参考GOLAN
- 本文实例讲述了Python实现从订阅源下载图片的方法。分享给大家供大家参考。具体如下:这段代码是基于python 3.4实现的,和pytho
- 本文实例讲述了JS实现倒序输出的几种常用方法。分享给大家供大家参考,具体如下:1.通过split和数组的逆序输出var num = 123;
- 最近背着老婆买了一个switch卡带,这货居然给丈母娘讲,害得我被丈母娘说还小了,不买奶粉买游戏,太气人了,我连夜用python写了个《记仇
- 安装pyecharts:pip install pyecharts安装snapshot-selenium:pip install snaps
- 这篇文章主要为大家详细介绍了python批量爬取下载抖音视频,具有一定的参考价值,感兴趣的小伙伴们可以参考一下项目源码展示:'
- 我个人感觉数据库这方面对于程序员来说很重要,无论是对于JAVA程序员还是DOTNET程序员以及其他编程人员来说都是必须掌握的。为了帮助大家更
- f-string 字符串格式化语法f-string 是 Python 3.6 版本引入的一种新的字符串格式化语法。与其他字符串格式