基于python的俄罗斯方块小游戏

课 程 名:   python课程设计

课程设计项目名称:   基于python的俄罗斯方块

团队成员:     叶焱镔、柯博群、钱昱铭

一、项目简介

1.1 项目博客地址

1.2 项目完成的功能与特色

俄罗斯方块的游戏实现,实现了随机方块的生成、下落、旋转,游戏的进行、消除、结束,游戏的重新开始、退出、暂停,可显示最高记录、历史记录、记录的排行,可继续上回的游戏

1.3 项目采用的技术栈    python

1.4 项目借鉴源代码的地址 https://blog.csdn.net/lanseguhui/article/details/80338332

1.5 团队成员任务分配表

叶焱镔:上回游戏的功能实现

柯博群:记录游戏的得分与排行情况,和退出的提示

钱昱铭:基础功能的设计与实现

二、项目的需求分析

1、实现各种方块的生产,包括形状和颜色等信息;

2、实现各个方块的上下左右移动和旋转的功能

3、实现消行的功能;

4、实现得分的统计功能;

5、实现开始,暂停,结束等功能

6、实现历史记录最高记录与排行

7、实现上回游戏继续

三、项目功能架构图、主要功能流程图

四、系统模块说明

4.1 系统模块列表

4.2 各模块详细描述(名称,功能,运行截图,关键源代码)

class RussiaBlock(object):

#初始化地图

def __init__(self):

self.newflag=True

self.sflag=False

#判断是否开始(记录游戏记录合法标志

self.create_not_exist()

# 方块颜色列表

self.color = [‘red‘, ‘orange‘, ‘yellow‘, ‘purple‘, ‘blue‘, ‘green‘, ‘pink‘]

# 字典 存储形状对应7种形状 元组存储坐标

self.shapeDict = {1: [(0, 0), (0, -1), (0, -2), (0, 1)],  # shape I

2: [(0, 0), (0, -1), (1, -1), (1, 0)],  # shape O

3: [(0, 0), (-1, 0), (0, -1), (1, 0)],  # shape T T型

4: [(0, 0), (0, -1), (1, 0), (2, 0)],  # shape J 右长倒L盖子

5: [(0, 0), (0, -1), (-1, 0), (-2, 0)],  # shape L

6: [(0, 0), (0, -1), (-1, -1), (1, 0)],  # shape Z

7: [(0, 0), (-1, 0), (0, -1), (1, -1)]}  # shape S

# 旋转坐标控制

self.rotateDict = {(0, 0): (0, 0), (0, 1): (-1, 0), (0, 2): (-2, 0), (0, -1): (1, 0),

(0, -2): (2, 0), (1, 0): (0, 1), (2, 0): (0, 2), (-1, 0): (0, -1),

(-2, 0): (0, -2), (1, 1): (-1, 1), (-1, 1): (-1, -1),

(-1, -1): (1, -1), (1, -1): (1, 1)}

# 初始高度,宽度 核心块位置

self.coreLocation = [4, -2]

self.height, self.width = 20, 10

self.size = 32

# map_s can record the location of every square.i宽  j高

self.map_s = self.rmyRecord()

if not bool(self.map_s):

# 全部置0

for i in range(self.width):

for j in range(-4, self.height):

self.map_s[(i, j)] = 0

# 添加边界

for i in range(-4, self.width + 4):

self.map_s[(i, self.height)] = 1

for j in range(-4, self.height + 4):

for i in range(-4, 0):

self.map_s[(i, j)] = 1

for j in range(-4, self.height + 4):

for i in range(self.width, self.width + 4):

self.map_s[(i, j)] = 1

# 初始化分数0  默认不加快  按下时加快

self.score = 0

self.isFaster = False

# 创建GUI界面

self.root = Tk()

self.root.title("RussiaBlock")

self.root.geometry("500x645")

self.area = Canvas(self.root, width=320, height=640, bg=‘white‘)

self.area.grid(row=2)

self.pauseBut = Button(self.root, text="暂停", height=2, width=13, font=18, command=self.is_pause)

self.pauseBut.place(x=340, y=100)

self.startBut = Button(self.root, text="开始", height=2, width=13, font=18, command=self.play)

