import kivy
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle, Color
from kivy.core.window import Window
from random import randint
from kivy.uix.label import Label
from kivy.config import Config

# Встановлюємо портретну орієнтацію та відключаємо автоматичне повертання екрану
Config.set('graphics', 'orientation', 'portrait')
Config.set('graphics', 'resizable', '0')  # Вимикаємо зміну розміру вікна (для ПК)

class SnakeGame(Widget):
    def __init__(self, **kwargs):
        super(SnakeGame, self).__init__(**kwargs)
        self.snake = []
        self.snake_length = 3
        self.direction = 'right'
        self.speed = 0.1  # Швидкість гри, менше значення - швидше (час між оновленнями логіки)
        self.animation_progress = 0  # Прогрес анімації від 0 до 1
        self.animation_duration = self.speed  # Тривалість анімації між комірками
        self.food = None
        self.score = 0

        # Розмір комірки та кількість стовпчиків/рядків
        self.cell_size = 20
        self.cols = int(Window.width / self.cell_size)
        self.rows = int(Window.height / self.cell_size)

        # Початкова позиція змійки в центрі
        initial_x = int(self.cols/2)
        initial_y = int(self.rows/2)
        for i in range(self.snake_length):
            self.snake.append({'prev': (initial_x - i, initial_y), 'current': (initial_x - i, initial_y)})

        self.place_food()  # Розміщуємо першу їжу

        # Запускаємо оновлення гри
        Clock.schedule_interval(self.update, 1/60)  # Онволюємо 60 разів на секунду

        # Для обробки свайпів
        self.touch_start = None
        self.time_since_last_move = 0  # Час, що минув з останнього кроку гри

    def place_food(self):
        # Випадкове розміщення їжі на полі
        food_x = randint(0, self.cols - 1)
        food_y = randint(0, self.rows - 1)
        while any(segment['current'] == (food_x, food_y) for segment in self.snake):
            food_x = randint(0, self.cols - 1)
            food_y = randint(0, self.rows - 1)
        self.food = (food_x, food_y)

    def update(self, dt):
        self.time_since_last_move += dt
        self.animation_progress += dt / self.animation_duration

        if self.animation_progress >= 1:
            self.animation_progress = 0

            # Оновлення позиції змійки в логіці гри
            self.update_snake()

            self.time_since_last_move = 0

        self.draw()

    def update_snake(self):
        # Оновлення позиції змійки
        head_x, head_y = self.snake[0]['current']

        if self.direction == 'up':
            head_y += 1
        elif self.direction == 'down':
            head_y -= 1
        elif self.direction == 'left':
            head_x -= 1
        elif self.direction == 'right':
            head_x += 1

        new_head_pos = (head_x, head_y)

        # Перевірка на зіткнення зі стінами або самим собою
        if (head_x < 0 or head_x >= self.cols or
            head_y < 0 or head_y >= self.rows or
            any(segment['current'] == new_head_pos for segment in self.snake)):
            self.game_over()
            return

        # Додаємо нову голову з поточною та попередньою позицією
        self.snake.insert(0, {'prev': self.snake[0]['current'], 'current': new_head_pos})

        # Перевірка на з'їдання їжі
        if self.food == new_head_pos:
            self.score += 1
            self.place_food()
        else:
            # Видаляємо останній сегмент, якщо їжа не з'їдена
            self.snake.pop()
        # Оновлюємо 'prev' для кожного сегмента
        for i in range(1, len(self.snake)):
            self.snake[i]['prev'] = self.snake[i]['current']

    def draw(self):
        self.canvas.clear()
        with self.canvas:
            # Малюємо їжу
            Color(1, 0, 0)  # Червоний колір
            Rectangle(pos=(self.food[0]*self.cell_size, self.food[1]*self.cell_size),
                      size=(self.cell_size, self.cell_size))

            # Малюємо змійку
            Color(0, 1, 0)  # Зелений колір
            for segment in self.snake:
                # Інтерполюємо позицію між prev та current
                prev_x, prev_y = segment['prev']
                curr_x, curr_y = segment['current']
                interp_x = (prev_x + (curr_x - prev_x) * self.animation_progress) * self.cell_size
                interp_y = (prev_y + (curr_y - prev_y) * self.animation_progress) * self.cell_size
                Rectangle(pos=(interp_x, interp_y),
                          size=(self.cell_size, self.cell_size))

    def on_touch_down(self, touch):
        # Зберігаємо початкову позицію торкання
        self.touch_start = touch.pos

    def on_touch_up(self, touch):
        # Коли палець відпущено, визначаємо напрямок свайпа
        if self.touch_start:
            dx = touch.x - self.touch_start[0]
            dy = touch.y - self.touch_start[1]

            if abs(dx) > abs(dy):
                # Горизонтальний свайп
                if dx > 0 and self.direction != 'left':
                    self.direction = 'right'
                elif dx < 0 and self.direction != 'right':
                    self.direction = 'left'
            else:
                # Вертикальний свайп
                if dy > 0 and self.direction != 'down':
                    self.direction = 'up'
                elif dy < 0 and self.direction != 'up':
                    self.direction = 'down'

            self.touch_start = None  # Скидаємо початкову позицію

    def game_over(self):
        # Завершення гри
        Clock.unschedule(self.update)
        self.canvas.clear()
        self.add_widget(Label(text='Гру завершено\nРахунок: ' + str(self.score),
                              font_size='40sp',
                              center_x=Window.width/2,
                              center_y=Window.height/2))

class SnakeApp(App):
    def build(self):
        game = SnakeGame()
        return game

if __name__ == '__main__':
    SnakeApp().run()

Зроби щоб після програшу було *Ви програли! Грати знову?*. Кнопка з надписом *Грати знову*