import sys from PyQt5 import QtWidgets, QtGui from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import * from tkinter.filedialog import askopenfilename from tkinter import * class App(QDialog): def __init__(self): super().__init__() self.file = "" # default Matrixsize N x N self.matrixSize = (8) self.matrixSizeDefault = (8) # Button Settings self.initialized = False self.title = 'Hidato Puzzle' self.setWindowIcon(QtGui.QIcon('icon.png')) self.width = 600 self.height = 700 self.initUI() def initUI(self): self.setWindowTitle(self.title) self.setMinimumSize(self.width, self.height) self.textbox = QLineEdit(self) self.textbox.setText(str(self.matrixSizeDefault)) self.flo = QFormLayout() self.buttonchange = QPushButton("Change Matrixsize", self) self.buttonchange.clicked.connect(self.changeSize) self.flo.addRow(QLabel("Matrix Size: NxN"), self.textbox) self.button1 = QPushButton("Enter Input", self) self.button1.clicked.connect(self.Dateiwahl) self.layout = QVBoxLayout() self.tableWidget = QTableWidget() self.layout.addLayout(self.flo) self.layout.addWidget(self.buttonchange) self.layout.addWidget(self.button1) self.layout.setAlignment(Qt.AlignTop) self.setLayout(self.layout) # Central Window qtRectangle = self.frameGeometry() centerPoint = QDesktopWidget().availableGeometry().center() qtRectangle.moveCenter(centerPoint) self.move(qtRectangle.topLeft()) self.show() # Open file (Button) def Dateiwahl(self): try: root = Tk() root.withdraw() self.file = askopenfilename() self.init_buttons() self.matrix_laden(self.file) except: QMessageBox.about(self, "Error", "File selection failed!") #Matrix reset (Button) def matrix_zuruecksetzen(self): self.matrix_laden(self.file) def changeSize(self): if self.textbox.text().isdigit(): self.matrixSize = int(self.textbox.text()) QMessageBox.about(self, "Success", "Changed Matrixsize to: {}".format(self.textbox.text())) else: QMessageBox.about(self, "Error", "Matrixsize has to be an integer!") self.textbox.setText(str(self.matrixSizeDefault)) #Button Drawing Instance (Only draw once after a Matrix is loaded) def init_buttons(self): if not self.initialized: self.button2 = QPushButton("Reset input", self) self.button2.clicked.connect(self.matrix_zuruecksetzen) self.button3 = QPushButton("Solve Matrix", self) self.button3.clicked.connect(self.matrix_loesen) self.button4 = QPushButton("compare Matrix", self) self.button4.clicked.connect(self.Matrix_vergleichen) self.layout.addWidget(self.button2) self.layout.addWidget(self.button3) self.layout.addWidget(self.button4) self.initialized = True #Create and Fill the Table with loaded Matrix def createTable(self, inmatrix): try: self.tableWidget.setRowCount(self.matrixSize) self.tableWidget.setColumnCount(self.matrixSize) self.tableWidget.setColumnWidth(0, 15) self.tableWidget.setColumnWidth(1, 15) self.tableWidget.setColumnWidth(2, 15) self.tableWidget.setColumnWidth(3, 15) self.tableWidget.setColumnWidth(4, 15) self.tableWidget.setColumnWidth(5, 15) self.tableWidget.setColumnWidth(6, 15) self.tableWidget.setColumnWidth(7, 15) self.tableWidget.setColumnWidth(8, 15) self.tableWidget.setColumnWidth(9, 15) # Make "." fields not editable self.map = {(x, y): e for y, row in enumerate(inmatrix) for x, e in enumerate(row)} for a, b in self.map.items(): self.tableWidget.setItem(a[1], a[0], QTableWidgetItem(b)) if (str(self.tableWidget.item(a[1], a[0]).text()) == '.'): self.tableWidget.item(a[1], a[0]).setFlags(Qt.ItemIsEnabled) if (str(self.tableWidget.item(a[1], a[0]).text()).isdigit()): self.tableWidget.item(a[1], a[0]).setFlags(Qt.ItemIsEnabled) self.layout.addWidget(self.tableWidget) except: QMessageBox.about(self, "Error", "Loading failed!") #Matrix load file def matrix_laden(self, file): try: self.inmatrix = [line.split() for line in open(str(file))] self.createTable(self.inmatrix) except: QMessageBox.about(self, "Error", "Loading failed!") # def matrix_loesen(self): buttonReply = QMessageBox.question(self, 'Hidato Solver', "Would you like to solve the Matrix?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if buttonReply == QMessageBox.Yes: try: inmatrix = self.inmatrix map = {(x, y): e for y, row in enumerate(inmatrix) for x, e in enumerate(row)} check_koords = {coord: int(e) for coord, e in map.items() if e.isdigit()} check = {n: coord for coord, n in check_koords.items()} legal = {coord for coord, e in map.items() if e != '.'} curr = 1 if curr in check: Wege = {(check[curr],)} else: Wege = {(coord,) for coord in legal} while Wege: if curr == len(legal): break curr += 1 NeuWege = set() for WegN in Wege: x, y = WegN[-1] for dy, dx in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]: newpos = (x + dx, y + dy) if newpos not in legal: continue if newpos in check_koords and check_koords[newpos] != curr: continue if curr in check and check[curr] != newpos: continue if newpos in WegN: continue NeuWege.add(WegN + (newpos,)) Wege = NeuWege if Wege: WegN = list(Wege)[0] for i, (x, y) in enumerate(WegN): inmatrix[y][x] = str(i + 1) self.createTable(inmatrix) else: QMessageBox.about(self, "Error", "Matrix not solveable!") except: QMessageBox.about(self, "Error", "Matrix solving failed!") #Compare User Input with the solved Matrix def Matrix_vergleichen(self): try: inmatrix = self.inmatrix map = {(x, y): e for y, row in enumerate(inmatrix) for x, e in enumerate(row)} check_koords = {coord: int(e) for coord, e in map.items() if e.isdigit()} check = {n: coord for coord, n in check_koords.items()} legal = {coord for coord, e in map.items() if e != '.'} curr = 1 if curr in check: Wege = {(check[curr],)} else: Wege = {(coord,) for coord in legal} while Wege: if curr == len(legal): break curr += 1 NeuWege = set() for WegN in Wege: x, y = WegN[-1] for dy, dx in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]: newpos = (x + dx, y + dy) if newpos not in legal: continue if newpos in check_koords and check_koords[newpos] != curr: continue if curr in check and check[curr] != newpos: continue if newpos in WegN: continue NeuWege.add(WegN + (newpos,)) Wege = NeuWege if Wege: WegN = list(Wege)[0] for i, (x, y) in enumerate(WegN): inmatrix[y][x] = str(i + 1) self.matrixTmp = inmatrix userstring = "" for row in range(self.matrixSize): for col in range(self.matrixSize): item = str(self.tableWidget.item(row, col).text()) userstring = userstring + item solutionstring = "" mapTmp = {(x, y): e for y, row in enumerate(self.matrixTmp) for x, e in enumerate(row)} for e in mapTmp.items(): solutionstring = solutionstring + e[1] if userstring == solutionstring: QMessageBox.about(self, "Success", "You solved the Puzzle!") else: QMessageBox.about(self, "Error", "Wrong Matrix, try again!") else: QMessageBox.about(self, "Error", "Matrix not solveable!") except: QMessageBox.about(self, "Error", "Matrix comparison not possible!") if __name__ == '__main__': print("Start") app = QApplication(sys.argv) ex = App() sys.exit(app.exec_()) ---- END OF PYTHON CODE Input as .txt files: 8x8: __ 33 35 __ __ . . . __ __ 24 22 __ . . . __ __ __ 21 __ __ . . __ 26 __ 13 40 11 . . 27 __ __ __ 9 __ 1 . . . __ __ 18 __ __ . . . . . __ 7 __ __ . . . . . . 5 __ 10x10: 88 __ _ 81 _ 100 1 3 4 _ 86 89 82 91 99 _ _ 8 _ 6 _ 83 92 98 56 78 _ 10 _ 14 _ 93 97 _ 77 _ 11 _ 13 _ _ 96 60 _ _ 54 31 12 29 _ 95 _ 75 _ 53 52 33 _ 28 18 72 _ 62 _ _ 37 _ 34 19 27 73 _ 64 50 45 _ 38 35 _ 20 70 67 65 _ 46 44 40 25 22 21 68 69 66 48 _ 43 _ 41 24 _ 8x8 (Not Solveable): __ 33 35 __ __ . . . __ __ 24 22 __ . . . __ __ __ 21 __ __ . . __ 26 __ 13 40 11 . . 27 __ __ __ 9 __ 1 . . . __ __ 19 __ __ . . . . . __ 7 __ __ . . . . . . 5 __ What is Hidato? https://en.wikipedia.org/wiki/Hidato