Skip to content

блок схема #114

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()

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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