self.startBut.place(x=340, y=20)

self.restartBut = Button(self.root, text="重新开始", height=2, width=13, font=18, command=self.is_restart)

self.restartBut.place(x=340, y=180)

self.quitBut = Button(self.root, text="退出", height=2, width=13, font=18, command=self.is_quit)

self.quitBut.place(x=340, y=260)

self.scoreLabel1 = Label(self.root, text="分数:", font=24)

self.scoreLabel1.place(x=340, y=400)

self.scoreLabel2 = Label(self.root, text="0", fg=‘red‘, font=24)

self.scoreLabel2.place(x=410, y=400)

#最高记录////////------------------------

self.scoreLabel3 = Label(self.root, text="最高记录:", font=24)

self.scoreLabel3.place(x=340, y=480)

maxs=self.getMax()[0]

self.scoreLabel4 = Label(self.root, text=maxs, fg=‘red‘, font=24)

self.scoreLabel4.place(x=450, y=480)

#排行/////////

self.sortBut = Button(self.root, text="排行", height=1, width=8, font=12, command=self.getSort)

self.sortBut.place(x=340, y=510)

#历史记录////////------------------------

self.recordBut = Button(self.root, text="历史记录", height=1, width=8, font=12, command=self.getRecord)

self.recordBut.place(x=340, y=550)

# 按键交互

self.area.bind("<Up>", self.rotate)

self.area.bind("<Left>", self.move_left)

self.area.bind("<Right>", self.move_right)

self.area.bind("<Down>", self.move_faster)

self.area.bind("<Key-w>", self.rotate)

self.area.bind("<Key-a>", self.move_left)

self.area.bind("<Key-d>", self.move_right)

self.area.bind("<Key-s>", self.move_faster)

self.area.focus_set()

# 菜单

self.menu = Menu(self.root)

self.root.config(menu=self.menu)

self.startMenu = Menu(self.menu)

self.menu.add_cascade(label=‘开始‘, menu=self.startMenu)

self.startMenu.add_command(label=‘新游戏‘, command=self.is_restart)

self.startMenu.add_separator()

self.startMenu.add_command(label=‘重新开始‘, command=self.play)

self.exitMenu = Menu(self.menu)

self.menu.add_cascade(label=‘退出‘, command=self.is_quit)

self.helpMenu = Menu(self.root)

self.menu.add_cascade(label=‘帮助‘, menu=self.helpMenu)

self.helpMenu.add_command(label=‘如何操作‘, command=self.rule)

self.helpMenu.add_separator()

self.helpMenu.add_command(label=‘关于...‘, command=self.about)

# 先将核心块的所在位置在map_s中的元素设为1,通过self.shapeDict获取其余方块位置,将map_s中对应元素设为1。

def get_location(self):

map_s[(core[0], core[1])] = 1

for i in range(4):

map_s[((core[0] + getNew[i][0]), (core[1] + getNew[i][1]))] = 1

# 判断方块下移一格后对应位置map_s中的元素是否为一,是,则不可移动,返回False;否,可以移动,返回True。

def can_move(self):

for i in range(4):

if map_s[(core[0] + getNew[i][0]), (core[1] + 1 + getNew[i][1])] == 1:

return False

return True

# 先用randRange获取1~7中的随机整数,随机到某一整数,那么访问self.shapeDict,获取这种形状方块的核心块及其他方块的相对位置。

# 访问颜色字典,获取此方块的颜色。建立循环,当方块可移动时(while self. can_move():),且暂停键未被摁下(if is_pause:),

# 核心块纵坐标加一,根据核心块及其他方块对于核心块的相对位置,画出四个方块。用self.get_location()函数获取方块的位置。

def draw_new(self):

global next_s

global getNew

global core

core = [4, -2]

next_s=randrange(1, 8)

if self.newflag:

core=self.rmysq()[0:2]

next_s=self.rmysq()[2]

self.scoreLabel2.config(text=str(self.rmysq()[-1]))

# 形状

self.newflag=False

getNew = self.shapeDict[next_s]

time = 0.2

while self.can_move():

if is_pause:

core[1] += 1

self.draw_square()

if self.isFaster:

sleep(time - 0.15)

else:

sleep(time + 0.22)

self.isFaster = False

else:

self.draw_square()

sleep(time)

self.get_location()

# 绘制当前方块

def draw_square(self):

self.area.delete("new")

for i in range(4):

self.area.create_rectangle((core[0] + getNew[i][0]) * self.size,

(core[1] + getNew[i][1]) * self.size,

(core[0] + getNew[i][0] + 1) * self.size,

(core[1] + getNew[i][1] + 1) * self.size,

fill=self.color[next_s - 1], tags="new")

self.area.update()

# 给底部每行中方块都加上标签:bottom + str(j), j代表该块所在行数,每次遍历map_s,建立对于range(self. height)的for循环,删去每一行,

# 若map_s什么地方的元素为1,画出这一位置的方块,不断更新。这样可以画出底部方块。

def draw_bottom(self):

for j in range(self.height):

self.area.delete(‘bottom‘ + str(j))

for i in range(self.width):

if map_s[(i, j)] == 1:

self.area.create_rectangle(self.size * i, self.size * j, self.size * (i + 1),

self.size * (j + 1), fill=‘grey‘, tags=‘bottom‘ + str(j))

self.area.update()

# 判断填满遍历map_s每一行的各个元素,若所有元素为1,则标签中score值+10,将

# 此行所有元素改为0,行数map_s(i,j)=map_s(i-1,j)(即所有之上的行下移)

# ,那么后续画底部方块时,可实现消行。

def is_fill(self):

for j in range(self.height):

t = 0

for i in range(self.width):

if map_s[(i, j)] == 1:

t = t + 1

if t == self.width:

self.get_score()

self.delete_line(j)

# 加分 每一行+10

def get_score(self):

score_value = eval(self.scoreLabel2[‘text‘])

score_value += 10

self.scoreLabel2.config(text=str(score_value))

# 消行

def delete_line(self, j):

for t in range(j, 2, -1):

for i in range(self.width):

map_s[(i, t)] = map_s[(i, t - 1)]

for i in range(self.width):

map_s[(i, 0)] = 0

self.draw_bottom()

# 遍历每一行,若从顶部到底部map_s每一行都有某一个元素或更多元素为1,

# 那么说明方块以顶到最上端,游戏结束。此处不可以简单判定最上一行是否有元素为1就判定结束,

# 若这样会产生顶部有新的方块产生,然后导致顶部有元素为1,误判为游戏结束。

def is_over(self):

t = 0

for j in range(self.height):

for i in range(self.width):

if self.map_s[(i, j)] == 1:

t += 1

break

if t >= self.height:

return False

else:

return True

# 先判断方块是否可以旋转(针对其靠近边界时)。先将其现在所在位置对应map_s中的元素改为0,判断其旋

# 转后位置对应map_s中的元素是否有一,若有,说明其旋转后的位置已经被占,是不能旋转的,返回值为False

# 。否则为可旋转,返回值True。若已判定可以旋转,那么访问self.rotateDict,得出旋转以后所有小块的位置

# 变换,将变换以后的位置对应map_s的元素设为1,旋转便已完成。

def can_rotate(self):

for i in range(4):

map_s[((core[0] + getNew[i][0]),

(core[1] + getNew[i][1]))] = 0

for i in range(4):

if map_s[((core[0] + self.rotateDict[getNew[i]][0]),

(core[1] + self.rotateDict[getNew[i]][1]))] == 1:

return False

return True

# 旋转

def rotate(self, event):

if next != 2:

if self.can_rotate():

for i in range(4):

getNew[i] = self.rotateDict[getNew[i]]

self.draw_square()

if not self.can_move():

for i in range(4):

map_s[((core[0] + getNew[i][0]), (core[1] + getNew[i][1]))] = 1

# 先判断是否左移/右移,同样,将方块现在所处位置的map_s中元素设为0,看其移动后的位置上map_s的元素是否有1,

# 若有,说明这一位置已被占据或已到边界,不可移动,返回False。若可移动,返回True。按下左键,若可

# 以移动,核心块的横坐标减1,由于我们只讨论其他小块对于核心块的相对位置,所以其他小块的位置自动随

