
им_КЛЕТК
.docxГУАП
КАФЕДРА № 41
ОТЧЕТ ЗАЩИЩЕН С ОЦЕНКОЙ
ПРЕПОДАВАТЕЛЬ
д-р физ.-мат. наук |
|
|
|
Рождественский Ю.В |
должность, уч. степень, звание |
|
подпись, дата |
|
инициалы, фамилия |
ОТЧЕТ О ЛАБОРАТОРНОЙ РАБОТЕ №1 |
РЕАЛИЗАЦИЯ ИГРЫ "ЖИЗНЬ" НА ОСНОВЕ КЛЕТОЧНОГО АВТОМАТА |
по курсу: ИМИТАЦИОННОЕ МОДЕЛИРОВАНИЕ |
|
|
РАБОТУ ВЫПОЛНИЛ
СТУДЕНТ гр. № |
4116 |
|
|
|
|
|
|
|
подпись, дата |
|
инициалы, фамилия |
Санкт-Петербург 2024
Цель работы: получить навыки имитационного моделирования с помощью клеточного автомата.
Ход работы
Реализована программа клеточного автомата с графическим интерфейсом. Создано игровое поле и определены основные правила автомата. Максимальный возраст клетки 5. С каждой итерацией возраст клетки увеличивается на 1.
Первое правило, пустая клетка становится зеленой или черной, если рядом есть три клетки соответствующего цвета (Рисунок 1-2).
Рисунок 1- Поле до первой итерации
Рисунок 2- Поле после первой итерации
Второе правило, если рядом с клеткой больше шести соседей, она становится пустой из-за перенаселения (Рисунок 3-4)
Рисунок 3- Поле до итерации
Рисунок 4- Поле после итерации
Третье правило, если клетка окружена двумя и больше соседями противоположного цвета, то она стареет в два раза быстрее (Рисунок 5-6).
Рисунок 5- Поле до начала итераций
Рисунок 6- Поле после итераций
Рисунок 7- Начальное состояние автомата
Рисунок 8- Состояние автомата на 85 итерации
Вывод: получены навыки имитационного моделирования с помощью клеточного автомата.
ПРИЛОЖЕНИЕ А. Код программы
import pygame
import pygame_gui
pygame.init()
WIDTH, HEIGHT = 1000, 550
GRID_SIZEX = 90 # Количество клеток по горизонтали
GRID_SIZEY = 50 # Количество клеток по вертикали
CELL_SIZEX = WIDTH // GRID_SIZEX # Ширина клетки
CELL_SIZEY = HEIGHT // GRID_SIZEY # Высота клетки
MAX_AGE = 5
# Цвета
GREEN = (0, 255, 0)
BLACK_COLOR = (0, 0, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)
screen = pygame.display.set_mode((WIDTH, HEIGHT+50))
pygame.display.set_caption("Клеточный автомат")
EMPTY = 0
GREEN_CELL = 1
BLACK_CELL = 2
# Класс для клетки
class Cell:
def __init__(self, x, y):
self.x = x
self.y = y
self.state = EMPTY # Начальное состояние (пустая клетка)
self.age = 0 # Возраст клетки (сколько шагов она прожила)
def draw(self):
if self.state == GREEN_CELL:
pygame.draw.rect(screen, GREEN, (self.x * CELL_SIZEX, self.y * CELL_SIZEY, CELL_SIZEX, CELL_SIZEY))
elif self.state == BLACK_CELL:
pygame.draw.rect(screen, BLACK_COLOR, (self.x * CELL_SIZEX, self.y * CELL_SIZEY, CELL_SIZEX, CELL_SIZEY))
def update(self, grid):
# Увеличиваем возраст клетки
if self.state != EMPTY:
self.age += 1
# Если клетка окружена клетками противоположного цвета, возраст увеличивается на 2
opposite_color = GREEN_CELL if self.state == BLACK_CELL else BLACK_CELL
neighbors = [
grid[nx][ny].state for nx in range(max(0, self.x - 1), min(GRID_SIZEX, self.x + 2))
for ny in range(max(0, self.y - 1), min(GRID_SIZEY, self.y + 2))
if (nx, ny) != (self.x, self.y)
]
if neighbors.count(opposite_color) >= 2:
self.age += 1
# Проверка на смерть от старости
if self.age >= MAX_AGE:
self.state = EMPTY
self.age = 0
grid = [[Cell(x, y) for y in range(GRID_SIZEY)] for x in range(GRID_SIZEX)]
# Функция для выполнения шага итерации
def step_iteration():
new_grid = [[cell.state for cell in row] for row in grid]
for x in range(GRID_SIZEX):
for y in range(GRID_SIZEY):
cell = grid[x][y]
neighbors = [
grid[nx][ny].state for nx in range(max(0, x - 1), min(GRID_SIZEX, x + 2))
for ny in range(max(0, y - 1), min(GRID_SIZEY, y + 2))
if (nx, ny) != (x, y)
]
# Правило 1: Рождение
if cell.state == EMPTY:
if neighbors.count(GREEN_CELL) >= 3:
new_grid[x][y] = GREEN_CELL
elif neighbors.count(BLACK_CELL) >= 3:
new_grid[x][y] = BLACK_CELL
# Правило 2: Перенаселение
elif neighbors.count(GREEN_CELL) + neighbors.count(BLACK_CELL) > 6:
new_grid[x][y] = EMPTY
for x in range(GRID_SIZEX):
for y in range(GRID_SIZEY):
grid[x][y].state = new_grid[x][y]
grid[x][y].update(grid)
# Функция для отрисовки сетки
def draw_grid():
for x in range(0, WIDTH, CELL_SIZEX):
pygame.draw.line(screen, GRAY, (x, 0), (x, HEIGHT), 1)
for y in range(0, HEIGHT, CELL_SIZEY):
pygame.draw.line(screen, GRAY, (0, y), (WIDTH, y), 1)
# Инициализация интерфейса
manager = pygame_gui.UIManager((WIDTH, HEIGHT+50))
# Кнопки
green_button = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((10, HEIGHT+5), (100, 40)),
text='Зеленая',
manager=manager)
black_button = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((120, HEIGHT+5), (100, 40)),
text='Черная',
manager=manager)
pause_button = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((230, HEIGHT+5), (100, 40)),
text='Пуск',
manager=manager)
next_button = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((340, HEIGHT+5), (100, 40)),
text='След. шаг',
manager=manager)
reset_button = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((450, HEIGHT+5), (100, 40)),
text='Сброс',
manager=manager)
# Основной цикл
running = True
paused = True # Начинаем с паузы
current_iteration = 0
# Управление кнопками
selected_cell_type = GREEN_CELL
# Таймер для автоматической итерации
clock = pygame.time.Clock()
iteration_timer = 0
# Флаг для отслеживания зажатия кнопки мыши
mouse_held = False
# Переменные для подсчета клеток
green_cells_count = 0
black_cells_count = 0
# Основной цикл
while running:
time_delta = clock.tick(60) / 1.0 # Обновление времени
iteration_timer += time_delta
screen.fill(WHITE)
# Рисуем сетку
draw_grid()
# Обновляем подсчет клеток
green_cells_count = 0
black_cells_count = 0
for row in grid:
for cell in row:
if cell.state == GREEN_CELL:
green_cells_count += 1
elif cell.state == BLACK_CELL:
black_cells_count += 1
# Отображаем клетки
for row in grid:
for cell in row:
cell.draw()
# Отображение номера итерации
font = pygame.font.SysFont('Impact', 20)
iteration_text = font.render(f"Итерация: {current_iteration}", True, BLACK)
screen.blit(iteration_text, (560, HEIGHT+5))
# Отображение количества клеток
green_count_text = font.render(f"Зеленых: {green_cells_count}", True, BLACK)
screen.blit(green_count_text, (700, HEIGHT+5))
black_count_text = font.render(f"Черных: {black_cells_count}", True, BLACK)
screen.blit(black_count_text, (700, HEIGHT+28))
# Обработка событий
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Обработка кликов мыши для установки клеток
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # Левая кнопка мыши
mouse_x, mouse_y = event.pos
grid_x = mouse_x // CELL_SIZEX
grid_y = mouse_y // CELL_SIZEY
if grid_x < GRID_SIZEX and grid_y < GRID_SIZEY:
grid[grid_x][grid_y].state = selected_cell_type
grid[grid_x][grid_y].age = 0
mouse_held = True # Мышь зажата
if event.type == pygame.MOUSEMOTION and mouse_held:
# Если мышь зажата, ставим клетки по мере движения
mouse_x, mouse_y = event.pos
grid_x = mouse_x // CELL_SIZEX
grid_y = mouse_y // CELL_SIZEY
if grid_x < GRID_SIZEX and grid_y < GRID_SIZEY:
grid[grid_x][grid_y].state = selected_cell_type
grid[grid_x][grid_y].age = 0
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # Левая кнопка мыши
mouse_held = False # Мышь отпущена
# Обработка событий интерфейса
if event.type == pygame_gui.UI_BUTTON_PRESSED:
if event.ui_element == green_button:
selected_cell_type = GREEN_CELL
elif event.ui_element == black_button:
selected_cell_type = BLACK_CELL
elif event.ui_element == pause_button:
paused = not paused
elif event.ui_element == next_button:
step_iteration()
current_iteration += 1
elif event.ui_element == reset_button:
grid = [[Cell(x, y) for y in range(GRID_SIZEY)] for x in range(GRID_SIZEX)]
current_iteration = 0
manager.process_events(event)
manager.update(time_delta)
if not paused and iteration_timer >= 1.0:
step_iteration()
current_iteration += 1
iteration_timer = 0
manager.draw_ui(screen)
pygame.display.update()
pygame.quit()