Scorpion_MB
@Scorpion_MB
Изучаю Питон

Почему код питона работает с ошибками?

Есть код:
spoiler
from random import randint
import os

# здесь просто задаем цвета. Они не соответствуют своим названиям, но главное всё сгруппировано в одном месте
# при желании цвета можно легко поменять не колупаясь во всей логике приложения
class Color:
    yellow2 = '\033[1;35m'
    reset = '\033[0m'
    blue = '\033[0;34m'
    yellow = '\033[1;33m'
    red = '\033[1;31m'
    miss = '\033[1;33m'
    faded = '\033[2;37m'


# функция которая окрашивает текст в заданный цвет.
def set_color(text, color):
    return color + text + Color.reset


# класс "клетка". Здесь мы задаем и визуальное отображение клеток и их цвет.
# по визуальному отображению мы проверяем какого типа клетка. Уж такая реализация.
# По этой причине нельзя обозначать одним символом два разных типа. Иначе в логике возникнет путаница.
class Cell:
    ship_cell = set_color('■', Color.blue)
    destroyed_ship = set_color('X', Color.yellow)
    damaged_ship = set_color('□', Color.yellow)
    miss_cell = set_color('•', Color.miss)
    grid = set_color('•', Color.faded)

class Board:

    letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']

    def __init__(self):
        # self.count_shot = 0
        self.board = []
        for n in range(10):
            self.board.append([Cell.grid]*10)

    @staticmethod
    def clear_screen():
        os.system('cls' if os.name == 'nt' else 'clear')

    def print_board(self):
        print('\n\t\033[1;4;33m* К О М П Ь Ю Т Е Р *\033[0m'.expandtabs(tabsize=7), \
              '\t\033[1;4;33m* И Г Р О К *\033[0m'.expandtabs(tabsize=28), '\n')
        print('  ', end=' ')
        for j in range(10):
            print('\033[1;4;36m', f'{j}', end=' ')
        print('\033[0m\t'.expandtabs(tabsize=16), end='')
        print('   ', end=' ')
        for j in range(10):
            print('\033[1;4;36m', f'{j}', end=' ')
        print('\033[0m')
        for i, row1, j, row2 in zip(self.letters, radar.board, self.letters, user.board):
            print(f'\033[1;35m{i}|', '\033[0m', '  '.join(list(map(str, row1))), '\t'.expandtabs(tabsize=12), \
                  f'\033[1;35m{j}|', '\033[0m', '  '.join(list(map(str, row2))))
        print('')


    def random_row(self):
        return randint(0, len(self.board)-1)

    def random_col(self):
        return randint(0, len(self.board[0])-1)

    def mark_destroyed_ship(self, ship):

        field = radar.board

        x, y = ship.x, ship.y
        width, height = ship.width, ship.height
        # print(width, height)

        for p_x in range(x - 1, x + height + 1):
            for p_y in range(y - 1, y + width + 1):
                if p_x < 0 or p_x >= len(field) or p_y < 0 or p_y >= len(field):
                    continue
                field[p_x][p_y] = Cell.miss_cell

        for p_x in range(x, x + height):
            for p_y in range(y, y + width):
                field[p_x][p_y] = Cell.destroyed_ship

class Ship:
    ships_rules = [4, 3, 3, 2, 2, 2, 1, 1, 1, 1]
    occupied_user = []
    occupied_comp = []
    occupied_radar = []
    count_ship = 10

    def __init__(self, len_ship):
        self.x = user.random_row()
        self.y = user.random_col()
        self.len_ship = len_ship
        self.direction = randint(0, 1)
        self.set_ship()
        self.setup = True
        # self.print_ship()
        # self.install_ship()

    def __str__(self):
        return Cell.ship_cell

    def set_ship(self):
        if self.direction == 0:
            self.height = 1
            self.width = self.len_ship

        if self.direction == 1:
            self.height = self.len_ship
            self.width = 1

        # self.print_ship()

    def print_ship(self):
        print(self.x, self.y, self.len_ship, self.direction)
        # ship.install_ship()

    def install_ship(self, field, occupied):
        if self.x+self.height < 11 and self.y+self.width < 11 and field.board[self.x][self.y] != Cell.ship_cell \
                and (self.x+max(0, self.height-3), self.y+max(0, self.width-3)) not in occupied \
                and (self.x+max(0, self.height-2), self.y+max(0, self.width-2)) not in occupied \
                and (self.x+max(0, self.height-1), self.y+max(0, self.width-1)) not in occupied:
            for l in range(self.len_ship):
                if self.direction == 0:
                    field.board[self.x][self.y+l] = ship
                if self.direction == 1:
                    field.board[self.x+l][self.y] = ship
        else:
            self.setup = False
            return

    def occupied_board(self, field, occupied):
        for o_x in range(self.x - 1, self.x + self.height + 1):
            for o_y in range(self.y - 1, self.y + self.width + 1):
                if o_x < 0 or o_x >= len(field.board) or o_y < 0 or o_y >= len(field.board):
                    continue
                occupied.append((o_x, o_y))
        # print(self.occupied)

    def print_occupied(self, field, occupied):
        for x, y in occupied:
            if str(field.board[x][y]) != Cell.ship_cell:
                field.board[x][y] = Cell.miss_cell

