Skip to content

блок схема #114

@izmaylov22-rgb

Description

@izmaylov22-rgb

import pygame
import random
import sys

ИГРА "МОРСКОЙ БОЙ" 6x6

Правила: игрок и компьютер стреляют по полям противника.

Побеждает тот, кто первым сделает 4 попадания.

Корабли (2 корабля по 2 палубы) расставлены так, чтобы не соприкасаться.

pygame.init()

Константы

FIELD_SIZE = 6 # Поле 6x6
CELL_SIZE = 80
WINDOW_WIDTH = CELL_SIZE * FIELD_SIZE * 2 + 150
WINDOW_HEIGHT = CELL_SIZE * FIELD_SIZE + 200
SHIP_COUNT = 2 # 2 корабля
DECK_COUNT = 2 # по 2 палубы каждый
HITS_TO_WIN = 4 # Для победы нужно 4 попадания

Цвета

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (100, 150, 255)
DARK_BLUE = (50, 100, 200)
GRAY = (200, 200, 200)
RED = (255, 0, 0)

Состояния клетки

EMPTY, SHIP, MISS, HIT = 0, 1, 2, 3
class BattleshipGame:
def init(self):
self.screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("Морской бой 6x6")
self.font = pygame.font.SysFont(None, 24)
self.small_font = pygame.font.SysFont(None, 18)

Два игровых поля (0=пусто, 1=корабль, 2=промах, 3=попадание)

self.player_field = [[EMPTY] * FIELD_SIZE for _ in range(FIELD_SIZE)]
self.computer_field = [[EMPTY] * FIELD_SIZE for _ in range(FIELD_SIZE)]
self.game_over = False
self.player_turn = True
self.message = "Ваш ход! Введите координаты (например: A1):"
self.input_buffer = ""

Расстановка кораблей

