我正在尝试开发图形数独游戏/求解器,以了解有关OOP主体,Python和GUI的更多信息。我决定使用PyQt5,主要是因为我比Pygame更了解这个概念。我的PyQt5有一个问题。我一直在将我的GUI应用程序加载为库,并从终端调用其功能,以便在发生错误时查看错误。它有助于调试。我的问题是,它通常会在打印错误后立即关闭用于运行应用程序的Python终端。有什么方法可以防止这种情况发生?
要进行复制,请下载GSudoku.py和sudoku.py或将其代码复制并粘贴到编辑器中,并以正确的名称保存。将它们放在同一目录中,然后从python shell导入GSudoku。调用GSudoku.Game(),然后在任意一个正方形上单击两次。应该抛出错误,并应该从python shell启动。
GitHub repo上提供了完整的源。 这是GSudoku.py。此版本引发属性错误。:
import sudoku
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget
class sudokuApp(QMainWindow):
def __init__(self):
super(sudokuApp, self).__init__()
self.setWindowTitle('Sudoku')
self.createUI()
self.resizeUI()
self.activateUI()
self.b1 = sudoku.board()
self.activeGrid = 'no active grid'
self.possibleInputs = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def createUI(self): #Create all the buttons, etcetera
#nine columns of buttons, nine buttons to a column
self.grids = [[QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self)],
[QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self)],
[QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self)],
[QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self)],
[QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self)],
[QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self)],
[QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self)],
[QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self)],
[QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self), QPushButton(self)]]
self.setupBtn = QPushButton(self)
self.solveBtn = QPushButton(self)
self.clearBtn = QPushButton(self)
self.setupBtn.setText('Setup')
self.solveBtn.setText('Solve')
self.clearBtn.setText('Clear')
def resizeUI(self, desiredScale = 1): #make them all the right size and scale them properly.
self.scale = desiredScale
self.gridwidth = 40 * self.scale
self.gridheight = 40 * self.scale
self.spacing = 5 * self.scale
self.boardWidth = self.spacing + (9 * (self.spacing + self.gridwidth))
self.boardHeight = self.spacing + (9 * (self.spacing + self.gridheight))
for i in range(9):
for j in range(9):
grid = self.grids[i][j]
grid.setGeometry(self.spacing + (j * (self.spacing + self.gridwidth)), self.spacing + (i * (self.spacing + self.gridheight)), self.gridwidth, self.gridheight)
self.setupBtn.setGeometry(self.spacing, self.boardHeight, (self.scale * 80), (self.scale * 30))
self.solveBtn.setGeometry((self.spacing * 2) + (self.scale * 80), self.boardHeight, (self.scale * 80), (self.scale * 30))
self.clearBtn.setGeometry((self.spacing * 3) + (self.scale * 160), self.boardHeight, (self.scale * 80), (self.scale * 30))
self.setFixedSize(self.boardWidth, self.boardHeight + (self.scale * 30) + self.spacing)
def activateUI(self):
for i in range(9):
for j in range(9):
grid = self.grids[i][j]
grid.clicked.connect(self.selectGrid)
grid.setCheckable(True)
self.setupBtn.clicked.connect(self.setup)
def setup(self):
self.b1.setup()
for i in range(9):
for j in range(9):
val = self.b1.rawread(i, j)
if val != 0:
self.grids[i][j].setText(str(val))
self.grids.setEnabled(False)
elif val == 0:
self.grids[i][j].setText('')
def selectGrid(self):
for i in range(9):
for j in range(9):
grid = self.grids[i][j]
if grid.isChecked():
x = i
y = j
grid.setCheckable(False) #reset the grid's checkable state, thereby unchecking it.
grid.setCheckable(True)
self.activeGrid = (x, y)
def editGrid(self, key):
x, y = self.activeGrid
#for i in self.possibleInputs:
print(key)
def keyPressEvent(self, event): #This is the keypress detector. I use this to determine input to edit grids.
try:
print(event.key())
key = event.key() - 48
print(key)
x, y = self.activeGrid
if len(sudoku.findall(self.possibleInputs, key)) == 1: #if the input is within the legal range
self.grids[x][y].setText(str(key))
sudoku.rawplace(x, y, key)
except:
pass
def Game():
app = QApplication([])
gameInstance = sudokuApp()
gameInstance.show()
app.exec_()
这里是sudoku.py。这是全部功能。
import random as rnd
class row():
def __init__(self):
self.grid = [0, 0, 0, 0, 0, 0, 0, 0, 0]
print('created row')
class col():
def __init__(self):
self.grid = [0, 0, 0, 0, 0, 0, 0, 0, 0]
class sub():
def __init__(self):
self.grid = [0, 0, 0, 0, 0, 0, 0, 0, 0]
class board():
mode = 'easy'
won = False
def __init__(self):
self.rows = [row(), row(), row(), row(), row(), row() ,row(), row(), row()]
self.cols = [col(), col(), col(), col(), col(), col(), col(), col(), col()]
self.subs = [sub(), sub(), sub(), sub(), sub(), sub(), sub(), sub(), sub()]
print('Board created.')
def setup(self):
if self.mode == 'easy':
numtoremove = 40
if self.mode == 'medium':
numtoremove = 50
if self.mode == 'hard':
numtoremove = 60
for i in self.rows:
for j in i.grid:
j = 0
for i in range(9):
for j in range(9):
self.rawplace(i, j, rnd.randint(1, 9))
self.check()
for i in range(rnd.randint(numtoremove, numtoremove + 10)):
self.rawplace(rnd.randint(0, 8), rnd.randint(0, 8), 0)
def clear(self):
for i in self.rows:
for j in i.grid:
j = 0
for i in self.cols:
for j in i.grid:
j = 0
for i in self.subs:
for j in i.grid:
j = 0
def check(self):
self.error = False
for i in self.rows:
#print('checking {}'.format(str(i)))
for j in range(1, 10):
instances = findall(i.grid, j)
#print(instances, end = ' ')
#print(len(instances))
if len(instances) > 1: #check for multiple instances and throw an error
error = True
i.grid[instances[len(instances) - 1]] = 0
if len(instances) == 0: #check to see if all grids are filled and set the won variable accordingly
self.won = True
else:
self.won = False
self.carry('rows', 'cols')
self.carry('rows', 'subs')
for i in self.cols:
#print('checking {}'.format(str(i)))
for j in range(1, 10):
instances = findall(i.grid, j)
#print(instances, end = ' ')
#print(len(instances))
if len(instances) > 1: #check for multiple instances and throw an error
error = True
i.grid[instances[len(instances) - 1]] = 0
if len(instances) == 0: #check to see if all grids are filled and set the won variable accordingly
self.won = True
else:
self.won = False
self.carry('cols', 'rows')
self.carry('rows', 'subs')
for i in self.subs:
#print('checking {}'.format(str(i)))
for j in range(1, 10):
instances = findall(i.grid, j)
#print(instances, end = ' ')
#print(len(instances))
if len(instances) > 1: #check for multiple instances and throw an error
error = True
i.grid[instances[len(instances) - 1]] = 0
if len(instances) == 0: #check to see if all grids are filled and set the won variable accordingly
self.won = True
else:
self.won = False
self.carry('subs', 'rows')
self.carry('rows', 'cols')
if self.error:
self.won = False
self.check()
def printboard(self, mode = 'rows'):
if mode == 'rows':
for i in self.rows:
for j in range(len(i.grid)):
print(i.grid[j], end = ' ')
print()
if mode == 'cols':
for i in range(9):
for j in self.cols:
print(j.grid[i], end = ' ')
print()
if mode == 'pretty':
lnctr = 0
print('-------------------------')
for i in self.rows:
print('| ' + str(i.grid[0]) + ' ' + str(i.grid[1]) + ' ' + str(i.grid[2]) + ' | ' +
str(i.grid[3]) + ' ' + str(i.grid[4]) + ' ' + str(i.grid[5]) + ' | ' +
str(i.grid[6]) + ' ' + str(i.grid[7]) + ' ' + str(i.grid[8]) + ' |')
lnctr += 1
if lnctr in [3, 6]:
print('|-------+-------+-------|')
print('-------------------------')
def place(self, xloc, yloc, val):
try:
#print(str(xloc) + ', ' + str(yloc) + ', ' + str(val))
return self.rawplace(int(xloc) - 1, int(yloc) - 1, int(val))
except:
return False
def rawplace(self, xloc, yloc, val):
#print("function: 'rawplace'")
try:
if xloc > 8 or xloc < 0 or yloc > 8 or yloc < 0:
#print('Out of range')
return False
else:
self.rows[yloc].grid[xloc] = val
self.carry('rows', 'cols')
self.carry('rows', 'subs')
return True
except:
return False
def read(self, xloc, yloc):
try:
return self.rawread(int(xloc - 1), int(yloc - 1))
except:
return False
def rawread(self, xloc, yloc):
try:
if xloc > 8 or xloc < 0 or yloc > 8 or yloc < 0:
#print('Out of range')
return False
else:
return self.rows[yloc].grid[xloc]
except:
return False
def carry(self, set1, set2):
if set1 == 'rows' and set2 == 'cols':
for x in range(9): #for each grid in the board
for y in range(9):
self.cols[x].grid[y] = self.rows[y].grid[x] #set that col.grid equal to that row.grid
if set1 == 'cols' and set2 == 'rows':
for x in range(9): #for each grid in the board
for y in range(9):
self.rows[y].grid[x] = self.cols[x].grid[y] #set that row.grid equal to that col.grid
if set1 == 'rows' and set2 == 'subs': #I couldn't come up with an algorithm here, so I listed the lines and made a script to mirror them for the subs - rows function.
self.subs[0].grid[0] = self.rows[0].grid[0] #first row
self.subs[0].grid[1] = self.rows[0].grid[1]
self.subs[0].grid[2] = self.rows[0].grid[2]
self.subs[0].grid[3] = self.rows[1].grid[0]
self.subs[0].grid[4] = self.rows[1].grid[1]
self.subs[0].grid[5] = self.rows[1].grid[2]
self.subs[0].grid[6] = self.rows[2].grid[0]
self.subs[0].grid[7] = self.rows[2].grid[1]
self.subs[0].grid[8] = self.rows[2].grid[2]
self.subs[1].grid[0] = self.rows[0].grid[3]
self.subs[1].grid[1] = self.rows[0].grid[4]
self.subs[1].grid[2] = self.rows[0].grid[5]
self.subs[1].grid[3] = self.rows[1].grid[3]
self.subs[1].grid[4] = self.rows[1].grid[4]
self.subs[1].grid[5] = self.rows[1].grid[5]
self.subs[1].grid[6] = self.rows[2].grid[3]
self.subs[1].grid[7] = self.rows[2].grid[4]
self.subs[1].grid[8] = self.rows[2].grid[5]
self.subs[2].grid[0] = self.rows[0].grid[6]
self.subs[2].grid[1] = self.rows[0].grid[7]
self.subs[2].grid[2] = self.rows[0].grid[8]
self.subs[2].grid[3] = self.rows[1].grid[6]
self.subs[2].grid[4] = self.rows[1].grid[7]
self.subs[2].grid[5] = self.rows[1].grid[8]
self.subs[2].grid[6] = self.rows[2].grid[6]
self.subs[2].grid[7] = self.rows[2].grid[7]
self.subs[2].grid[8] = self.rows[2].grid[8]
self.subs[3].grid[0] = self.rows[3].grid[0] #second row
self.subs[3].grid[1] = self.rows[3].grid[1]
self.subs[3].grid[2] = self.rows[3].grid[2]
self.subs[3].grid[3] = self.rows[4].grid[0]
self.subs[3].grid[4] = self.rows[4].grid[1]
self.subs[3].grid[5] = self.rows[4].grid[2]
self.subs[3].grid[6] = self.rows[5].grid[0]
self.subs[3].grid[7] = self.rows[5].grid[1]
self.subs[3].grid[8] = self.rows[5].grid[2]
self.subs[4].grid[0] = self.rows[3].grid[3]
self.subs[4].grid[1] = self.rows[3].grid[4]
self.subs[4].grid[2] = self.rows[3].grid[5]
self.subs[4].grid[3] = self.rows[4].grid[3]
self.subs[4].grid[4] = self.rows[4].grid[4]
self.subs[4].grid[5] = self.rows[4].grid[5]
self.subs[4].grid[6] = self.rows[5].grid[3]
self.subs[4].grid[7] = self.rows[5].grid[4]
self.subs[4].grid[8] = self.rows[5].grid[5]
self.subs[5].grid[0] = self.rows[3].grid[6]
self.subs[5].grid[1] = self.rows[3].grid[7]
self.subs[5].grid[2] = self.rows[3].grid[8]
self.subs[5].grid[3] = self.rows[4].grid[6]
self.subs[5].grid[4] = self.rows[4].grid[7]
self.subs[5].grid[5] = self.rows[4].grid[8]
self.subs[5].grid[6] = self.rows[5].grid[6]
self.subs[5].grid[7] = self.rows[5].grid[7]
self.subs[5].grid[8] = self.rows[5].grid[8]
self.subs[6].grid[0] = self.rows[6].grid[0] #third row
self.subs[6].grid[1] = self.rows[6].grid[1]
self.subs[6].grid[2] = self.rows[6].grid[2]
self.subs[6].grid[3] = self.rows[7].grid[0]
self.subs[6].grid[4] = self.rows[7].grid[1]
self.subs[6].grid[5] = self.rows[7].grid[2]
self.subs[6].grid[6] = self.rows[8].grid[0]
self.subs[6].grid[7] = self.rows[8].grid[1]
self.subs[6].grid[8] = self.rows[8].grid[2]
self.subs[7].grid[0] = self.rows[6].grid[3]
self.subs[7].grid[1] = self.rows[6].grid[4]
self.subs[7].grid[2] = self.rows[6].grid[5]
self.subs[7].grid[3] = self.rows[7].grid[3]
self.subs[7].grid[4] = self.rows[7].grid[4]
self.subs[7].grid[5] = self.rows[7].grid[5]
self.subs[7].grid[6] = self.rows[8].grid[3]
self.subs[7].grid[7] = self.rows[8].grid[4]
self.subs[7].grid[8] = self.rows[8].grid[5]
self.subs[8].grid[0] = self.rows[6].grid[6]
self.subs[8].grid[1] = self.rows[6].grid[7]
self.subs[8].grid[2] = self.rows[6].grid[8]
self.subs[8].grid[3] = self.rows[7].grid[6]
self.subs[8].grid[4] = self.rows[7].grid[7]
self.subs[8].grid[5] = self.rows[7].grid[8]
self.subs[8].grid[6] = self.rows[8].grid[6]
self.subs[8].grid[7] = self.rows[8].grid[7]
self.subs[8].grid[8] = self.rows[8].grid[8]
if set1 == 'subs' and set2 == 'rows':
self.rows[0].grid[0] = self.subs[0].grid[0] #first row
self.rows[0].grid[1] = self.subs[0].grid[1]
self.rows[0].grid[2] = self.subs[0].grid[2]
self.rows[1].grid[0] = self.subs[0].grid[3]
self.rows[1].grid[1] = self.subs[0].grid[4]
self.rows[1].grid[2] = self.subs[0].grid[5]
self.rows[2].grid[0] = self.subs[0].grid[6]
self.rows[2].grid[1] = self.subs[0].grid[7]
self.rows[2].grid[2] = self.subs[0].grid[8]
self.rows[0].grid[3] = self.subs[1].grid[0]
self.rows[0].grid[4] = self.subs[1].grid[1]
self.rows[0].grid[5] = self.subs[1].grid[2]
self.rows[1].grid[3] = self.subs[1].grid[3]
self.rows[1].grid[4] = self.subs[1].grid[4]
self.rows[1].grid[5] = self.subs[1].grid[5]
self.rows[2].grid[3] = self.subs[1].grid[6]
self.rows[2].grid[4] = self.subs[1].grid[7]
self.rows[2].grid[5] = self.subs[1].grid[8]
self.rows[0].grid[6] = self.subs[2].grid[0]
self.rows[0].grid[7] = self.subs[2].grid[1]
self.rows[0].grid[8] = self.subs[2].grid[2]
self.rows[1].grid[6] = self.subs[2].grid[3]
self.rows[1].grid[7] = self.subs[2].grid[4]
self.rows[1].grid[8] = self.subs[2].grid[5]
self.rows[2].grid[6] = self.subs[2].grid[6]
self.rows[2].grid[7] = self.subs[2].grid[7]
self.rows[2].grid[8] = self.subs[2].grid[8]
self.rows[3].grid[0] = self.subs[3].grid[0] #second row
self.rows[3].grid[1] = self.subs[3].grid[1]
self.rows[3].grid[2] = self.subs[3].grid[2]
self.rows[4].grid[0] = self.subs[3].grid[3]
self.rows[4].grid[1] = self.subs[3].grid[4]
self.rows[4].grid[2] = self.subs[3].grid[5]
self.rows[5].grid[0] = self.subs[3].grid[6]
self.rows[5].grid[1] = self.subs[3].grid[7]
self.rows[5].grid[2] = self.subs[3].grid[8]
self.rows[3].grid[3] = self.subs[4].grid[0]
self.rows[3].grid[4] = self.subs[4].grid[1]
self.rows[3].grid[5] = self.subs[4].grid[2]
self.rows[4].grid[3] = self.subs[4].grid[3]
self.rows[4].grid[4] = self.subs[4].grid[4]
self.rows[4].grid[5] = self.subs[4].grid[5]
self.rows[5].grid[3] = self.subs[4].grid[6]
self.rows[5].grid[4] = self.subs[4].grid[7]
self.rows[5].grid[5] = self.subs[4].grid[8]
self.rows[3].grid[6] = self.subs[5].grid[0]
self.rows[3].grid[7] = self.subs[5].grid[1]
self.rows[3].grid[8] = self.subs[5].grid[2]
self.rows[4].grid[6] = self.subs[5].grid[3]
self.rows[4].grid[7] = self.subs[5].grid[4]
self.rows[4].grid[8] = self.subs[5].grid[5]
self.rows[5].grid[6] = self.subs[5].grid[6]
self.rows[5].grid[7] = self.subs[5].grid[7]
self.rows[5].grid[8] = self.subs[5].grid[8]
self.rows[6].grid[0] = self.subs[6].grid[0] #third row
self.rows[6].grid[1] = self.subs[6].grid[1]
self.rows[6].grid[2] = self.subs[6].grid[2]
self.rows[7].grid[0] = self.subs[6].grid[3]
self.rows[7].grid[1] = self.subs[6].grid[4]
self.rows[7].grid[2] = self.subs[6].grid[5]
self.rows[8].grid[0] = self.subs[6].grid[6]
self.rows[8].grid[1] = self.subs[6].grid[7]
self.rows[8].grid[2] = self.subs[6].grid[8]
self.rows[6].grid[3] = self.subs[7].grid[0]
self.rows[6].grid[4] = self.subs[7].grid[1]
self.rows[6].grid[5] = self.subs[7].grid[2]
self.rows[7].grid[3] = self.subs[7].grid[3]
self.rows[7].grid[4] = self.subs[7].grid[4]
self.rows[7].grid[5] = self.subs[7].grid[5]
self.rows[8].grid[3] = self.subs[7].grid[6]
self.rows[8].grid[4] = self.subs[7].grid[7]
self.rows[8].grid[5] = self.subs[7].grid[8]
self.rows[6].grid[6] = self.subs[8].grid[0]
self.rows[6].grid[7] = self.subs[8].grid[1]
self.rows[6].grid[8] = self.subs[8].grid[2]
self.rows[7].grid[6] = self.subs[8].grid[3]
self.rows[7].grid[7] = self.subs[8].grid[4]
self.rows[7].grid[8] = self.subs[8].grid[5]
self.rows[8].grid[6] = self.subs[8].grid[6]
self.rows[8].grid[7] = self.subs[8].grid[7]
self.rows[8].grid[8] = self.subs[8].grid[8]
def findall(listin, x):
occurences = []
for i in range(len(listin)):
if listin[i] == x:
occurences.append(i)
return occurences
在Visual Studio 2019下安装的Python 3.7.4 Windows 10家庭版