class Shot:

    def __init__(self):
        self.x = None
        self.y = None

    def shot_by_ships(self):
        xy = input('\033[1;32mВаш выстрел (например, d3): ')
        if len(xy) == 2:
            input_x = xy[0]
            if xy[1].isdigit():
                input_y = int(xy[1])
            else:
                input_y = 10
            if input_x in Board.letters and 0 <= input_y < 10:
                self.x = Board.letters.index(input_x)
                self.y = int(xy[1])
                if radar.board[self.x][self.y] in (Cell.miss_cell, Cell.ship_cell, Cell.damaged_ship, Cell.destroyed_ship):
                    print('Эта клетка занята! Еще разок...')
                    self.shot_by_ships()
                self.receive_shot()

            else:
                print('Неправильный ввод. Еще разок... ')
                return self.shot_by_ships()
        else:
            print('Должно быть две координаты. Еще разок...')
            return self.shot_by_ships()


    def receive_shot(self):
        sx = self.x
        sy = self.y
        # radar.count_shot += 1

        if type(comp.board[sx][sy]) == Ship:
            ship = comp.board[sx][sy]
            ship.len_ship -= 1


            if ship.len_ship <= 0:
                radar.mark_destroyed_ship(ship)
                print('\033[1;33mКорабль уничтожен!')
                Ship.count_ship -= 1
                return ship

            radar.board[sx][sy] = Cell.damaged_ship
            print('\033[1;33mПопадание!')
            return 'get'

        else:
            radar.board[sx][sy] = Cell.miss_cell
            print('\033[1;33mПромах!')
            return 'miss'


if __name__ == "__main__":
    user = Board()
    radar = Board()
    # user.print_board()
    comp = Board()
    for len_ship in Ship.ships_rules:
        ship = Ship(len_ship)
        # ship.print_ship()
        ship.install_ship(user, Ship.occupied_user)
        # print(ship.setup)
        while ship.setup == False:
            # print('Повторный запуск')
            ship = Ship(len_ship)
            # ship.print_ship()
            ship.install_ship(user, Ship.occupied_user)
            # print(ship.setup)
        # user.print_board()
        ship.occupied_board(user, Ship.occupied_user)
        # ship.print_occupied(user, Ship.occupied_user)
    for len_ship in Ship.ships_rules:
        ship = Ship(len_ship)
        # ship.print_ship()
        ship.install_ship(comp, Ship.occupied_comp)
        # print(ship.setup)
        while ship.setup == False:
            # print('Повторный запуск')
            ship = Ship(len_ship)
            # ship.print_ship()
            ship.install_ship(comp, Ship.occupied_comp)
            # print(ship.setup)
        # radar.print_board()
        ship.occupied_board(comp, Ship.occupied_comp)
        # ship.print_occupied(radar, Ship.occupied_comp)
    user.print_board()

    while Ship.count_ship > 0:
        shot = Shot()
        # shot.shot_by_ships()
        if shot.shot_by_ships() == 'miss':
            print('\033[1;33mПромах!', 'Внешняя запись')
        elif shot.shot_by_ships() == 'get':
            print('\033[1;33mПопадание!', 'Внешняя запись')
        elif type(shot.shot_by_ships) == Shot:
            print('\033[1;33mКорабль уничтожен!', 'Внешняя запись')
        # radar.clear_screen()

        print('Отрисовка')
        radar.print_board()
    print('\033[1;31mИгра закончена!')


Не всегда ожидаемый результат:

Ваш выстрел (например, d3): f3
Попадание!
Ваш выстрел (например, d3): f4
Промах!
Отрисовка

Как видно, не сработала отрисовка после попадания и не вызвался второй принт.
После промаха отрисовка произошла, но второй принт не сработал.
Бывает и наоборот. В чем может быть причина?
  • Вопрос задан
  • 177 просмотров
Решения вопроса 1
SoreMix
@SoreMix Куратор тега Python
yellow
Ретюрны потеряны тут:

def shot_by_ships(self):
        xy = input('\033[1;32mВаш выстрел (например, d3): ')
        if len(xy) == 2:
            input_x = xy[0]
            if xy[1].isdigit():
                input_y = int(xy[1])
            else:
                input_y = 10
            if input_x in Board.letters and 0 <= input_y < 10:
                self.x = Board.letters.index(input_x)
                self.y = int(xy[1])
                if radar.board[self.x][self.y] in (Cell.miss_cell, Cell.ship_cell, Cell.damaged_ship, Cell.destroyed_ship):
                    print('Эта клетка занята! Еще разок...')
                    self.shot_by_ships()
                self.receive_shot()


Надо:
def shot_by_ships(self):
        xy = input('\033[1;32mВаш выстрел (например, d3): ')
        if len(xy) == 2:
            input_x = xy[0]
            if xy[1].isdigit():
                input_y = int(xy[1])
            else:
                input_y = 10
            if input_x in Board.letters and 0 <= input_y < 10:
                self.x = Board.letters.index(input_x)
                self.y = int(xy[1])
                if radar.board[self.x][self.y] in (Cell.miss_cell, Cell.ship_cell, Cell.damaged_ship, Cell.destroyed_ship):
                    print('Эта клетка занята! Еще разок...')
                    return self.shot_by_ships()
                return self.receive_shot()


И вместо постоянного вызова метода
if shot.shot_by_ships() == 'miss':
    print('\033[1;33mПромах!', 'Внешняя запись')
elif shot.shot_by_ships() == 'get':
    print('\033[1;33mПопадание!', 'Внешняя запись')
elif type(shot.shot_by_ships) == Shot:
    print('\033[1;33mКорабль уничтожен!', 'Внешняя запись')


Вы явно хотите это:
shot_result = shot.shot_by_ships()
if shot_result == 'miss':
    print('\033[1;33mПромах!', 'Внешняя запись')
elif shot_result == 'get':
    print('\033[1;33mПопадание!', 'Внешняя запись')
elif type(shot_result) == Shot:
    print('\033[1;33mКорабль уничтожен!', 'Внешняя запись')

Плюс здесь же нужно исправить с elif type(shot_result) == Shot: на elif type(shot_result) == Ship:
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы