from PyQt5.QtWidgets import QMainWindow, QFrame, QDesktopWidget, QApplication
from PyQt5.QtCore import Qt, QBasicTimer, pyqtSignal
from PyQt5.QtGui import QPainter, QColor
import sys, random class Tetris(QMainWindow): def __init__(self):
super().__init__() self.initUI() def initUI(self):
'''initiates application UI''' self.tboard = Board(self)
self.setCentralWidget(self.tboard) self.statusbar = self.statusBar()
self.tboard.msg2Statusbar[str].connect(self.statusbar.showMessage) self.tboard.start() self.resize(, )
self.center()
self.setWindowTitle('Tetris')
self.show() def center(self):
'''centers the window on the screen''' screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width()-size.width())/,
(screen.height()-size.height())/) class Board(QFrame): msg2Statusbar = pyqtSignal(str) BoardWidth =
BoardHeight =
Speed = def __init__(self, parent):
super().__init__(parent) self.initBoard() def initBoard(self):
'''initiates board''' self.timer = QBasicTimer()
self.isWaitingAfterLine = False self.curX =
self.curY =
self.numLinesRemoved =
self.board = [] self.setFocusPolicy(Qt.StrongFocus)
self.isStarted = False
self.isPaused = False
self.clearBoard() def shapeAt(self, x, y):
'''determines shape at the board position''' return self.board[(y * Board.BoardWidth) + x] def setShapeAt(self, x, y, shape):
'''sets a shape at the board''' self.board[(y * Board.BoardWidth) + x] = shape def squareWidth(self):
'''returns the width of one square''' return self.contentsRect().width() // Board.BoardWidth def squareHeight(self):
'''returns the height of one square''' return self.contentsRect().height() // Board.BoardHeight def start(self):
'''starts game''' if self.isPaused:
return self.isStarted = True
self.isWaitingAfterLine = False
self.numLinesRemoved =
self.clearBoard() self.msg2Statusbar.emit(str(self.numLinesRemoved)) self.newPiece()
self.timer.start(Board.Speed, self) def pause(self):
'''pauses game''' if not self.isStarted:
return self.isPaused = not self.isPaused if self.isPaused:
self.timer.stop()
self.msg2Statusbar.emit("paused") else:
self.timer.start(Board.Speed, self)
self.msg2Statusbar.emit(str(self.numLinesRemoved)) self.update() def paintEvent(self, event):
'''paints all shapes of the game''' painter = QPainter(self)
rect = self.contentsRect() boardTop = rect.bottom() - Board.BoardHeight * self.squareHeight() for i in range(Board.BoardHeight):
for j in range(Board.BoardWidth):
shape = self.shapeAt(j, Board.BoardHeight - i - ) if shape != Tetrominoe.NoShape:
self.drawSquare(painter,
rect.left() + j * self.squareWidth(),
boardTop + i * self.squareHeight(), shape) if self.curPiece.shape() != Tetrominoe.NoShape: for i in range(): x = self.curX + self.curPiece.x(i)
y = self.curY - self.curPiece.y(i)
self.drawSquare(painter, rect.left() + x * self.squareWidth(),
boardTop + (Board.BoardHeight - y - ) * self.squareHeight(),
self.curPiece.shape()) def keyPressEvent(self, event):
'''processes key press events''' if not self.isStarted or self.curPiece.shape() == Tetrominoe.NoShape:
super(Board, self).keyPressEvent(event)
return key = event.key() if key == Qt.Key_P:
self.pause()
return if self.isPaused:
return elif key == Qt.Key_Left:
self.tryMove(self.curPiece, self.curX - , self.curY) elif key == Qt.Key_Right:
self.tryMove(self.curPiece, self.curX + , self.curY) elif key == Qt.Key_Down:
self.tryMove(self.curPiece.rotateRight(), self.curX, self.curY) elif key == Qt.Key_Up:
self.tryMove(self.curPiece.rotateLeft(), self.curX, self.curY) elif key == Qt.Key_Space:
self.dropDown() elif key == Qt.Key_D:
self.oneLineDown() else:
super(Board, self).keyPressEvent(event) def timerEvent(self, event):
'''handles timer event''' if event.timerId() == self.timer.timerId(): if self.isWaitingAfterLine:
self.isWaitingAfterLine = False
self.newPiece()
else:
self.oneLineDown() else:
super(Board, self).timerEvent(event) def clearBoard(self):
'''clears shapes from the board''' for i in range(Board.BoardHeight * Board.BoardWidth):
self.board.append(Tetrominoe.NoShape) def dropDown(self):
'''drops down a shape''' newY = self.curY while newY > : if not self.tryMove(self.curPiece, self.curX, newY - ):
break newY -= self.pieceDropped() def oneLineDown(self):
'''goes one line down with a shape''' if not self.tryMove(self.curPiece, self.curX, self.curY - ):
self.pieceDropped() def pieceDropped(self):
'''after dropping shape, remove full lines and create new shape''' for i in range(): x = self.curX + self.curPiece.x(i)
y = self.curY - self.curPiece.y(i)
self.setShapeAt(x, y, self.curPiece.shape()) self.removeFullLines() if not self.isWaitingAfterLine:
self.newPiece() def removeFullLines(self):
'''removes all full lines from the board''' numFullLines =
rowsToRemove = [] for i in range(Board.BoardHeight): n =
for j in range(Board.BoardWidth):
if not self.shapeAt(j, i) == Tetrominoe.NoShape:
n = n + if n == :
rowsToRemove.append(i) rowsToRemove.reverse() for m in rowsToRemove: for k in range(m, Board.BoardHeight):
for l in range(Board.BoardWidth):
self.setShapeAt(l, k, self.shapeAt(l, k + )) numFullLines = numFullLines + len(rowsToRemove) if numFullLines > : self.numLinesRemoved = self.numLinesRemoved + numFullLines
self.msg2Statusbar.emit(str(self.numLinesRemoved)) self.isWaitingAfterLine = True
self.curPiece.setShape(Tetrominoe.NoShape)
self.update() def newPiece(self):
'''creates a new shape''' self.curPiece = Shape()
self.curPiece.setRandomShape()
self.curX = Board.BoardWidth // 2 + 1
self.curY = Board.BoardHeight - + self.curPiece.minY() if not self.tryMove(self.curPiece, self.curX, self.curY): self.curPiece.setShape(Tetrominoe.NoShape)
self.timer.stop()
self.isStarted = False
self.msg2Statusbar.emit("Game over") def tryMove(self, newPiece, newX, newY):
'''tries to move a shape''' for i in range(): x = newX + newPiece.x(i)
y = newY - newPiece.y(i) if x < or x >= Board.BoardWidth or y < or y >= Board.BoardHeight:
return False if self.shapeAt(x, y) != Tetrominoe.NoShape:
return False self.curPiece = newPiece
self.curX = newX
self.curY = newY
self.update() return True def drawSquare(self, painter, x, y, shape):
'''draws a square of a shape''' colorTable = [0x000000, 0xCC6666, 0x66CC66, 0x6666CC,
0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00] color = QColor(colorTable[shape])
painter.fillRect(x + , y + , self.squareWidth() - ,
self.squareHeight() - , color) painter.setPen(color.lighter())
painter.drawLine(x, y + self.squareHeight() - , x, y)
painter.drawLine(x, y, x + self.squareWidth() - , y) painter.setPen(color.darker())
painter.drawLine(x + , y + self.squareHeight() - ,
x + self.squareWidth() - , y + self.squareHeight() - )
painter.drawLine(x + self.squareWidth() - ,
y + self.squareHeight() - , x + self.squareWidth() - , y + ) class Tetrominoe(object): NoShape =
ZShape =
SShape =
LineShape =
TShape =
SquareShape =
LShape =
MirroredLShape = class Shape(object): coordsTable = (
((, ), (, ), (, ), (, )),
((, -), (, ), (-, ), (-, )),
((, -), (, ), (, ), (, )),
((, -), (, ), (, ), (, )),
((-, ), (, ), (, ), (, )),
((, ), (, ), (, ), (, )),
((-, -), (, -), (, ), (, )),
((, -), (, -), (, ), (, ))
) def __init__(self): self.coords = [[,] for i in range()]
self.pieceShape = Tetrominoe.NoShape self.setShape(Tetrominoe.NoShape) def shape(self):
'''returns shape''' return self.pieceShape def setShape(self, shape):
'''sets a shape''' table = Shape.coordsTable[shape] for i in range():
for j in range():
self.coords[i][j] = table[i][j] self.pieceShape = shape def setRandomShape(self):
'''chooses a random shape''' self.setShape(random.randint(, )) def x(self, index):
'''returns x coordinate''' return self.coords[index][] def y(self, index):
'''returns y coordinate''' return self.coords[index][] def setX(self, index, x):
'''sets x coordinate''' self.coords[index][] = x def setY(self, index, y):
'''sets y coordinate''' self.coords[index][] = y def minX(self):
'''returns min x value''' m = self.coords[][]
for i in range():
m = min(m, self.coords[i][]) return m def maxX(self):
'''returns max x value''' m = self.coords[][]
for i in range():
m = max(m, self.coords[i][]) return m def minY(self):
'''returns min y value''' m = self.coords[][]
for i in range():
m = min(m, self.coords[i][]) return m def maxY(self):
'''returns max y value''' m = self.coords[][]
for i in range():
m = max(m, self.coords[i][]) return m def rotateLeft(self):
'''rotates shape to the left''' if self.pieceShape == Tetrominoe.SquareShape:
return self result = Shape()
result.pieceShape = self.pieceShape for i in range(): result.setX(i, self.y(i))
result.setY(i, -self.x(i)) return result def rotateRight(self):
'''rotates shape to the right''' if self.pieceShape == Tetrominoe.SquareShape:
return self result = Shape()
result.pieceShape = self.pieceShape for i in range(): result.setX(i, -self.y(i))
result.setY(i, self.x(i)) return result if __name__ == '__main__': app = QApplication([])
tetris = Tetris()
sys.exit(app.exec_())

