Beispiel #1
0
class GameScreen(QWidget):
    def __init__(self):
        # Call parent class's __init__()
        super().__init__()

        self.board = GameBoard()
        self.board.setFixedSize(600, 600)

        self.game_status = QLabel()
        self.game_status.setObjectName("gameStatus")
        self.game_status.setMaximumHeight(30)
        self.game_status.setAlignment(QtCore.Qt.AlignCenter)
        self.reset_button = QPushButton("Reset")
        self.reset_button.clicked.connect(self.reset_game)
        self.reset_button.setCursor(QtCore.Qt.CursorShape.PointingHandCursor)
        self.reset_button.setMinimumWidth(120)
        self.exit_button = QPushButton("Exit Game")
        self.exit_button.clicked.connect(sys.exit)
        self.exit_button.setCursor(QtCore.Qt.CursorShape.PointingHandCursor)
        self.exit_button.setMinimumWidth(120)

        self.control_panel = QVBoxLayout()
        self.control_panel.addWidget(self.game_status)
        self.control_panel.addWidget(self.reset_button)
        self.control_panel.addWidget(self.exit_button)

        self.main_layout = QBoxLayout(QBoxLayout.Direction.LeftToRight)
        self.main_layout.addWidget(self.board)
        self.main_layout.addLayout(self.control_panel)

        # Set layout
        self.setLayout(self.main_layout)

    def resizeEvent(self, event):
        offset = -self.board.main_layout.spacing() * self.board.main_layout.rowCount()
        width = self.size().width() + offset
        height = self.size().height() + offset
        excess = width - height
        if excess >= 0:
            min_cp_width = self.control_panel.minimumSize().width()
            margin = max([0, min_cp_width - excess + self.main_layout.spacing()])
            height -= margin
            self.main_layout.setDirection(QBoxLayout.Direction.LeftToRight)
            self.board.setFixedSize(height, height)
            self.board.setContentsMargins(0, 0, 0, 0)
        else:
            min_cp_height = self.control_panel.minimumSize().height()
            margin = max([0, min_cp_height + excess + self.main_layout.spacing()])
            width -= margin
            self.main_layout.setDirection(QBoxLayout.Direction.TopToBottom)
            self.board.setFixedSize(width + margin - self.main_layout.spacing(), width)
            self.board.setContentsMargins(
                (margin - self.main_layout.spacing()) / 2,
                0,
                (margin - self.main_layout.spacing()) / 2,
                0,
            )
        super().resizeEvent(event)

    def reset_game(self):
        for cell in self.board.findChildren(QPushButton):
            cell.setText(" ")
            cell.setStyleSheet("")
        self.game_status.setText("")

    def get_state(self):
        state = []
        cell_type = {"X": 1.0, "O": -1.0, " ": 0.0}
        for cell in self.board.findChildren(QPushButton):
            state.append(cell_type[cell.text()])
        # Add a batch dimension
        return torch.tensor(state).unsqueeze(0).to(self.device)

    def num_actions_available(self):
        num_actions_available = 0
        for cell in self.board.findChildren(QPushButton):
            if cell.text() == " ":
                num_actions_available += 1
        return num_actions_available

    def take_action(self, action):
        player = "X" if self.board.x_turn else "O"
        print(self.board.findChildren(QPushButton)[action.item()])
        self.board.findChildren(QPushButton)[action.item()].setText(player)
        self.board.x_turn = not self.board.x_turn
        if (game_status := self.board.check_game_status()) == 0:
            self.game_status.setText("It's a tie!")
            self.done = True
            return torch.tensor([1], device=self.device)
        elif game_status == 1:
            self.game_status.setText("X has won!")
            self.done = True
            return torch.tensor([-1 + (self.board.x_turn) * 3], device=self.device)