self.setup_ships(self.player_field)
self.setup_ships(self.computer_field)
def setup_ships(self, field):
"""Случайная расстановка кораблей с проверкой, чтобы не касались краями"""
for _ in range(SHIP_COUNT):
placed = False
attempts = 0
while not placed and attempts < 1000:
x, y = random.randint(0, FIELD_SIZE - 1), random.randint(0, FIELD_SIZE

horizontal = random.choice([True, False])
if self.can_place_ship(field, x, y, horizontal):
self.place_ship(field, x, y, horizontal)
placed = True
attempts += 1
def can_place_ship(self, field, x, y, horizontal):
"""Проверка: корабль помещается и не касается других краями (включая
диагонали)"""

Проверка границ поля

if (horizontal and x + DECK_COUNT > FIELD_SIZE) or (not horizontal and y +
DECK_COUNT > FIELD_SIZE):
return False

Клетки будущего корабля

cells = [(x + i, y) if horizontal else (x, y + i) for i in range(DECK_COUNT)]

Проверка, что все клетки пустые

for cx, cy in cells:
if field[cy][cx] != EMPTY:
return False

Проверка соседей (включая диагонали)

for cx, cy in cells:
for dy in (-1, 0, 1):
for dx in (-1, 0, 1):
nx, ny = cx + dx, cy + dy
if 0 <= nx < FIELD_SIZE and 0 <= ny < FIELD_SIZE:
if field[ny][nx] != EMPTY and (nx, ny) not in cells:
return False
return True
def place_ship(self, field, x, y, horizontal):
"""Размещение корабля на поле"""
for i in range(DECK_COUNT):
if horizontal:
field[y][x + i] = SHIP
else:
field[y + i][x] = SHIP
def draw_field(self, field, x, y, show_ships=False):
"""Отрисовка игрового поля с сеткой и координатами"""

Рисуем сетку

for i in range(FIELD_SIZE + 1):
pygame.draw.line(self.screen, BLACK, (x, y + i * CELL_SIZE), (x +
FIELD_SIZE * CELL_SIZE, y + i * CELL_SIZE), 2)
pygame.draw.line(self.screen, BLACK, (x + i * CELL_SIZE, y), (x + i *
CELL_SIZE, y + FIELD_SIZE * CELL_SIZE), 2)

Рисуем клетки

for row in range(FIELD_SIZE):
for col in range(FIELD_SIZE):
rect = pygame.Rect(x + col * CELL_SIZE + 1, y + row * CELL_SIZE + 1,
CELL_SIZE - 2, CELL_SIZE - 2)

Цвет зависит от состояния клетки

if field[row][col] == EMPTY:
color = BLUE
elif field[row][col] == SHIP:
color = DARK_BLUE if show_ships else BLUE
elif field[row][col] == MISS:
color = GRAY
else: # HIT
color = RED
pygame.draw.rect(self.screen, color, rect)

Буквы столбцов (A-F) - только в первой строке

if row == 0:
letter = self.small_font.render(chr(65 + col), True, BLACK)
self.screen.blit(letter, (x + col * CELL_SIZE + CELL_SIZE // 2 -
5, y - 20))

Цифры строк (1-6) - слева от поля

number = self.small_font.render(str(row + 1), True, BLACK)
self.screen.blit(number, (x - 30, y + row * CELL_SIZE + CELL_SIZE // 2 -
10))
def process_player_shot(self, col, row):
"""Обработка выстрела игрока по полю компьютера"""
if self.computer_field[row][col] == SHIP:
self.computer_field[row][col] = HIT
hits = sum(row.count(HIT) for row in self.computer_field)
self.message = f"Попал! Осталось попаданий: {HITS_TO_WIN - hits}"
if hits >= HITS_TO_WIN:
self.game_over = True
self.message = "Поздравляем! Вы победили!"
elif self.computer_field[row][col] == EMPTY:
self.computer_field[row][col] = MISS
self.message = "Мимо! Ход компьютера..."
self.player_turn = False
def computer_shot(self):
"""Случайный выстрел компьютера по полю игрока"""
while True:
col, row = random.randint(0, FIELD_SIZE - 1), random.randint(0, FIELD_SIZE

if self.player_field[row][col] in (EMPTY, SHIP):
break
if self.player_field[row][col] == SHIP:
self.player_field[row][col] = HIT
hits = sum(row.count(HIT) for row in self.player_field)
self.message = f"Компьютер попал! Осталось попаданий до поражения:
{HITS_TO_WIN - hits}"
if hits >= HITS_TO_WIN:
self.game_over = True
self.message = "Компьютер победил!"
else:
self.player_field[row][col] = MISS
self.message = "Компьютер промахнулся! Ваш ход."
self.player_turn = True
def check_coords(self, text):
"""Преобразует 'A1' в координаты (0,0) и проверяет корректность"""
if len(text) == 2 and text[0].isalpha() and text[1].isdigit():
x, y = ord(text[0]) - ord('A'), int(text[1]) - 1
if 0 <= x < FIELD_SIZE and 0 <= y < FIELD_SIZE:
return x, y
raise ValueError("Используйте формат A1-F6")
def run(self):
"""Главный игровой цикл"""
while True:

Обработка событий

for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE: # Выход по ESC
pygame.quit()
sys.exit()
if self.player_turn and not self.game_over:
if event.key == pygame.K_RETURN and self.input_buffer:
try:
x, y = self.check_coords(self.input_buffer.upper())
if self.computer_field[y][x] in (HIT, MISS):
self.message = "Сюда уже стреляли!"
else:
self.process_player_shot(x, y)
self.input_buffer = ""
except Exception as e:
self.message = f"Ошибка: {e}"
elif event.key == pygame.K_BACKSPACE:
self.input_buffer = self.input_buffer[:-1]
elif event.unicode.isalnum() and len(self.input_buffer) < 3:
self.input_buffer += event.unicode.upper()

Ход компьютера

if not self.player_turn and not self.game_over:
pygame.time.wait(500)
self.computer_shot()

Отрисовка

self.screen.fill(WHITE)
self.draw_field(self.player_field, 50, 50, show_ships=True) #
Левое поле - игрока
self.draw_field(self.computer_field, WINDOW_WIDTH // 2 + 25, 50) #
Правое поле - компьютера

Вывод сообщений и подсказок

self.screen.blit(self.font.render(self.message, True, BLACK), (50,
WINDOW_HEIGHT - 80))
self.screen.blit(self.font.render(f"Ввод: {self.input_buffer}", True,
BLACK), (50, WINDOW_HEIGHT - 40))
self.screen.blit(self.small_font.render("ESC - выход", True, BLACK),
(WINDOW_WIDTH - 100, WINDOW_HEIGHT - 30))
pygame.display.flip()
if not self.game_over:
pygame.time.Clock().tick(30)
if name == "main":
BattleshipGame().run()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions