不稳定版的python俄罗斯方块

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shuaicenglou3032/article/details/80010856

基于Python2.7,Linux下运行异常

有普通俄罗斯方块的功能以及历史最高分、暂停、重玩功能

本来是在另一台电脑上的,那台电脑不能连接u盘,故本版本是对着稳定版的代码抄的,可能哪里抄错了一些,所以存在bug.

# coding=utf-8
from Tkinter import *
from random import *
try:
    import cPickle as pickle
except ImportError:
    import pickle
import  threading
from time import sleep
import os

#幕布类
class Curtain(object):
    def __init__(self, canvas):
        self.row = 20
        self.col = 10
        self.back = list()
        self.gridBack = list()
        for i in range(0, self.row):
            self.back.insert(i, list())
            self.gridBack.insert(i, list())
        for i in range(0, self.row):
            for j in range(0,self.col):
                self.back[i].insert(j, 0)
                self.gridBack[i].insert(j, canvas.create_rectangle(30 * j, 30 * i, 30 * (j+1), 30 * (i+1)))

#方块类
class Brick(object):
    def __init__(self):
        self.speed = 1     #下落速度
        self.shape = 0
        self.curRow = 0
        self.curCol = 0
        self.down = False
    #生成一个新方块
    def getNewBrick(self, brickConfig):
        self.curBrickNum = randint(0, len(brickConfig)-1)
        self.shape = 0
        self.currBrick = brickConfig[self.curBrickNum][self.shape]
        self.curCol = 0
        self.curRow = 0
        self.down = False

'''
    工具类:
    1.读写配置文件的形状、分数历史记录信息
    2.控制程序暂停、继续、重玩
    3.判断方块是否抵达边界
    4.检测方块生成位置上是否有被占用的格子
'''
class Tool(object):
    def __init__(self):
        self.curr_dir = os.path.dirname(os.path.realpath(__file__))    #取得当前目录的路径
        self.ifPause = False
        self.ifRestart = False

    #暂停
    def pause(self):
        self.ifPause = True

    #继续
    def continu(self):
        self.ifPause = False

    #重玩
    def restart(self):
        self.ifRestart = True
    #判断是否抵达边界,左移则aspect传1,右移传3,下移传4
    def checkIfArriveBorder(self, aspect, brick, back):
        flag = True
        if aspect == 4:         #下,没到下界返回True
            for i in range(0, 3):
                for j in range(0, 3):
                    if brick.currBrick[i][j] != 0 and (
                            brick.curRow + i >= back.row or back.back[brick.curRow + i][brick.curCol + j] !=0):
                        flag = False
                        brick.down = True
                        break
        elif aspect == 3:                   #右
            for i in range(0, 3):
                for j in range(0, 3):
                    if brick.currBrick[j][i] != 0 and (
                            brick.curCol + i >= back.col or back.back[brick.curRow + i][brick.curCol + j] !=0):
                        flag = False
                        break
        elif aspect == 2:       #上,判断变形操作是否会越界
            if brick.curCol < 0:
                brick.curCol = 0
            if brick.curCol + 2 >= back.col:
                brick.curCol = back.col - 3
            if brick.curRow + 2 >= back.row:
                brick.curRow = brick.curRow - 3
        elif aspect == 1:
            for i in range(0, 3):
                for j in range(0, 3):
                    if brick.currBrick[i][j] != 0 and(
                            brick.curCol + i < 0 or back.back[brick.curRow + j][brick.curCol + i] != 0):
                        flag = False
                        break
        else:
            print '未知错误,aspect值=',aspect

    #从文件中读取历史最高分
    def getMaxGrade(self):
        f = open(self.curr_dir + '/grade.txt', 'rb')
        grade = pickle.load(f)  # 反序列化历史最高分的信息
        f.close()
        return grade

    #向文件中写入新的历史最高分
    def updateHistoryGradeMax(self, newMax):
        f = open(self.curr_dir + '/grade.txt', 'wb')
        f.seek(0)
        f.truncate()
        pickle.dump(newMax, f)
        f.close()

    #从配置文件中读取方块的形状并返回读取的值
    def getBrickFromConfig(self):
        _configFile = open(self.curr_dir + '/config.txt', 'rb')
        brick = pickle.load(_configFile)
        _configFile.close()
        return brick

    #检测方块生成位置上是否有被占用的格子,有则返回True,并检查顶层格子是否有方块,有则游戏结束
    def checkIfBeenUse(self, back, brick):
        flag = False
        for i in range(0,3):
            for j in range(0,3):
                if back.back[i][j] == 1 and brick.currBrick[i][j] == 1:
                    flag = True
                    break
            if flag:
                break
        for i in range(0, back.col):
            if back.back[0][i] == 1:
                flag = True
                break
        return flag
class Main(object):
    #实例化类和图形相关的组件
    def _init__(self):
        self.start = True
        self.tool = Tool()
        self.root = Tk()
        self.HistoryScorceMax = self.tool.getMaxGrade()
        self.currGrade = 0
        self.brickConfig = self.tool.getBrickFromConfig()
        self.ifRestart = False
        self.root.title = ('俄罗斯方块v0.1')
        self.root.minsize(400, 600)
        self.frame = Frame(self.root, width=400, height = 600)
        self.frame.place(x=0, y=0)
        self.label = Label(self.root,text='历史最高分')
        self.historyGradeLabel = Label(self.root,text=self.HistoryScorceMax)  #显示历史最高分
        self.label1 = Label(self.root,text='当前分数')
        self.gameInfo = Label(self.root,text='游戏开始',fg='red',font=('times',12,'bold'))
        self.currentGradeLabel = Label(self.root, text=self.currGrade)
        self.button1 = Button(text='暂停', command=self.tool.pause)
        self.button2 = Button(text='继续', command=self.tool.continu)
        self.button3 = Button(text='重玩', command=self.tool.restart)
        self.canvas = Canvas(self.frame, width=300, heigh=600)
        self.button1.place(x=350, y=0)
        self.button2.place(x=350, y=40)
        self.button3.place(x=350, y=80)
        self.label.place(x=304, y=120)
        self.historyGradeLabel.place(x=369, y=120)
        self.currentGradeLabel.place(x=357, y=160)
        self.gameInfo.place(x=304, y=200)
        self.label1.place(x=304, y=160)
        self.back = Curtain(self.canvas)
        self.brick = Brick()
        self.canvas.pack()
    #清屏并重新开始
    def cleanAndRestart(self):
        for i in range(0, self.back.row):            #重置位置信息和颜色
            for j in range(0, self.back.col):
                self.back.back[i][j] = 0
                self.canvas.itemconfig(self.back.gridBack[i][j],fill="white")
        self.brick.getNewBrick(self.brickConfig)     #重置方块
        self.currGrade = 0                         #重置分数
        self.currentGradeLabel.config(text=self.currGrade)
        self.tool.ifRestart = False
        self.gameInfo.config(text="游戏开始")

    #更新当前分数并对比历史最高分,若超过历史最高分刷新历史最高分并写入文件存储
    def updateAndCheckGrade(self):
        self.currGrade += 1
        self.currentGradeLabel.config(text=self.currGrade)
        if self.currGrade > self.HistoryScorceMax:
            self.HistoryScorceMax = self.currGrade
            self.historyGradeLabel.config(text=self.HistoryScorceMax)
            self.tool.updateHistoryGradeMax(self.HistoryScorceMax)
    #检查是否有需要消除的行
    def checkIfNeedRemove(self):
        for i in range(0, self.back.row):
            tag1 = True
            for j in range(0, self.back.col):
                if self.back.back[i][j] == 0:
                    tag1 = False
                    break
            if tag1 == True:
                self.updateAndCheckGrade()
                for m in xrange(i - 1, 0, -1):
                    for n in range(0, self.back.col):
                        self.back.back[m+1][n] = self.back.back[m][n]

    #更新back表中的位置信息
    def updateBackInfo(self):
        for i in range(0, self.back.row):
            for j in range(0, self.back.col):
                if self.back.back[i][j] == 1:
                    self.canvas.itemconfig(self.back.gridBack[i][j], fill="red")
                elif self.back.back[i][j] == 0:
                    self.canvas.itemconfig(self.back.gridBack[i][j], fill="white")
        for i in range(0, len(self.brick.currBrick)):
            for j in range(0, len(self.brick.currBrick[i])):
                if self.brick.currBrick[i][j] == 1:
                    self.canvas.itemconfig(self.back.gridBack[self.brick.curRow+i][self.brick.curCol+j], fill="red")
        #判断方块是否已经运动到达底部
        if self.brick.down:
            for i in range(0, len(self.brick.currBrick)):
                for j in range(0, len(self.brick.currBrick[i])):
                    if self.brick.currBrick[i][j] != 0:
                        self.back.back[self.brick.curRow+i][self.brick.curCol+j] = self.brick.currBrick[i][j]
            #检查整行是否需要消除
            self.checkIfNeedRemove()
            #获得下一个方块
            self.brick.getNewBrick(self.brickConfig)

    #处理键盘事件
    def onKeyBoardEvent(self, event):
        #未开始,不必监听键盘输入
        if self.start == False:
            return
        if self.tool.ifPause:    #暂停时不监听键盘操作
            return
        #记录原来的值
        midCurCol = self.brick.curCol
        midCurRow = self.brick.curRow
        midShape = self.brick.shape
        direction = 0
        midBrick = self.brick.currBrick

        if event.keycode == 37:
            # 左移
            self.brick.curCol -= 1
            direction = 1
        elif event.keycode == 38:
            # 变化方块的形状
            self.brick.shape += 1
            direction = 2
            if self.brick.shape >= 4:
                self.brick.shape = 0
            self.brick.currBrick = self.brickConfig[self.brick.curBrickNum][self.brick.shape]
        elif event.keycode == 39:
            direction = 3
            # 右移
            self.brick.curCol += 1
        elif event.keycode == 40:
            direction = 4
            # 下移
            self.brick.curRow += 1
        if self.tool.checkIfArriveBorder(direction,self.brick,self.back):
            self.brick.curCol = midCurCol
            self.brick.curRow = midCurRow
            self.brick.shape = midShape
            self.brick.currBrick = midBrick
        self.updateBackInfo()
        return True
    #方块向下移动的线程run方法
    def brickDown(self):
        while True:
            if self.start == False:
                print("线程退出")
                break;
            if self.tool.ifRestart:
                print '开始重玩'
                self.cleanAndRestart()
            while self.tool.ifPause:
                if self.tool.ifRestart:
                    self.cleanAndRestart()  #暂停时点击重玩按钮,进入重玩流程
                    self.tool.ifPause = False
                    break
            if self.tool.checkIfBeenUse(self.back,self.brick):
                print('格子被占用,游戏结束')
                self.gameInfo.config(text="游戏结束")
                while True:
                    if self.tool.ifRestart:
                        self.cleanAndRestart()
                        self.tool.ifPause = False
                        break
            else:
                tempRow = self.brick.curRow
                self.brick.curRow += 1
                if self.tool.checkIfArriveBorder(4, self.brick, self.back) == False:
                    self.brick.curRow = tempRow
                self.updateBackInfo()
                sleep(self.brick.speed)
    def __init__(self):
        self._init__()
        self.brick.getNewBrick(self.brickConfig)
        self.downThread = threading.Thread(target=self.brickDown, args=())
        self.downThread.start()
        #监听键盘事件
        self.root.bind("<KeyPress>", self.onKeyBoardEvent)
        self.root.mainloop()
        self.start = False
main = Main()

猜你喜欢

转载自blog.csdn.net/shuaicenglou3032/article/details/80010856