pyqt 实现的俄罗斯方块的更多相关文章

  1. 【转载】Pyqt 编写的俄罗斯方块

    #!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import print_function from __future__ ...

  2. Python应用03 使用PyQT制作视频播放器

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁任何形式转载. 最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/ ...

  3. arcpy+PyQt+py2exe快速开发桌面端ArcGIS应用程序

    前段时间有一个项目,大体是要做一个GIS数据处理工具. 一般的方法是基于ArcObjects来进行开发,因为我对ArcObjects不太熟悉,所以就思考有没有其他简单快速的方法来做. 在查看ArcGI ...

  4. 还是俄罗斯方块之android版

    前面的,口水话 请直接跳过. 虽然现在不比以前了 也没多少人气了,放到首页 都不到几百的点击量.也许博客园整体水平也是在往水的方向发展.不谈那些了,哥也曾经辉煌过 有过一天上千的点击量 ,哥也曾经有过 ...

  5. x01.Tetris: 俄罗斯方块

    最强大脑有个小孩玩俄罗斯方块游戏神乎其技,那么,就写一个吧,玩玩而已. 由于逻辑简单,又作了一些简化,所以代码并不多. using System; using System.Collections.G ...

  6. 俄罗斯方块C#版

    using System; using System.Windows.Forms; using System.Drawing; using System.Media; class me : Form ...

  7. 纯JS实现俄罗斯方块,打造属于你的游戏帝国

    纯JS俄罗斯方块,打造属于你的游戏帝国. 本文原始作者博客 http://www.cnblogs.com/toutou 俄罗斯方块(Tetris, 俄文:Тетрис)是一款电视游戏机和掌上游戏机游戏 ...

  8. Pyqt 基础功能

    总结Pyqt的基础知识 1. Pyqt  设置禁止最大化及禁止拖拽窗口大小 # PyQT禁止窗口最大化按钮: self.setWindowFlags(QtCore.Qt.WindowMinimizeB ...

  9. 模拟提交API数据Pyqt版

    其实这个模拟提交数据之前已经写过篇: Python requests模拟登录 因为现在在做的项目中需要一个debug请求调试API,用PHP的CURL写了一个,又因Pyqt更能直观灵活的显示请求的参数 ...

