Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Скриптовые языки программирования > Python
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.03.2021, 23:22   #1
_human_
Пользователь
 
Регистрация: 15.02.2021
Сообщений: 10
По умолчанию Игра "жизнь". Клеточный автомат.

Я написал клеточный автомат "жизнь", вот код (состоит из 2х файлов, главного и файла classes.py):
главный:
Код:
import pygame
import time
import classes

FPS = 0
pygame.init()
sc = pygame.display.set_mode((1200, 800))
pygame.display.set_caption("FPS = " + str(FPS))

class desk_grafikal(classes.desk):
    def __init__(self, w, h, a):
        classes.desk.__init__(self, w, h, a)
    def draw(self):
        y = 0
        for i in self.desk:
            x = 0
            for a in i:
                if a == 1:
                    pygame.draw.rect(sc, (0, 255, 0), (x * self.a, y * self.a, self.a, self.a))
                else:
                    pygame.draw.rect(sc, (255, 0, 0), (x * self.a, y * self.a, self.a, self.a))
                x += 1
            y += 1
        
a = desk_grafikal(50, 50, 10)

simulating = 0
time0 = time.time()
flRunning = True
while flRunning:
    time1 = time.time()
    FPS = 1//(time1 - time0)
    pygame.display.set_caption("FPS = " + str(FPS))
    
    a.draw()
    if simulating:
        a.update()
        
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            print("Закрытие окна...")
            pygame.quit()
            flRunning = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                a.kletka_klic(coord = event.pos)
            elif event.button == 3:
                if simulating:
                    simulating = 0
                else:
                    simulating = 1
    time0 = time1
    pygame.display.flip()
#    time.sleep(0.05)
    sc.fill((0, 0, 0))
classes.py:
Код:
import numpy as np

class desk:
    def __init__(self, w, h, a):
        self.desk = np.int8(np.zeros((h, w)))
        self.w = w
        self.h = h
        self.a = a
        self.nears = np.array([[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]])
    def kletka_klic(self, coord = (0, 0)):
        x = coord[0] // self.a
        y = coord[1] // self.a
        if x < self.w + 1 and y < self.h + 1:
            self.delta_color(x, y, self.desk)
        else:
            print("!!!такой клетки нет!!!")
    def delta_color(self, x, y, desk):
        if desk[y][x] == 1:
            desk[y][x] = 0
        else:
            desk[y][x] = 1
    def count(self, x, y):
        count = 0
        for i in self.nears:
            if self.desk[(y + i[1]) % self.h][(x + i[0]) % self.w] == 1:
                count += 1
        return count
    def update(self):
        y = 0
        desk = self.desk.copy()
        for i in self.desk:
            x = 0
            for a in i:
                c = self.count(x, y)
                if desk[y][x] == 1:
                    if c < 2 or c > 3:
                        self.delta_color(x, y, desk)
                else:
                    if c == 3:
                        self.delta_color(x, y, desk)
                x += 1
            y += 1
        self.desk = desk.copy()
Левой кнопкой мыши меняется состояние клетки, правой запускается/останавливается визуализация. Она вроде работает корректно, но очень медленно. При размере поля приведённом в коде, FPS равен 10, при визуализации.
Можно как-то поднять FPS? (например, сработает ли в качестве ускорения обработка не всей доски, а только живых клеток, через словарь?)
В конечной цели требуется поле примерно 500 на 500. Питон просто не справится с этим, и нужно переписывать, например, на С++, или просто на столько моя программа кривая, что она такая медленная?
_human_ вне форума Ответить с цитированием
Старый 17.03.2021, 04:03   #2
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

Немного поменял classes.py, стало в 3 раза быстрее:
Код:
import numpy as np

class desk:
    def __init__(self, w, h, a):
        self.old_desk = np.int8(np.zeros((h, w)))
        self.new_desk = np.int8(np.zeros((h, w)))
        self.desk = self.old_desk
        self.w = w
        self.h = h
        self.a = a

    def kletka_klic(self, coord = (0, 0)):
        x = coord[0] // self.a
        y = coord[1] // self.a
        if x < self.w + 1 and y < self.h + 1:
            self.delta_color(x, y, self.desk)
        else:
            print("!!!такой клетки нет!!!")

    def delta_color(self, x, y, desk):
        if desk[y][x] == 1:
            desk[y][x] = 0
        else:
            desk[y][x] = 1

    def update(self):
        old_desk = self.old_desk
        new_desk = self.new_desk
        w, h = self.w, self.h
        for y, i in enumerate(old_desk):
            for x, a in enumerate(i):
                c = -old_desk[y][x]
                for x1 in range(x - 1, x + 2):
                    for y1 in range(y - 1, y + 2):
                        c += old_desk[y1 % h][x1 % w]
                if a == 1:
                    if c < 2 or c > 3:
                        new_desk[y][x] = 0
                    else:
                        new_desk[y][x] = 1
                else:
                    if c == 3:
                        new_desk[y][x] = 1
                    else:
                        new_desk[y][x] = 0
        self.desk = new_desk
        self.new_desk = old_desk
        self.old_desk = new_desk
Цитата:
Сообщение от _human_
обработка не всей доски, а только живых клеток
Если их будет заметно меньше, чем общее количество клеток, то да. Например, в 7 раз быстрее (с одним планером на поле):
Код:
import numpy as np

class desk:
    def __init__(self, w, h, a):
        self.desk = np.int8(np.zeros((h, w)))
        self.w = w
        self.h = h
        self.a = a
        self.alive = []

    def kletka_klic(self, coord = (0, 0)):
        x = coord[0] // self.a
        y = coord[1] // self.a
        if x < self.w + 1 and y < self.h + 1:
            self.delta_color(x, y, self.desk)
        else:
            print("!!!такой клетки нет!!!")

    def delta_color(self, x, y, desk):
        if desk[y][x] == 1:
            desk[y][x] = 0
            self.alive.remove((x, y))
        else:
            desk[y][x] = 1
            self.alive.append((x, y))

    def update(self):
        desk, w, h = self.desk, self.w, self.h
        new_desk = np.int8(np.zeros((h, w)))
        new_alive = []

        proccessed = set()

        for x, y in self.alive:
            for x1 in range(x - 1, x + 2):
                for y1 in range(y - 1, y + 2):
                    proccessed.add((x1 % w, y1 % h))

        for x, y in proccessed:
            c = -desk[y][x]
            for x1 in range(x - 1, x + 2):
                for y1 in range(y - 1, y + 2):
                    c += desk[y1 % h][x1 % w]
            if ((desk[y][x] == 1 and not (c < 2 or c > 3)) or (desk[y][x] == 0 and c == 3)):
                new_desk[y][x] = 1
                new_alive.append((x, y))

        self.desk = new_desk
        self.alive = new_alive
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Игра "Жизнь". Проблема с границами DrawGrid KateTr Помощь студентам 0 02.04.2017 18:33
C++ "Игра жизнь" Горыныч Помощь студентам 1 14.12.2014 15:26
Игра "Жизнь" на Assembler kolo6awka Помощь студентам 0 22.12.2013 21:21
Игра "Жизнь" на C++, console application zoluxa Общие вопросы C/C++ 11 16.11.2012 17:47
Клеточный автомат (Игра Жизнь) в Delphi nitroes Фриланс 4 12.03.2012 13:11