#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import
try:
str = unicode
except NameError:
pass import random, sys, sip
try:
sip.setapi("QString" ,2)
except ValueError:
pass from PyQt4 import QtCore, QtGui NoShape, ZShape, SShape, LineShape, TShape, SquareShape, LShape, MirroredLShape = range(8) random.seed(None) class TetrixWindow(QtGui.QWidget):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent, QtCore.Qt.Window) self.board = TetrixBoard()
self.indictor = TetrixIndictor() nextPieceLabel = QtGui.QLabel(self)
nextPieceLabel.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Raised)
nextPieceLabel.setAlignment(QtCore.Qt.AlignCenter)
self.board.setNextPieceLabel(nextPieceLabel) scoreLcd = QtGui.QLCDNumber(6)
scoreLcd.setSegmentStyle(QtGui.QLCDNumber.Filled)
levelLcd = QtGui.QLCDNumber(2)
levelLcd.setSegmentStyle(QtGui.QLCDNumber.Filled)
linesLcd = QtGui.QLCDNumber(6)
linesLcd.setSegmentStyle(QtGui.QLCDNumber.Filled) startButton = QtGui.QPushButton(self.trUtf8("开始(&S)"))
startButton.setFocusPolicy(QtCore.Qt.NoFocus)
quitButton = QtGui.QPushButton(self.trUtf8("退出(&X)"))
quitButton.setFocusPolicy(QtCore.Qt.NoFocus)
pauseButton = QtGui.QPushButton(self.trUtf8("暂停(&P)"))
pauseButton.setFocusPolicy(QtCore.Qt.NoFocus) startButton.clicked.connect(self.board.start)
pauseButton.clicked.connect(self.board.pause)
quitButton.clicked.connect(self.close)
self.board.scoreChanged.connect(scoreLcd.display)
self.board.levelChanged.connect(levelLcd.display)
self.board.linesRemovedChanged.connect(linesLcd.display)
self.board.act.connect(self.indictor.showIndictor) layout1 = QtGui.QHBoxLayout()
layout3 = QtGui.QVBoxLayout()
layout3.addWidget(self.board)
layout3.addWidget(self.indictor)
layout3.setSpacing(0)
layout1.addLayout(layout3)
layout2 = QtGui.QVBoxLayout()
layout2.addWidget(self.createLabel(self.trUtf8("下一个方块")))
layout2.addWidget(nextPieceLabel)
layout2.addWidget(self.createLabel(self.trUtf8("级别")))
layout2.addWidget(levelLcd)
layout2.addWidget(self.createLabel(self.trUtf8("成绩")),)
layout2.addWidget(scoreLcd)
layout2.addWidget(self.createLabel(self.trUtf8("总共消去行数")))
layout2.addWidget(linesLcd)
layout2.addWidget(startButton)
layout2.addWidget(quitButton)
layout2.addWidget(pauseButton)
layout1.addLayout(layout2)
layout1.setStretch(0, 75)
layout1.setStretch(1, 25)
self.setLayout(layout1) self.setWindowTitle(self.trUtf8("俄罗斯方块(Tetrix)"))
self.resize(self.logicalDpiX() / 96 * 275, self.logicalDpiY() / 96 * 380) r = self.geometry()
r.moveCenter(QtGui.qApp.desktop().screenGeometry().center())
self.setGeometry(r) def createLabel(self, text):
lbl = QtGui.QLabel(text)
lbl.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom)
return lbl class TetrixIndictor(QtGui.QWidget):
"""位于主游戏区下方的一个扁小的控件,用于显示当前位置落下时的位置。
现在主要的问题是游戏区的大小超出了人类的眼睛的焦点区。
或许可以让整个游戏界面更小一些。""" def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.begin = self.end = None
self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) def showIndictor(self, curX, piece):
self.begin = curX + piece.minX()
self.end = curX + piece.maxX()
self.update() def paintEvent(self, event):
QtGui.QWidget.paintEvent(self, event)
if self.begin is None:
return
board = self.parent().board
pieceWidth = board.contentsRect().width() // TetrixBoard.BoardWidth
brush = QtGui.QBrush(QtCore.Qt.yellow)
painter = QtGui.QPainter(self)
painter.setBrush(brush)
painter.drawRect(board.contentsRect().left() + self.begin * pieceWidth, 0, \
(self.end - self.begin + 1) * pieceWidth, self.height() - 1 ) def sizeHint(self):
return QtCore.QSize(self.parent().board.width(), 8) class TetrixBoard(QtGui.QFrame):
BoardWidth = 11
BoardHeight = 22 scoreChanged = QtCore.pyqtSignal(int)
levelChanged = QtCore.pyqtSignal(int)
linesRemovedChanged = QtCore.pyqtSignal(int)
act = QtCore.pyqtSignal(int, "PyQt_PyObject") def __init__(self, parent = None):
super(TetrixBoard, self).__init__(parent)
self.setStyleSheet("background-color:black;border:2px solid darkGreen;") self.timer = QtCore.QBasicTimer()
self.nextPieceLabel = None
self.isWaitingAfterLine = False
self.curPiece = TetrixPiece()
self.nextPiece = TetrixPiece()
self.curX = 0
self.curY = 0
self.numLinesRemoved = 0
self.numPiecesDropped = 0
self.score = 0
self.level = 0
self.board = None #self.setFrameStyle(QtGui.QFrame.Panel | QtGui.QFrame.Sunken)
self.setFrameStyle(QtGui.QFrame.Box)
self.setFocusPolicy(QtCore.Qt.StrongFocus)
self.isStarted = False
self.isPaused = False
self.clearBoard() self.nextPiece.setRandomShape() def focusOutEvent(self, event):
if self.isStarted and not self.isPaused:
self.pause()
QtGui.QFrame.focusOutEvent(self, event) def shapeAt(self, x, y):
return self.board[(y * TetrixBoard.BoardWidth) + x] def setShapeAt(self, x, y, shape):
self.board[(y * TetrixBoard.BoardWidth) + x] = shape def timeoutTime(self):
return 1000 // (1 + self.level) def squareWidth(self):
return self.contentsRect().width() // TetrixBoard.BoardWidth def squareHeight(self):
return self.contentsRect().height() // TetrixBoard.BoardHeight def setNextPieceLabel(self, label):
self.nextPieceLabel = label
#label.setScaledContents(True)
label.setMinimumSize(label.width(), label.width()) def sizeHint(self):
return QtCore.QSize(TetrixBoard.BoardWidth * 15 + self.frameWidth() * 2,
TetrixBoard.BoardHeight * 15 + self.frameWidth() * 2) def minimumSizeHint(self):
return QtCore.QSize(TetrixBoard.BoardWidth * 15 + self.frameWidth() * 2,
TetrixBoard.BoardHeight * 15 + self.frameWidth() * 2) def start(self):
if self.isPaused:
return self.isStarted = True
self.isWaitingAfterLine = False
self.numLinesRemoved = 0
self.numPiecesDropped = 0
self.score = 0
self.level = 1
self.clearBoard() self.linesRemovedChanged.emit(self.numLinesRemoved)
self.scoreChanged.emit(self.score)
self.levelChanged.emit(self.level) self.newPiece()
self.timer.start(self.timeoutTime(), self) def pause(self):
if not self.isStarted:
return self.isPaused = not self.isPaused
if self.isPaused:
self.timer.stop()
else:
self.timer.start(self.timeoutTime(), self) self.update() def paintEvent(self, event):
super(TetrixBoard, self).paintEvent(event) painter = QtGui.QPainter(self)
rect = self.contentsRect() if self.isPaused:
painter.drawText(rect, QtCore.Qt.AlignCenter, self.trUtf8("暂停"))
return boardTop = rect.bottom() - TetrixBoard.BoardHeight * self.squareHeight() for i in range(TetrixBoard.BoardHeight):
for j in range(TetrixBoard.BoardWidth):
shape = self.shapeAt(j, TetrixBoard.BoardHeight - i - 1)
if shape != NoShape:
self.drawSquare(painter,
rect.left() + j * self.squareWidth(),
boardTop + i * self.squareHeight(), shape) if self.curPiece.shape() != NoShape:
for i in range(4):
x = self.curX + self.curPiece.x(i)
y = self.curY - self.curPiece.y(i)
self.drawSquare(painter, rect.left() + x * self.squareWidth(),
boardTop + (TetrixBoard.BoardHeight - y - 1) * self.squareHeight(),
self.curPiece.shape()) def keyPressEvent(self, event):
if not self.isStarted or self.isPaused or self.curPiece.shape() == NoShape:
super(TetrixBoard, self).keyPressEvent(event)
return key = event.key()
if key == QtCore.Qt.Key_Left:
self.tryMove(self.curPiece, self.curX - 1, self.curY)
elif key == QtCore.Qt.Key_Right:
self.tryMove(self.curPiece, self.curX + 1, self.curY)
elif key == QtCore.Qt.Key_Down:
self.tryMove(self.curPiece.rotatedRight(), self.curX, self.curY)
elif key == QtCore.Qt.Key_Up:
self.tryMove(self.curPiece.rotatedLeft(), self.curX, self.curY)
elif key == QtCore.Qt.Key_Space:
self.dropDown()
elif key == QtCore.Qt.Key_D:
self.oneLineDown()
else:
super(TetrixBoard, self).keyPressEvent(event) def timerEvent(self, event):
if event.timerId() == self.timer.timerId():
if self.isWaitingAfterLine:
self.isWaitingAfterLine = False
self.newPiece()
self.timer.start(self.timeoutTime(), self)
else:
self.oneLineDown()
else:
super(TetrixBoard, self).timerEvent(event) def clearBoard(self):
self.board = [NoShape for i in range(TetrixBoard.BoardHeight * TetrixBoard.BoardWidth)] def dropDown(self):
dropHeight = 0
newY = self.curY
while newY > 0:
if not self.tryMove(self.curPiece, self.curX, newY - 1):
break
newY -= 1
dropHeight += 1 self.pieceDropped(dropHeight) def oneLineDown(self):
if not self.tryMove(self.curPiece, self.curX, self.curY - 1):
self.pieceDropped(0) def pieceDropped(self, dropHeight):
for i in range(4):
x = self.curX + self.curPiece.x(i)
y = self.curY - self.curPiece.y(i)
self.setShapeAt(x, y, self.curPiece.shape()) self.numPiecesDropped += 1
if self.numPiecesDropped % 25 == 0:
self.level += 1
self.timer.start(self.timeoutTime(), self)
self.levelChanged.emit(self.level) self.score += dropHeight + 7
self.scoreChanged.emit(self.score)
self.removeFullLines() if not self.isWaitingAfterLine:
self.newPiece() def removeFullLines(self):
numFullLines = 0 for i in range(TetrixBoard.BoardHeight - 1, -1, -1):
lineIsFull = True for j in range(TetrixBoard.BoardWidth):
if self.shapeAt(j, i) == NoShape:
lineIsFull = False
break if lineIsFull:
numFullLines += 1
for k in range(i, TetrixBoard.BoardHeight - 1):
for j in range(TetrixBoard.BoardWidth):
self.setShapeAt(j, k, self.shapeAt(j, k + 1)) for j in range(TetrixBoard.BoardWidth):
self.setShapeAt(j, TetrixBoard.BoardHeight - 1, NoShape) if numFullLines > 0:
self.numLinesRemoved += numFullLines
self.score += 10 * numFullLines
self.linesRemovedChanged.emit(self.numLinesRemoved)
self.scoreChanged.emit(self.score) self.timer.start(200, self)
self.isWaitingAfterLine = True
self.curPiece.setShape(NoShape)
self.update() def newPiece(self):
self.curPiece = self.nextPiece
self.nextPiece = TetrixPiece()
self.nextPiece.setRandomShape()
self.showNextPiece()
self.curX = TetrixBoard.BoardWidth // 2
self.curY = TetrixBoard.BoardHeight - 1 + self.curPiece.minY()
self.act.emit(self.curX, self.curPiece) if not self.tryMove(self.curPiece, self.curX, self.curY):
self.curPiece.setShape(NoShape)
self.timer.stop()
self.isStarted = False def showNextPiece(self):
if self.nextPieceLabel is None:
return dx = self.nextPiece.maxX() - self.nextPiece.minX() + 1
dy = self.nextPiece.maxY() - self.nextPiece.minY() + 1 self.pixmapNextPiece = QtGui.QPixmap(dx * self.squareWidth(), dy * self.squareHeight())
painter = QtGui.QPainter(self.pixmapNextPiece)
painter.fillRect(self.pixmapNextPiece.rect(), self.nextPieceLabel.palette().background()) for i in range(4):
x = self.nextPiece.x(i) - self.nextPiece.minX()
y = self.nextPiece.y(i) - self.nextPiece.minY()
self.drawSquare(painter, x * self.squareWidth(),
y * self.squareHeight(), self.nextPiece.shape()) self.nextPieceLabel.setPixmap(self.pixmapNextPiece) def tryMove(self, newPiece, newX, newY):
for i in range(4):
x = newX + newPiece.x(i)
y = newY - newPiece.y(i)
if x < 0 or x >= TetrixBoard.BoardWidth or y < 0 or y >= TetrixBoard.BoardHeight:
return False
if self.shapeAt(x, y) != NoShape:
return False self.curPiece = newPiece
self.curX = newX
self.curY = newY
self.update()
self.act.emit(self.curX, self.curPiece)
return True def drawSquare(self, painter, x, y, shape):
colorTable = [0x000000, 0xCC6666, 0x66CC66, 0x6666CC,
0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00] color = QtGui.QColor(colorTable[shape])
painter.fillRect(x + 1, y + 1, self.squareWidth() - 2,
self.squareHeight() - 2, color) painter.setPen(color.light())
painter.drawLine(x, y + self.squareHeight() - 1, x, y)
painter.drawLine(x, y, x + self.squareWidth() - 1, y) painter.setPen(color.dark())
painter.drawLine(x + 1, y + self.squareHeight() - 1,
x + self.squareWidth() - 1, y + self.squareHeight() - 1)
painter.drawLine(x + self.squareWidth() - 1,
y + self.squareHeight() - 1, x + self.squareWidth() - 1, y + 1) class TetrixPiece(object):
coordsTable = (
((0, 0), (0, 0), (0, 0), (0, 0)),
((0, -1), (0, 0), ( - 1, 0), ( - 1, 1)),
((0, -1), (0, 0), (1, 0), (1, 1)),
((0, -1), (0, 0), (0, 1), (0, 2)),
(( - 1, 0), (0, 0), (1, 0), (0, 1)),
((0, 0), (1, 0), (0, 1), (1, 1)),
(( - 1, -1), (0, -1), (0, 0), (0, 1)),
((1, -1), (0, -1), (0, 0), (0, 1))
) def __init__(self):
self.coords = [[0,0] for _ in range(4)]
self.pieceShape = NoShape self.setShape(NoShape) def shape(self):
return self.pieceShape def setShape(self, shape):
table = TetrixPiece.coordsTable[shape]
for i in range(4):
for j in range(2):
self.coords[i][j] = table[i][j] self.pieceShape = shape def setRandomShape(self):
self.setShape(random.randint(1, 7)) def x(self, index):
return self.coords[index][0] def y(self, index):
return self.coords[index][1] def setX(self, index, x):
self.coords[index][0] = x def setY(self, index, y):
self.coords[index][1] = y def minX(self):
m = self.coords[0][0]
for i in range(4):
m = min(m, self.coords[i][0]) return m def maxX(self):
m = self.coords[0][0]
for i in range(4):
m = max(m, self.coords[i][0]) return m def minY(self):
m = self.coords[0][1]
for i in range(4):
m = min(m, self.coords[i][1]) return m def maxY(self):
m = self.coords[0][1]
for i in range(4):
m = max(m, self.coords[i][1]) return m def rotatedLeft(self):
if self.pieceShape == SquareShape:
return self result = TetrixPiece()
result.pieceShape = self.pieceShape
for i in range(4):
result.setX(i, self.y(i))
result.setY(i, -self.x(i)) return result def rotatedRight(self):
if self.pieceShape == SquareShape:
return self result = TetrixPiece()
result.pieceShape = self.pieceShape
for i in range(4):
result.setX(i, -self.y(i))
result.setY(i, self.x(i)) return result if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = TetrixWindow()
window.show()
if hasattr(app, "exec"):
result = getattr(app, "exec")()
else:
result = getattr(app, "exec_")()
sys.exit(result)