# 核心块的位置移动而移动。将移动过后的位置对应map_s中的元素设为1。

def can_left(self):

core_now = core

for i in range(4):

map_s[((core_now[0] + getNew[i][0]), (core_now[1] + getNew[i][1]))] = 0

for i in range(4):

if map_s[((core_now[0] + getNew[i][0] - 1), (core_now[1] + getNew[i][1]))] == 1:

return False

return True

# 左移

def move_left(self, event):

if self.can_left():

core[0] -= 1

self.draw_square()

self.draw_bottom()

if not self.can_move():

for i in range(4):

map_s[((core[0] + getNew[i][0]), (core[1] + getNew[i][1]))] = 1

# 判断右移

def can_right(self):

for i in range(4):

map_s[((core[0] + getNew[i][0]), (core[1] + getNew[i][1]))] = 0

for i in range(4):

if map_s[((core[0] + getNew[i][0] + 1), (core[1] + getNew[i][1]))] == 1:

return False

return True

# 右移

def move_right(self, event):

if self.can_right():

core[0] += 1

self.draw_square()

self.draw_bottom()

if not self.can_move():

for i in range(4):

map_s[((core[0] + getNew[i][0]), (core[1] + getNew[i][1]))] = 1

# 初始化中有一self. isFaster 的变量被设为False,当其为False时,

# 程序中的sleep(time)中time的值为0.35,而按下下键,self. isFaster变为True,

# time变成0.05,通过调整sleep()中变量的大小可以调节方块运动的速度。

# 此功能通过if语句实现。

def move_faster(self, event):

self.isFaster = True

if not self.can_move():

for i in range(4):

map_s[((core[0] + getNew[i][0]), (core[1] + getNew[i][1]))] = 1

# run the program

def run(self):

self.draw_bottom()

self.is_fill()

self.draw_new()

# play the game

def play(self):

self.sflag=True

self.startBut.config(state=DISABLED)

global is_pause

is_pause = True

global map_s

map_s = self.map_s

while True:

if self.is_over():

self.run()

else:

break

self.over()

# restart the game

def restart(self):

self.map_s = {}

for i in range(self.width):

for j in range(-4, self.height):

self.map_s[(i, j)] = 0

for i in range(-1, self.width):

self.map_s[(i, self.height)] = 1

for j in range(-4, self.height + 1):

self.map_s[(-1, j)] = 1

self.map_s[(self.width, j)] = 1

self.score = 0

for j in range(self.height):

self.area.delete(‘bottom‘ + str(j))

self.play()

# 结束后告诉用户失败

def over(self):

if self.sflag:

self.ARecord()

self.myRecord()

feedback = messagebox.askquestion("游戏结束!", "再次挑战?")

self.delmyRecord()

if feedback == ‘yes‘:

self.restart()

else:

self.root.destroy()

# 退出

def is_quit(self):

ask_quit = messagebox.askquestion("退出", "保存并退出?")

if ask_quit == ‘yes‘:

if self.sflag:

self.ARecord()

self.myRecord()

self.root.destroy()

exit()

# 判断是否按下restart

def is_restart(self):

ask_restart = messagebox.askquestion("放弃游戏", "确定重新开始?")

if ask_restart == ‘yes‘:

self.delmyRecord()

if self.sflag:

self.ARecord()

self.restart()

else:

return

# 每次一按下暂停键,is_pause = not is_pause,当is_pause = True时,由于之前提到过的if is_pause:语句,

# 方块可以移动,游戏运行。当按下暂停键以后,is_pause值为False,方块将不可移动。同时,is_pause值为False时

# ,暂停键变为开始键,即标签由Pause 改为 Resume,当is_pause值为True时,Resume改为Pause。这一功能由if语句实现。

def is_pause(self):

global is_pause

is_pause = not is_pause

if not is_pause:

self.pauseBut["text"] = "继续"

else:

self.pauseBut["text"] = "暂停"

# 帮助

def rule(self):

rule_top = Toplevel()

rule_top.title(‘帮助‘)

rule_top.geometry(‘800x400‘)