随机推荐

  1. win10 java环境变量的正确配置

    变量名:[JAVA_HOME]变量值:[D:\Program Files\Java\jdk1.8.0_92][jdk安装路径]变量名:[Path]变量值:[;%JAVA_HOME%\bin;%JAVA ...

  2. matplotlib —— 调整坐标轴

    import matplotlib.pyplot as plt import numpy as np # 绘制普通图像 x = np.linspace(-1, 1, 50) y1 = 2 * x + ...

  3. collections模块(收藏)

    collections是Python内建的一个集合模块,提供了许多有用的集合类. 1. namedtuple 我们知道tuple可以表示不变集合,例如,一个点的二维坐标就可以表示成: >> ...

  4. [redis] 介绍安装

    redis相关网站 官方网站:http://redis.io/ redis简介 官方介绍:http://redis.io/topics/introduction 百度百科:http://baike.b ...

  5. JS 数组和对象的遍历方式,以及几种方式的比较。

    通常我们会用循环的方式来遍历数组.但是循环是 导致js 性能问题的原因之一.一般我们会采用下几种方式来进行数组的遍历: 方式1: for in 循环: var arr = [1,2,3,4,5]; v ...

  6. redis的5种数据结构的使用场景介绍

    一.redis 数据结构使用场景 原来看过 redisbook 这本书,对 redis 的基本功能都已经熟悉了,从上周开始看 redis 的源码.目前目标是吃透 redis 的数据结构.我们都知道,在 ...

  7. bootstrap modal 垂直居中对齐

    bootstrap modal 垂直居中对齐   文章参考 http://www.bubuko.com/infodetail-666582.html http://v3.bootcss.com/Jav ...

  8. 终端FQ

    前言我一直以为全局FQ就是所有的都能够自由访问,没想到终端有时候却不行,这里终端一般指的是window的cmd和mac的Terminal.终端一般程序员用的比较多,下载第三方依赖啊,都需要,所以我总结 ...

  9. Hdu dp

    4856 这题说的是给了一个图 这个图有很多的隧道每个隧道是单向的 只能从一个入口进入从另一个入口出来 要求计算出走完这些隧道花的总时间 因为这个图是一个网格行的然后 先用bfs算出隧道的出口到每个隧 ...

  10. suse zypper 添加源

    一.查看源和仓库 1.查看repos (软件仓库) zypper lr 2.查看services(软件源) zypper ls 二.删除源和仓库 1.删除软件仓库 zypper rr name 2.删 ...