【转载】Pyqt 编写的俄罗斯方块的更多相关文章

  1. 【Python】[技术博客] 如何对使用PYQT编写的GUI文件进行单元测试

    如何对使用PYQT编写的GUI文件进行单元测试 想要对PYQT编写的GUI文件进行单元测试,我们主要用到QTest QTest里面包含了一些对窗体的各种控件进行模拟操作的函数,通过QTest对窗体进行 ...

  2. 用Shell编写的俄罗斯方块代码

    用Shell编写的俄罗斯方块代码 不得不承认任何一门语言玩6了,啥都能搞出来啊,竟然用Shell编写出来了一个俄罗斯方块游戏的代码,很有意思,这个代码不是我写出来的,不过大家可以下载一下在window ...

  3. 一个VB编写的俄罗斯方块

    'VB语言版俄罗斯方块'Totoo.Aoo34智造(一个人的两个名字),一些方块,很多计算 Const WN As Integer = 10, HN As Integer = 20Const Boxl ...

  4. 转载:pyqt线程间通过 信号/槽 通信

    转自:http://blog.sina.com.cn/s/blog_613d5bb701016qzv.html 信号(singal)与槽(slot)用于对象相互通信,信号:当某个对象的某个事件发生时, ...

  5. 使用PyQT编写界面程序

    使用PyQT比QT好在,可以随时监测函数正确性,省去编译时间 ! 这是个不小的节省. 1. PyQt: 打开对话框 msgbox = QtGui.QMessageBox(self)# 我的语句是 ms ...

  6. [转载]自己编写 php 在线问卷调查程序

        <html> <head> <title>问卷调查</title> <meta http-equiv="Content-Type ...

  7. javascript 60行编写的俄罗斯方块游戏

    转自 http://***/share/1759652641295360.htm <!doctype html><html><head></head>& ...

  8. pyqt 实现的俄罗斯方块

    from PyQt5.QtWidgets import QMainWindow, QFrame, QDesktopWidget, QApplication from PyQt5.QtCore impo ...

  9. PyQt编写Python GUI程序,简易示例

    https://blog.csdn.net/qq_41841569/article/details/81014207