rule = "按下开始进行游戏 使用‘w’‘a’‘s’‘d’或‘↑’‘↓’‘←’‘→’控制."

rule_label = Label(rule_top, text=rule, fg=‘blue‘, font=18)

rule_label.place(x=50, y=50)

# 显示有关信息

def about(self):

about_top = Toplevel()

about_top.title(‘关于‘)

about_top.geometry(‘300x150‘)

about = "俄罗斯方块."

about_label = Label(about_top, font=(‘Curier‘, 20), fg=‘darkblue‘, text=about)

about_label.pack()

#判断txt文件是否存在 不存在创建txt////---------

def create_not_exist(self):

FileName1=‘Record.txt‘

FileName2=‘G_Record.txt‘

if not (os.path.exists(FileName1) and os.path.exists(FileName2)):

f1 = open(FileName1, mode="a", encoding="utf-8")

f2 = open(FileName2, mode="a", encoding="utf-8")

f1.close()

f2.close()

#存入记录////---------

def ARecord(self):

f = open(‘Record.txt‘,‘a‘)

f.write(self.scoreLabel2[‘text‘])

f.write(‘,‘)

f.close()

#排序获得最高的记录//////---------

def getMax(self):

f = open(‘Record.txt‘)

rs=f.read().split(‘,‘)

if rs[0]==‘‘:

maxs=[‘0‘]

else:

del rs[-1]

maxs=list(map(int,rs))

maxs.sort()

maxs.reverse()

f.close()

return maxs

#排行记录////--------

def getSort(self):

sort=str(self.getMax())

ask_restart = messagebox.askquestion(‘排行‘,‘排行:{}‘.format(sort))

#历史所有记录////--------

def getRecord(self):

f = open(‘Record.txt‘)

rs=f.read()

ask_restart = messagebox.askquestion(‘历史记录‘,‘记录:{}‘.format(rs))

f.close()

#窗口右上角叉掉提示//////-------------

def my_close(self):

res = messagebox.askokcancel(‘提示‘, ‘是否关闭窗口‘)

if res == True:

if self.sflag:

self.ARecord()

self.myRecord()

self.root.destroy()

#删除上次记录从零开始

def delmyRecord(self):

f = open(‘G_Record.txt‘, mode="w", encoding="utf-8")

f.close()

self.scoreLabel2.config(text=‘0‘)

#写入上次数据  上次游戏的地图x(myk)与y(myv)坐标以及随机方块到达的位置(sq)/////---------------------------

def myRecord(self):

f = open(‘G_Record.txt‘, mode="w", encoding="utf-8")

myk=str(self.map_s.keys())

myv=str(self.map_s.values())

#核心块

sq=str((core[0], core[1]))

#方块形状

rd=str(next_s)

#上次记录

rc=self.scoreLabel2[‘text‘]

date=myk+myv+‘&‘+sq+rd+‘,‘+rc

f.write(date)

f.close()

#读取上次数据/////---------------------

def rmyRecord(self):

f = open(‘G_Record.txt‘, mode="r", encoding="utf-8")

read=f.read()

if len(read)==0:

kv={}

self.newflag=False

else:

#key value分界下标位置

n=read.index(‘v‘)-5

m=read.index(‘&‘)-1

#字典key坐标x,y,x,y....

listk=[int(k) for k in re.findall(r‘-?\d+‘, read[11:n-2])]

#字典value

listvalue=[int(v) for v in re.findall(r‘\d‘,read[(n+13):m-2])]

x=0

listkey=[]

i=1

for y in listk:

if (i%2)==0:

lk=(x,y)

listkey.append(lk)

else:

x=y

i+=1

kv=dict(zip(listkey,listvalue))

f.close()

return kv

#返回上次的方块(列表)核心坐标

def rmysq(self):

f = open(‘G_Record.txt‘, mode="r", encoding="utf-8")

read=f.read()

if len(read)==0:

mysq=[]

else:

n=read.index(‘&‘)

mysq=[int(k) for k in re.findall(r‘-?\d+‘, read[n:])]

f.close()

return mysq

def mainloop(self):

self.root.protocol(‘WM_DELETE_WINDOW‘, self.my_close)

self.root.mainloop()

def main():

