222 lines
8.8 KiB
Python
222 lines
8.8 KiB
Python
|
import random
|
||
|
import numpy as np
|
||
|
import pygame
|
||
|
|
||
|
# Wymiary planszy
|
||
|
rows, cols = 10, 10 # Ustalona liczba wierszy i kolumn
|
||
|
size = 50 # Rozmiar pojedynczego pola na planszy
|
||
|
|
||
|
|
||
|
# Klasa reprezentująca planszę
|
||
|
class Board:
|
||
|
def __init__(self):
|
||
|
self.board = [] # Tablica reprezentująca planszę
|
||
|
self.vegetables = [] # Tablica przechowująca warzywa na planszy
|
||
|
self.soil_features = None # Cechy gleby (wilgotność, temperatura itp.)
|
||
|
self.vegetable_names = [] # Tablica przechowująca nazwy warzyw na planszy
|
||
|
self.load_images() # Ładowanie obrazów warzyw i innych elementów planszy
|
||
|
self.generate_board() # Generowanie początkowej planszy
|
||
|
|
||
|
# Metoda do ładowania obrazów
|
||
|
def load_images(self):
|
||
|
self.grass = pygame.Surface((size, size)) # Tworzenie powierzchni dla trawy
|
||
|
self.grass.fill((0, 255, 0)) # Wypełnienie powierzchni zielonym kolorem (trawa)
|
||
|
|
||
|
# Tworzenie powierzchni dla różnych warzyw
|
||
|
self.warzywa_images = {
|
||
|
"pomidor": [pygame.Surface((size, size)) for _ in range(9)],
|
||
|
"ogorek": [pygame.Surface((size, size)) for _ in range(9)],
|
||
|
"kalafior": [pygame.Surface((size, size)) for _ in range(9)]
|
||
|
}
|
||
|
|
||
|
# Kolory przypisane do każdego warzywa
|
||
|
colors = {
|
||
|
"pomidor": (255, 0, 0), # Czerwony
|
||
|
"ogorek": (255, 165, 0), # Pomarańczowy
|
||
|
"kalafior": (255, 255, 255) # Biały
|
||
|
}
|
||
|
|
||
|
# Wypełnianie powierzchni odpowiednim kolorem dla każdego warzywa
|
||
|
for veg, color in colors.items():
|
||
|
for surface in self.warzywa_images[veg]:
|
||
|
surface.fill(color)
|
||
|
|
||
|
# Typy warzyw przypisane do liczb
|
||
|
self.vegetable_types = {
|
||
|
"pomidor": 1,
|
||
|
"ogorek": 2,
|
||
|
"kalafior": 3
|
||
|
}
|
||
|
|
||
|
# Metoda do generowania początkowej planszy
|
||
|
def generate_board(self):
|
||
|
self.board = [[random.choice([0, 1, 2, 3]) for _ in range(cols)] for _ in range(rows)]
|
||
|
self.vegetables = [[None for _ in range(cols)] for _ in range(rows)]
|
||
|
self.vegetable_names = [[None for _ in range(cols)] for _ in range(rows)]
|
||
|
|
||
|
# Losowe przypisanie warzyw do planszy
|
||
|
for row in range(rows):
|
||
|
for col in range(cols):
|
||
|
if self.board[row][col] in (1, 2, 3):
|
||
|
vegetable_type = list(self.warzywa_images.keys())[self.board[row][col] - 1]
|
||
|
vegetable_image = random.choice(self.warzywa_images[vegetable_type])
|
||
|
self.vegetables[row][col] = vegetable_image
|
||
|
self.vegetable_names[row][col] = vegetable_type
|
||
|
|
||
|
self.soil_features = self.generate_soil_features() # Generowanie cech gleby
|
||
|
|
||
|
# Metoda do generowania cech gleby
|
||
|
def generate_soil_features(self):
|
||
|
return {
|
||
|
"wilgotnosc_gleby": random.randint(30, 70),
|
||
|
"temperatura_gleby": random.randint(13, 26),
|
||
|
"opady_deszczu": random.randint(0, 11),
|
||
|
"wiek_rosliny": random.randint(1, 9),
|
||
|
"proc_ekspo_na_swiatlo": random.randint(10, 90),
|
||
|
"pora_dnia": random.randint(8, 20),
|
||
|
"pora_roku": random.randint(1, 4)
|
||
|
}
|
||
|
|
||
|
# Metoda oceniająca jakość planszy
|
||
|
def evaluate(self):
|
||
|
score = 0
|
||
|
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # Kierunki: prawo, dół, lewo, góra
|
||
|
|
||
|
# Sprawdzanie sąsiednich pól dla każdego warzywa
|
||
|
for row in range(rows):
|
||
|
for col in range(cols):
|
||
|
if self.is_vegetable(row, col):
|
||
|
for dr, dc in directions:
|
||
|
new_row, new_col = row + dr, col + dc
|
||
|
if 0 <= new_row < rows and 0 <= new_col < cols:
|
||
|
if self.vegetable_names[row][col] == self.vegetable_names[new_row][new_col]:
|
||
|
score += 1
|
||
|
return score
|
||
|
|
||
|
# Metoda mutująca planszę
|
||
|
def mutate(self, mutation_rate):
|
||
|
for row in range(rows):
|
||
|
for col in range(cols):
|
||
|
if random.random() < mutation_rate:
|
||
|
self.board[row][col] = random.choice([0, 1, 2, 3])
|
||
|
if self.board[row][col] in (1, 2, 3):
|
||
|
vegetable_type = list(self.warzywa_images.keys())[self.board[row][col] - 1]
|
||
|
vegetable_image = random.choice(self.warzywa_images[vegetable_type])
|
||
|
self.vegetables[row][col] = vegetable_image
|
||
|
self.vegetable_names[row][col] = vegetable_type
|
||
|
|
||
|
# Metoda krzyżująca planszę z inną planszą
|
||
|
def crossover(self, other_board):
|
||
|
crossover_point = random.randint(0, rows * cols - 1)
|
||
|
for i in range(rows):
|
||
|
for j in range(cols):
|
||
|
if i * cols + j > crossover_point:
|
||
|
self.board[i][j], other_board.board[i][j] = other_board.board[i][j], self.board[i][j]
|
||
|
self.vegetables[i][j], other_board.vegetables[i][j] = other_board.vegetables[i][j], \
|
||
|
self.vegetables[i][j]
|
||
|
self.vegetable_names[i][j], other_board.vegetable_names[i][j] = other_board.vegetable_names[i][j], \
|
||
|
self.vegetable_names[i][j]
|
||
|
|
||
|
# Metoda kopiująca planszę
|
||
|
def copy(self):
|
||
|
new_board = Board()
|
||
|
new_board.board = [row[:] for row in self.board]
|
||
|
new_board.vegetables = [row[:] for row in self.vegetables]
|
||
|
new_board.vegetable_names = [row[:] for row in self.vegetable_names]
|
||
|
new_board.soil_features = self.soil_features.copy()
|
||
|
return new_board
|
||
|
|
||
|
# Sprawdza, czy dane pole zawiera warzywo
|
||
|
def is_vegetable(self, row, col):
|
||
|
return self.board[row][col] in (1, 2, 3)
|
||
|
|
||
|
# Rysowanie planszy na oknie pygame
|
||
|
def draw_cubes(self, win):
|
||
|
for row in range(rows):
|
||
|
for col in range(cols):
|
||
|
cube_rect = pygame.Rect(col * size, row * size, size, size)
|
||
|
cube = self.board[row][col]
|
||
|
if cube == 0:
|
||
|
win.blit(self.grass, cube_rect)
|
||
|
else:
|
||
|
if self.vegetables[row][col]:
|
||
|
vegetable_image = pygame.transform.scale(self.vegetables[row][col], (size, size))
|
||
|
win.blit(vegetable_image, cube_rect)
|
||
|
|
||
|
|
||
|
# Funkcja oceniająca planszę (wywołuje metodę evaluate)
|
||
|
def evaluate(board):
|
||
|
return board.evaluate()
|
||
|
|
||
|
|
||
|
# Generowanie początkowej populacji plansz
|
||
|
def generate_population(size):
|
||
|
return [Board() for _ in range(size)]
|
||
|
|
||
|
|
||
|
# Selekcja metodą ruletki
|
||
|
def roulette_wheel_selection(population, fitnesses):
|
||
|
total_fitness = sum(fitnesses)
|
||
|
selection_probs = [f / total_fitness for f in fitnesses]
|
||
|
return population[random.choices(range(len(population)), weights=selection_probs, k=1)[0]]
|
||
|
|
||
|
|
||
|
# Krzyżowanie jednopunktowe
|
||
|
def crossover(parent1, parent2):
|
||
|
child1, child2 = parent1.copy(), parent2.copy()
|
||
|
child1.crossover(child2)
|
||
|
return child1, child2
|
||
|
|
||
|
|
||
|
# Mutacja planszy
|
||
|
def mutate(board, mutation_rate):
|
||
|
board.mutate(mutation_rate)
|
||
|
|
||
|
|
||
|
# Algorytm genetyczny
|
||
|
def genetic_algorithm(pop_size, generations, mutation_rate):
|
||
|
population = generate_population(pop_size) # Generowanie początkowej populacji
|
||
|
for _ in range(generations):
|
||
|
fitnesses = [evaluate(board) for board in population] # Ocenianie każdej planszy
|
||
|
new_population = []
|
||
|
while len(new_population) < pop_size:
|
||
|
parent1 = roulette_wheel_selection(population, fitnesses) # Wybór rodzica 1 metodą ruletki
|
||
|
parent2 = roulette_wheel_selection(population, fitnesses) # Wybór rodzica 2 metodą ruletki
|
||
|
offspring1, offspring2 = crossover(parent1, parent2) # Krzyżowanie rodziców
|
||
|
mutate(offspring1, mutation_rate) # Mutacja potomka 1
|
||
|
mutate(offspring2, mutation_rate) # Mutacja potomka 2
|
||
|
new_population.extend([offspring1, offspring2]) # Dodanie potomków do nowej populacji
|
||
|
population = new_population # Zamiana starej populacji na nową
|
||
|
best_board = max(population, key=evaluate) # Wybór najlepszej planszy z populacji
|
||
|
return best_board
|
||
|
|
||
|
|
||
|
# Parametry algorytmu
|
||
|
pop_size = 50 # Rozmiar populacji
|
||
|
generations = 200 # Liczba generacji
|
||
|
mutation_rate = 0.05 # Wskaźnik mutacji
|
||
|
|
||
|
# Inicjalizacja Pygame
|
||
|
pygame.init()
|
||
|
win = pygame.display.set_mode((cols * size, rows * size)) # Ustawienie rozmiaru okna
|
||
|
pygame.display.set_caption('Generated Board') # Ustawienie tytułu okna
|
||
|
|
||
|
# Generowanie najlepszej planszy
|
||
|
best_board = genetic_algorithm(pop_size, generations, mutation_rate)
|
||
|
|
||
|
# Rysowanie najlepszej planszy
|
||
|
best_board.draw_cubes(win)
|
||
|
pygame.display.update()
|
||
|
|
||
|
# Zapisywanie planszy do pliku
|
||
|
np.save('generated_board.npy', best_board.board)
|
||
|
|
||
|
# Utrzymanie okna otwartego do zamknięcia przez użytkownika
|
||
|
run = True
|
||
|
while run:
|
||
|
for event in pygame.event.get():
|
||
|
if event.type == pygame.QUIT:
|
||
|
run = False
|
||
|
|
||
|
pygame.quit()
|