Не правильно работает определение корабля в морском бое

Пишу "Морской бой" и нашел неприятный момент, когда стреляешь в 3 палубный корабль с середины и любую клетку с краю, он уничтожается и 3 клетка где должен быть еще корабль закрывается, с 4 палубным такая же история.

Если вот так расставить корабли введите сюда описание изображения

При самой игре, происходит вот так

я пометил, где еще должен стоять корабль

введите сюда описание изображения

https://github.com/rangihrad/sw.git

извиняюсь, за большой код, но как мог его сократил.


Ответы (1 шт):

Автор решения: GrAnd

Ваша проблема заключалась в том, что вы нигде не храните знания о кораблях. Занятые ячейки поля, что вы храните в players[].board - этой информации не достаточно. Потому что, допустим, вы попадаете трехпалубнику в середину, и в результате в players[].boardон, по сути, "разваливается" на два однопалубника. Отсюда и получается полное потопление при попадании в любую из этих частей-однопалубников.

Итак, во-первых я замучился задавать корабли через ввод координат (честно говоря на третьем корабле). Поэтому я переделал так, что надо выделить нужное количество ячеек таблицы и нажать на кнопку "Поставить корабль". Заодно совместил задание однопалубника и остальных (не понял зачем его отдельно обрабатывали). Кнопки теперь эквивалентные, но мне было лень переделывать. Так что сами, к примеру, на их место поставьте счётчики оставшихся кораблей (что сейчас во всплывающих подсказках) и сделаете одну общую кнопку.