随机推荐

  1. 31 GroupSock(AddressString)——live555源码阅读(四)网络

    31 GroupSock(AddressString)——live555源码阅读(四)网络 31 GroupSock(AddressString)——live555源码阅读(四)网络 简介 Addre ...

  2. js之DOM和事件

    DOM 查找 直接查找 var obj = document.getElementById('i1') 间接查找 文件内容操作: innerText 仅文本 innerHTML 全内容 value i ...

  3. django的信号

    Django中提供了“信号调度”,用于在框架执行操作时解耦.通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者. 1.Django内置信号 Model signals pre_in ...

  4. phpcms不显示验证码

    只需修改./caches/configs/system.php即可 1.本地域名如果是 http://localhost 如果所有的文件都在根目录下(例如apache下的htdocs或www),此时, ...

  5. CentOS6.5安装Tab增强版:bash-completion

    CentOS6.5安装Tab增强版:bash-completion,可补全命令参数: 因为CentOS官方源并不带有bash-completion的包,所以,为了可用yum安装,增加epel的源, 首 ...

  6. 【leetcode】Convert Sorted Array to Binary Search Tree

    Convert Sorted Array to Binary Search Tree Given an array where elements are sorted in ascending ord ...

  7. MySQL key_len 大小的计算

    背景: 当用Explain查看SQL的执行计划时,里面有列显示了 key_len 的值,根据这个值可以判断索引的长度,在组合索引里面可以更清楚的了解到了哪部分字段使用到了索引. 环境: CREATE ...

  8. jQueryUI Datepicker的使用

    jQueryUI Datepicker是一个高度可定制的插件,可以很方便的为你的页面添加日期选择功能,你可以自定义日期的显示格式 以及要使用的语言. 你可以使用键盘的快捷键来驱动datepicker插 ...

  9. 【leetcode】Isomorphic Strings(easy)

    Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the chara ...

  10. xmpp笔记2(客户端到服务器的例子)--xml

    xmpp( 客户端到服务器的例子 ) 1 步:客户端初始流给服务器: <stream:stream xmlns='jabber:client' xmlns:stream='http://ethe ...