russia_block = RussiaBlock()

russia_block.mainloop()

main()

五、项目总结

5.1 特点

5.2 不足之处

原文地址:https://www.cnblogs.com/kbqhs/p/12081677.html

时间: 2024-08-24 21:31:47

基于python的俄罗斯方块小游戏的相关文章

C语言俄罗斯方块小游戏练习

.title { text-align: center; margin-bottom: .2em } .subtitle { text-align: center; font-size: medium; font-weight: bold; margin-top: 0 } .todo { font-family: monospace; color: red } .done { font-family: monospace; color: green } .priority { font-fami

java swing开发短小精悍的俄罗斯方块小游戏源代码下载,仅300行代码

原文:java swing开发短小精悍的俄罗斯方块小游戏源代码下载,仅300行代码 源代码下载地址:http://www.zuidaima.com/share/1550463495146496.htm java swing开发短小精悍的俄罗斯方块小游戏源代码下载,仅300行代码, 很久以前找到的一个Swing实现的俄罗斯方块,短线精悍,算法值得一看 经验证代码可用,确实短小精悍,值得下载. package com.zuidaima.swing.game; import java.awt.*; i

用Python写一个小游戏

刚学Python时间不长,但也知道了一点,看别人的参考写了一个猜数字小游戏,也算是禹学于乐吧. #!/usr/bin/env   python #coding=utf-8 import random secret = random.randint(1,100) guess,tries = 0,0 print u"已经给出了一个1-99的数字" while guess != secret and tries < 5: print u"请给出你猜的数字:" pri

软件设计之基于Java的连连看小游戏(一)——开题及游戏首页的制作

原本计划紧张忙碌的考试月在图书馆和实验室度过,结果突如其来为期两周的软件设计把课余时间几乎捆绑在了机房.软设没有太多知识上的要求,只要成品简洁美观.实用准确即可.考虑了很久决定要用Java swing做一个完善的连连看小游戏. (一)工作计划安排: 1.16周完成游戏界面的制作以及图形消除功能的实现. 2.17周完成连线的显示以及菜单功能的实现(退出.再来一局等功能),并进行界面及性能的优化. 今天第一天确定了具体的实施方案,决定了游戏界面要达到的效果,并开始着手制作游戏首页的界面. (二)目前

基于pygame的一个小游戏

class GameStats(): """跟踪游戏的统计信息""" #def __int__(self, ai_settings): def __init__(self, ai_settings): """初始化统计信息""" self.ai_settings = ai_settings self.reset_stats() # 让游戏 处于非活动状态 self.game_active

基于python一个分发小脚本

基于paramiko分发公钥到其他机器,有不足的地方还望见谅 #-*- coding: utf-8 -*- #!/usr/bin/python  import os import paramiko import threading data='ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAvQfqvW1JjYhRVgqYjBCLsTWNx0q/X+IcHdATG0MvJ5Nrew08eoEiy4/rScsUiQaMLaIApTa0Smn5Yg9vP0Z4ESfqMEye

Python 基础实战 -- 小游戏之猜数字

1 import random 2 3 secret = random.randint(1,10) #随机一个数字作为答案 4 value = secret + random.randint(100,1000) #随便给一个值,防止重复 5 count = 3 #剩余游戏次数 6 while not secret == value: 7 count -= 1 8 try: 9 temp = input("请输入一个数值:") 10 if not temp.isdigit() or te

Python猜数小游戏

[游戏规则]生成一个指定范围的随机数(如:1-100),然后玩家输入数值猜答案,屏幕会根据玩家输入的数字给出大小提示,一直到玩家猜出准确答案则游戏胜利并结束. import  random answer=random.randint(1,100) n=int(input("Please input num: ")) while n!=answer :       if n>answer:           n = int(input("Num is Big! Plea

Python学习-55 小游戏- 猜大小

#游戏开始,首先玩家选择大小,选择完成后开始摇骰子(11<=总值<=18为大,3<=总值<=10为小) import random def roll_dice(numbers=3,points=None): # 创建3个筛子numbers,创建点数points print('<<<<roll the dice!>>>>') if points is None: points = [] # 把点数放到一个空的列表里 while numb