Я добавил в ваш класс Player() ещё и данные о кораблях `ships'. Этот массив содержит все корабли с координатами всех их частей и длиной. При попадании, у соответствующего корабля уменьшается длина, и корабль считается убитым при достижении нулевой длины.

Ну и схлопнул в циклы кучу однотипных строчек. Хотя в этом направлении ещё работать и работать. Подсказка: чтобы не плодить кучу однотипных простых переменных и писать кучи похожих строк кода - чаще используйте списки и словари, по которым потом можно итерироваться в циклах или адресоваться по индексу безо всяких if.

import sys
import re
from random import randrange
import sqlite3

from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtCore import QBasicTimer, QCoreApplication

from PyQt5.QtWidgets import QApplication, QMainWindow, \
    QStackedWidget, QMessageBox, QInputDialog, QTableWidgetItem, QAction
from PyQt5 import QtCore, QtGui
from PyQt5 import QtWidgets

def natural_key(string_):
    return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', string_)]


class Ui_MainWindow_ready(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(960, 540)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.playerLabel = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(16)
        self.playerLabel.setFont(font)
        self.playerLabel.setObjectName("playerLabel")
        self.horizontalLayout_2.addWidget(self.playerLabel)
        self.gridLayout.addLayout(self.horizontalLayout_2, 0, 0, 1, 1)
        self.readyButton = QtWidgets.QPushButton(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(24)
        self.readyButton.setFont(font)
        self.readyButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.readyButton.setObjectName("readyButton")
        self.gridLayout.addWidget(self.readyButton, 0, 2, 1, 2)
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.linkorButton = QtWidgets.QPushButton(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setItalic(False)
        font.setStrikeOut(False)
        self.linkorButton.setFont(font)
        self.linkorButton.setObjectName("linkorButton")
        self.verticalLayout_2.addWidget(self.linkorButton)
        self.kreyserButton = QtWidgets.QPushButton(self.centralwidget)
        self.kreyserButton.setFont(font)
        self.kreyserButton.setObjectName("kreyserButton")
        self.verticalLayout_2.addWidget(self.kreyserButton)
        self.esminecButton = QtWidgets.QPushButton(self.centralwidget)
        self.esminecButton.setFont(font)
        self.esminecButton.setObjectName("esminecButton")
        self.verticalLayout_2.addWidget(self.esminecButton)
        self.torpedButton = QtWidgets.QPushButton(self.centralwidget)
        self.torpedButton.setFont(font)
        self.torpedButton.setObjectName("torpedButton")
        self.verticalLayout_2.addWidget(self.torpedButton)
        self.gridLayout.addLayout(self.verticalLayout_2, 1, 3, 1, 1)
        self.boardMap = QtWidgets.QTableWidget(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.boardMap.setFont(font)
        self.boardMap.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.boardMap.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored)
        self.boardMap.setObjectName("boardMap")
        self.boardMap.setColumnCount(10)
        self.boardMap.setRowCount(10)
        for i in range(10):
            item = QtWidgets.QTableWidgetItem()
            self.boardMap.setVerticalHeaderItem(i, item)
            item = QtWidgets.QTableWidgetItem()
            self.boardMap.setHorizontalHeaderItem(i, item)
        self.gridLayout.addWidget(self.boardMap, 1, 0, 1, 1)
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.linkorImage = QtWidgets.QLabel(self.centralwidget)
        self.linkorImage.setText("")
        self.linkorImage.setObjectName("linkorImage")
        self.verticalLayout.addWidget(self.linkorImage)
        self.kreyserImage = QtWidgets.QLabel(self.centralwidget)
        self.kreyserImage.setText("")
        self.kreyserImage.setObjectName("kreyserImage")
        self.verticalLayout.addWidget(self.kreyserImage)
        self.esminecImage = QtWidgets.QLabel(self.centralwidget)
        self.esminecImage.setText("")
        self.esminecImage.setObjectName("esminecImage")
        self.verticalLayout.addWidget(self.esminecImage)
        self.torpedImage = QtWidgets.QLabel(self.centralwidget)
        self.torpedImage.setText("")
        self.torpedImage.setObjectName("torpedImage")
        self.verticalLayout.addWidget(self.torpedImage)
        self.gridLayout.addLayout(self.verticalLayout, 1, 2, 1, 1)
        self.verticalLayout_3 = QtWidgets.QVBoxLayout()
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.lcdNumber = []
        for i in range(4, 0, -1):
            self.lcdNumber.append(QtWidgets.QLCDNumber(self.centralwidget))
            self.lcdNumber[-1].setProperty("intValue", i)
            self.lcdNumber[-1].setObjectName(f"lcdNumber_{4-i}")
            self.verticalLayout_3.addWidget(self.lcdNumber[-1])
        self.gridLayout.addLayout(self.verticalLayout_3, 1, 1, 1, 1)
        self.label = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(8)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 0, 1, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 960, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.playerLabel.setText(_translate("MainWindow", "Игрок1"))
        self.readyButton.setText(_translate("MainWindow", "Я  готов"))
        for w in [self.linkorButton, self.kreyserButton, self.esminecButton, self.torpedButton]:
            w.setText(_translate("MainWindow", "Поставить корабль"))
        for i in range(10):
            item = self.boardMap.verticalHeaderItem(i)
            item.setText(_translate("MainWindow", str(i+1)))
        for i, c in enumerate("ABCDEFGHIJ"):
            item = self.boardMap.horizontalHeaderItem(i)
            item.setText(_translate("MainWindow", c))
        self.label.setText(_translate("MainWindow", "Количество ячеек."))


class Ui_MainWindow_pvp(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(960, 577)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.board1Label = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(16)
        self.board1Label.setFont(font)
        self.board1Label.setObjectName("board1Label")
        self.horizontalLayout.addWidget(self.board1Label)
        self.linkorP1 = QtWidgets.QLabel(self.centralwidget)
        self.linkorP1.setText("")
        self.linkorP1.setObjectName("linkorP1")
        self.horizontalLayout.addWidget(self.linkorP1)
        self.kreyserP1 = QtWidgets.QLabel(self.centralwidget)
        self.kreyserP1.setText("")
        self.kreyserP1.setObjectName("kreyserP1")
        self.horizontalLayout.addWidget(self.kreyserP1)
        self.esminecP1 = QtWidgets.QLabel(self.centralwidget)
        self.esminecP1.setText("")
        self.esminecP1.setObjectName("esminecP1")
        self.horizontalLayout.addWidget(self.esminecP1)
        self.torpedP1 = QtWidgets.QLabel(self.centralwidget)
        self.torpedP1.setText("")
        self.torpedP1.setObjectName("torpedP1")
        self.horizontalLayout.addWidget(self.torpedP1)
        self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.linkorP2 = QtWidgets.QLabel(self.centralwidget)
        self.linkorP2.setText("")
        self.linkorP2.setObjectName("linkorP2")
        self.horizontalLayout_2.addWidget(self.linkorP2)
        self.kreyserP2 = QtWidgets.QLabel(self.centralwidget)
        self.kreyserP2.setText("")
        self.kreyserP2.setObjectName("kreyserP2")
        self.horizontalLayout_2.addWidget(self.kreyserP2)
        self.esminecP2 = QtWidgets.QLabel(self.centralwidget)
        self.esminecP2.setText("")
        self.esminecP2.setObjectName("esminecP2")
        self.horizontalLayout_2.addWidget(self.esminecP2)
        self.torpedP2 = QtWidgets.QLabel(self.centralwidget)
        self.torpedP2.setText("")
        self.torpedP2.setObjectName("torpedP2")
        self.horizontalLayout_2.addWidget(self.torpedP2)
        self.board2Label = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(16)
        self.board2Label.setFont(font)
        self.board2Label.setObjectName("board2Label")
        self.horizontalLayout_2.addWidget(self.board2Label)
        self.gridLayout.addLayout(self.horizontalLayout_2, 0, 5, 1, 1)
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setMinimumSize(QtCore.QSize(441, 461))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(10)
        self.tableWidget.setRowCount(10)
        for i in range(10):
            item = QtWidgets.QTableWidgetItem()
            self.tableWidget.setVerticalHeaderItem(i, item)
            item = QtWidgets.QTableWidgetItem()
            self.tableWidget.setHorizontalHeaderItem(i, item)
        self.gridLayout.addWidget(self.tableWidget, 1, 0, 1, 3)
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(spacerItem, 0, 1, 1, 1)
        self.vsLable = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setFamily("Digital Counter 7")
        font.setPointSize(36)
        self.vsLable.setFont(font)
        self.vsLable.setText("")
        self.vsLable.setObjectName("vsLable")
        self.gridLayout.addWidget(self.vsLable, 0, 2, 1, 2)
        self.tableWidget_2 = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget_2.setMinimumSize(QtCore.QSize(441, 461))
        self.tableWidget_2.setObjectName("tableWidget_2")
        self.tableWidget_2.setColumnCount(10)
        self.tableWidget_2.setRowCount(10)
        for i in range(10):
            item = QtWidgets.QTableWidgetItem()
            self.tableWidget_2.setVerticalHeaderItem(i, item)
            item = QtWidgets.QTableWidgetItem()
            self.tableWidget_2.setHorizontalHeaderItem(i, item)
        self.gridLayout.addWidget(self.tableWidget_2, 1, 3, 1, 3)
        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(spacerItem1, 0, 4, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 960, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Game PVP"))
        for i in range(10):
            item = self.tableWidget.verticalHeaderItem(i)
            item.setText(_translate("MainWindow", str(i+1)))
            item = self.tableWidget_2.verticalHeaderItem(i)
            item.setText(_translate("MainWindow", str(i+1)))
        for i, c in enumerate("ABCDEFGHIJ"):
            item = self.tableWidget.horizontalHeaderItem(i)
            item.setText(_translate("MainWindow", c))
            item = self.tableWidget_2.horizontalHeaderItem(i)
            item.setText(_translate("MainWindow", c))


COORDS = dict(("ABCDEFGHIJ"[x]+str(y+1), (y, x)) for x in range(10) for y in range(10))
players = []



def new_cell_mul():  # Когда ставлю звёздочку в QTableWidget
    cell_mul = QTableWidgetItem("*")
    cell_mul.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
    return cell_mul


def new_cell_x():  # Когда ставлю крестик в QTableWidget
    cell_x = QTableWidgetItem("X")
    cell_x.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
    return cell_x


def new_cell_dot():  # Когда ставлю точку в QTableWidget
    cell_dot = QTableWidgetItem(".")
    cell_dot.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
    return cell_dot



class ReadyMain(QMainWindow, Ui_MainWindow_ready):
    """Меню подготовления к самой игре"""

    def __init__(self, parent=None):             
        super(ReadyMain, self).__init__(parent)
        self.setupUi(self)

        self.map = SeaMap(self.boardMap)
        self.new_count()  # Обновление переменных-счётчиков
        self.new_map()  # Обновление карты


        self.initUI()

    def initUI(self):
        # Задаю цвет и форму кнопкам
        for w in [self.linkorButton, self.kreyserButton, self.esminecButton, self.torpedButton]:
            w.setStyleSheet("color: white; background-color: #b6afa9;"
                            "border-radius: 10px;")
            w.clicked.connect(self.setShip)

        self.readyButton.setStyleSheet("color: white; background-color: #b6afa9;"
                                       "border-radius: 10px;")
        self.readyButton.clicked.connect(self.start)


    def new_map(self):  # Метод создаёт(обновляет) карту
        for i in range(self.boardMap.columnCount()):
            for j in range(self.boardMap.rowCount()):
                self.boardMap.setItem(i, j, new_cell_dot())
        self.boardMap.resizeColumnsToContents()
        self.boardMap.resizeRowsToContents()

        self.boardMap.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)

        self.boardMap.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)

    def new_db(self, who):  # Занесения данных в базу данных
        self.con = sqlite3.connect("Players.db")
        self.cur = self.con.cursor()
        for i, j in COORDS.items():
            self.cur.execute(f"""UPDATE {who} SET {i[0]} = '{str(self.boardMap.item(*COORDS[i]).text())}'
                         WHERE id={int(i[1:])}""")
        self.con.commit()


    def start(self):
        """Если Игрок1 нажал кнопку,
        то Игрок2 начинает заполнять данные.
        Иначе начинает игру"""
        # Проверка, все ли корабли поставлены
        if any(self.count.values()):
            self.error("Вы не поставили все корабли")
            return
        if self.sender().text() == 'Я  готов':
            self.new_db("Player1")
            players.append(Player('Player1', self.boardMap, self.ships))  # Добавление в список игрока
            players
            self.readyButton.setText("Я готов")
            self.playerLabel.setText("Игрок 2")
            self.new_count()  # Обновление переменных-счётчиков
            self.new_map()  # Обновление карты



        else:
            self.new_db("Player2")
            players.append(Player('Player2', self.boardMap, self.ships))  # Добавление в список игрока
            windows.setCurrentIndex(1)

    def new_count(self):  # Создание(обновление) переменных-счётчиков
        self.count = { 'L': 1, 'K': 2, 'E': 3, 'T': 4}
        self.ships = { 'L': [], 'K': [], 'E': [], 'T': []}
        for who in "TEKL":
            {'L': self.linkorButton,
             'K': self.kreyserButton,
             'E': self.esminecButton,
             'T': self.torpedButton}[who].setToolTip(f"{self.count[who]} left")

    def coords_is_right(self, new_coords, num, mode='dual'):
        # проверка на правильность введённых координат
        new_coords[0] = new_coords[0].upper()
        new_coords[1] = new_coords[1].upper()
        if mode != 'v':
            return (COORDS[new_coords[1]][0] - COORDS[new_coords[0]][0] == 0 and
                    COORDS[new_coords[1]][1] - COORDS[new_coords[0]][1] == num) or \
                   (COORDS[new_coords[1]][0] - COORDS[new_coords[0]][0] == num and
                    COORDS[new_coords[1]][1] - COORDS[new_coords[0]][1] == 0)
        return (COORDS[new_coords[1]][0] - COORDS[new_coords[0]][0] == num and
                COORDS[new_coords[1]][1] - COORDS[new_coords[0]][1] == 0)

    def check(self, c1, c2, i, num):
        # Проверка, если в координатах есть * или X,
        if num == 1:
            return (str(self.boardMap.item(c1 + i, c2).text()) == "*" or
                    str(self.boardMap.item(c1 + i, c2).text()) == "X")
        return (str(self.boardMap.item(c1, c2 + i).text()) == "*" or
                str(self.boardMap.item(c1, c2 + i).text()) == "X")

    def error(self, text="Недопустимый размер или форма корабля."):  # Вызов ошибки
        QMessageBox.critical(self, 'Ошибка!', text)

    def setShipByType(self, coords, num, who):  # Создание любого корабля на поле
        error = False
        new_coords = coords.split('-')
        if self.coords_is_right(new_coords, num):
            vertical = self.coords_is_right(new_coords, num, 'v')
            c1, c2 = COORDS[new_coords[0]][0], COORDS[new_coords[0]][1]
            for i in range(num + 1):
                if self.check(c1, c2, i, 1 if vertical else 2):
                    self.error("Сюда нельзя поставить корабль")
                    return
            coords_as_num = []
            for i in range(num + 1):
                if not vertical:
                    self.boardMap.setItem(c1, c2 + i, new_cell_x())
                    coords_as_num.append((c1, c2 + i))
                    if i == num:
                        self.map.shoot(c1, c2 + i, "sink")
                else:
                    self.boardMap.setItem(c1 + i, c2, new_cell_x())
                    coords_as_num.append((c1 + i, c2))
                    if i == num:
                        self.map.shoot(c1 + i, c2, 'sink')
            self.count[who] -= 1
            self.ships[who].append([coords_as_num, {'L': 4, 'K': 3, 'E': 2, 'T': 1}[who]])
            {'L': self.linkorButton,
             'K': self.kreyserButton,
             'E': self.esminecButton,
             'T': self.torpedButton}[who].setToolTip(f"{self.count[who]} left")

        else:
            self.error()



    def setShip(self):  # Создание корабля
        items = sorted(["ABCDEFGHIJ"[item.column()]+str(item.row()+1) for item in self.boardMap.selectedItems()], key=natural_key)
        n = len(items)
        if 1 <= n <= 4:
            if self.count[' TEKL'[n]] == 0:
                self.error("Все корабли этого типа поставлены")
                return
            try:
                self.setShipByType(f"{items[0]}-{items[-1]}", n-1, " TEKL"[n])
            except BaseException:
                self.error()
        else:
            self.error()


class PVPMain(QMainWindow, Ui_MainWindow_pvp):
    def __init__(self, parent=None):
        super(PVPMain, self).__init__(parent)
        self.setupUi(self)


        self.turn = "Игрок1"  # Очередь первого игрока

        self.map = []
        self.map.append(SeaMap(self.tableWidget))
        self.map.append(SeaMap(self.tableWidget_2))

        self.new_boards()  # Создание игрового поля

        self.initUI()

    def initUI(self):
        self.tableWidget.cellClicked[int, int].connect(self.course1)
        self.tableWidget_2.cellClicked[int, int].connect(self.course2)


        self.board1Label.setText("Игрок 1")
        self.board2Label.setText("Игрок 2")
        self.board1Label.setStyleSheet("background-color: #B22222")
        self.board2Label.setStyleSheet("background-color: #1E90FF")


        self.tableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)

        self.tableWidget.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)


        self.tableWidget_2.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)

        self.tableWidget_2.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)

    def new_boards(self):
        for i in range(self.tableWidget.columnCount()):
            for j in range(self.tableWidget.rowCount()):
                self.tableWidget.setItem(i, j, new_cell_dot())
        for i in range(self.tableWidget_2.columnCount()):
            for j in range(self.tableWidget_2.rowCount()):
                self.tableWidget_2.setItem(i, j, new_cell_dot())
        self.tableWidget.resizeColumnsToContents()
        self.tableWidget.resizeRowsToContents()
        self.tableWidget_2.resizeColumnsToContents()
        self.tableWidget_2.resizeRowsToContents()

    def change_of_course(self):  # Смена хода
        if self.turn == "Игрок1":
            self.turn = "Игрок2"
            self.board2Label.setStyleSheet("background-color: #B22222")
            self.board1Label.setStyleSheet("background-color: #1E90FF")
            players[0], players[1] = players[1], players[0]
        elif self.turn == "Игрок2":
            self.turn = "Игрок1"
            self.board1Label.setStyleSheet("background-color: #B22222")
            self.board2Label.setStyleSheet("background-color: #1E90FF")
            players[0], players[1] = players[1], players[0]


    def info(self, text="Координаты правильные"):  # Информационное табло
        QMessageBox.information(self, "INFO", text)

    def error(self, text="Вы уже стреляли в эту клетку."):  # Вызов ошибки
        QMessageBox.critical(self, 'Ошибка!', text)

    def check(self):
        if all(players[1].board[i][j] == 0 for i in range(10) for j in range(10)):
            self.info(f"Выиграл {self.turn}!")
            windows.setCurrentIndex(5)
            return

    def course1(self, c1, c2):
        self.course(c1, c2, 1)

    def course2(self, c1, c2):
        self.course(c1, c2, 2)

    def course(self, r, c, num):  # Ход
        if self.turn[-1] == '1' and num == 2 or self.turn[-1] == '2' and num == 1:
            flag = True
            coord = (r, c)
        else:
            flag = False

        if num == 1:
            if str(self.tableWidget.item(r, c).text()) == "*" or str(self.tableWidget.item(r, c).text()) == "X" :
                self.error()
                return
        else:
            if str(self.tableWidget_2.item(r, c).text()) == "*" or str(self.tableWidget_2.item(r, c).text()) == "X" :
                self.error()
                return

        if flag:
            if self.dot_or_notdot((r, c)):
                dead = self.shootAndCheckIfShipIsDead((r, c))
                what = 'sink' if dead else  'hit'
                pl = 1 if self.turn[-1] == '1' else 0
                self.map[pl].shoot(r, c, what)
                players[1].board[r][c] = 0
                self.info("Корабль потоплен!" if dead else "Попадание!")

                self.check()
            else:
                pl = 1 if self.turn[-1] == '1' else 0
                self.map[pl].shoot(r, c, 'miss')
                self.info("Промах!")

                self.change_of_course()
        else:
            QMessageBox.critical(self, "Ошибка!", "Не ваша очередь!")

    def dot_or_notdot(self, coord):  # Проверка попал, не попал
        new_coord = None
        for key, value in COORDS.items():
            if value == coord:
                new_coord = (key, value)
                break
        con = sqlite3.connect("Players.db")
        cur = con.cursor()
        result = cur.execute(
            f"""SELECT {new_coord[0][0]} FROM Player{players[1].who[-1]}
            WHERE id={new_coord[1][0] + 1}""").fetchone()
        if result[0] == "." or result[0] == "*":
            return False
        return True

    def shootAndCheckIfShipIsDead(self, pos):  # Стреляем по кораблю и проверяем, потопил или ранил
        x, y = pos
        if 0 <= x < 10 and 0 <= y < 10:
            if players[1].board[x][y] == 1:
                for who in "TEKL":
                    for ship in players[1].ships[who]:
                        if pos in ship[0]:
                            ship[1] -= 1
                            return ship[1] == 0
        return False




class Player:
    def __init__(self, who, map, ships):
        self.who = who
        self.board = []
        self.ships = ships
        for i in range(10):
            self.board.append([])
            for j in range(10):
                self.board[i].append(0)
        for i in range(10):
            for j in range(10):
                if str(map.item(i, j).text()) == 'X':
                    self.board[i][j] = 1


class SeaMap:
    def __init__(self, board):
        self.map = board

    def shoot(self, row, col, result):
        if result == 'miss':
            self.map.setItem(row, col, new_cell_mul())
        elif result == 'hit':
            self.map.setItem(row, col, new_cell_x())
        elif result == 'sink':
            for i in range(row - 1, row + 2):
                for j in range(col - 1, col + 2):
                    if 0 <= i < 10 and 0 <= j < 10:
                        if str(self.map.item(i, j).text()) == '.':
                            self.map.setItem(i, j, new_cell_mul())
            self.map.setItem(row, col, new_cell_x())
            for j in range(10):
                if str(self.map.item(row, j).text()) == 'X':
                    col = j
                    for i in range(row - 1, row + 2):
                        for u in range(col - 1, col + 2):
                            if 0 <= i < 10 and 0 <= u < 10:
                                if str(self.map.item(i, u).text()) == '.':
                                    self.map.setItem(i, u, new_cell_mul())
            for v in range(10):
                if str(self.map.item(v, col).text()) == 'X':
                    row = v
                    for v in range(row - 1, row + 2):
                        for u in range(col - 1, col + 2):
                            if 0 <= v < 10 and 0 <= u < 10:
                                if str(self.map.item(v, u).text()) == '.':
                                    self.map.setItem(v, u, new_cell_mul())


if __name__ == '__main__': 
    app = QApplication(sys.argv)


    ready_window = ReadyMain()
    pvp_window = PVPMain()

    windows = QStackedWidget()


    windows.addWidget(ready_window)  # 0
    windows.addWidget(pvp_window)  # 1


    windows.setWindowTitle("Морской бой")
    windows.show()
    sys.exit(app.exec())

Ранен Убит

→ Ссылка