from random import randint
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QVBoxLayout, QLineEdit, QFrame
from PyQt5.QtGui import QPainter, QPen
from PyQt5.QtCore import Qt

class Labyrinthe(QWidget):
    def __init__(self, mursH, mursV, globNbrColonnes, globNbrLignes):
        super().__init__()
        self.mursH = mursH
        self.mursV = mursV
        self.globNbrColonnes = globNbrColonnes
        self.globNbrLignes = globNbrLignes
        self.initUI()

    def initUI(self):
        self.setWindowTitle('Labyrinthe')
        self.setGeometry(100, 100, (self.globNbrColonnes + 2) * 20, (self.globNbrLignes + 2) * 20)
        self.show()

    def paintEvent(self, event):
        qp = QPainter(self)
        delta = 20
        dim = 20
        qp.setPen(QPen(Qt.black, 2, Qt.SolidLine))

        for ligne in range(self.globNbrLignes * 2 + 1):
            if ligne % 2 == 0:
                for colonne in range(self.globNbrColonnes * 2 + 1):
                    if colonne % 2 != 0:
                        if self.mursH[ligne // 2][(colonne - 1) // 2]:
                            qp.drawLine(int(delta + (colonne - 1) * dim / 2), int(delta + ligne * dim / 2),
                                        int(delta + (colonne + 1) * dim / 2), int(delta + ligne * dim / 2))
            else:
                for colonne in range(self.globNbrColonnes * 2 + 1):
                    if colonne % 2 == 0:
                        if self.mursV[(ligne - 1) // 2][colonne // 2]:
                            qp.drawLine(int(delta + colonne * dim / 2), int(delta + (ligne - 1) * dim / 2),
                                        int(delta + colonne * dim / 2), int(delta + (ligne + 1) * dim / 2))

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('Labyrinthe')
        self.setGeometry(100, 100, 300, 400)

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        label1 = QLabel("Génération du labyrinthe", self)
        label1.setStyleSheet("font: 20pt Arial")
        label1.setAlignment(Qt.AlignCenter)
        vbox.addWidget(label1)

        line1 = QFrame(self)
        line1.setFrameShape(QFrame.HLine)
        line1.setFrameShadow(QFrame.Sunken)
        vbox.addWidget(line1)

        label2 = QLabel("Nombre de colonnes (10 minimum, 99 maximum)", self)
        vbox.addWidget(label2)

        self.nbrCols = QLineEdit(self)
        vbox.addWidget(self.nbrCols)

        label3 = QLabel("Nombre de lignes (10 minimum, 99 maximum)", self)
        vbox.addWidget(label3)

        self.nbrLignes = QLineEdit(self)
        vbox.addWidget(self.nbrLignes)

        line2 = QFrame(self)
        line2.setFrameShape(QFrame.HLine)
        line2.setFrameShadow(QFrame.Sunken)
        vbox.addWidget(line2)

        btnGenerer = QPushButton("Générer le labyrinthe", self)
        btnGenerer.clicked.connect(self.generer_labyrinthe)
        vbox.addWidget(btnGenerer)

    def generer_labyrinthe(self):
        try:
            globNbrColonnes = int(self.nbrCols.text())
            globNbrLignes = int(self.nbrLignes.text())
        except ValueError:
            return

        if globNbrColonnes < 10:
            globNbrColonnes = 10
        if globNbrColonnes > 99:
            globNbrColonnes = 99
        if globNbrLignes < 10:
            globNbrLignes = 10
        if globNbrLignes > 99:
            globNbrLignes = 99

        MursH = [[True for _ in range(globNbrColonnes)] for _ in range(globNbrLignes + 1)]
        MursV = [[True for _ in range(globNbrColonnes + 1)] for _ in range(globNbrLignes)]

        self.explore(globNbrColonnes, globNbrLignes, MursH, MursV)

        self.labyrinthe = Labyrinthe(MursH, MursV, globNbrColonnes, globNbrLignes)
        self.labyrinthe.show()

    def explore(self, globNbrColonnes, globNbrLignes, MursH, MursV):
        def Mur_aleatoire():
            return randint(0, globNbrLignes - 1), randint(0, globNbrColonnes - 1)

        def Carve_passage(aleatoire_x, aleatoire_y):
            pile = [(aleatoire_x, aleatoire_y)]
            while pile:
                x, y = pile[-1]
                directions = ['N', 'S', 'E', 'O']
                while directions:
                    direction = directions.pop(randint(0, len(directions) - 1))
                    if direction == 'N' and x > 0 and MursH[x][y]:
                        MursH[x][y] = False
                        x -= 1
                        pile.append((x, y))
                        break
                    elif direction == 'S' and x < globNbrLignes - 1 and MursH[x + 1][y]:
                        MursH[x + 1][y] = False
                        x += 1
                        pile.append((x, y))
                        break
                    elif direction == 'E' and y < globNbrColonnes - 1 and MursV[x][y + 1]:
                        MursV[x][y + 1] = False
                        y += 1
                        pile.append((x, y))
                        break
                    elif direction == 'O' and y > 0 and MursV[x][y]:
                        MursV[x][y] = False
                        y -= 1
                        pile.append((x, y))
                        break
                else:
                    pile.pop()

        x, y = Mur_aleatoire()
        Carve_passage(x, y)

if __name__ == '__main__':
    app = QApplication([])
    window = Window()
    window.show()
    app.exec_()
