prototype v2

This commit is contained in:
s464923 2024-06-08 00:03:29 +02:00
parent 14640a2b12
commit 7b358760e9
5 changed files with 80 additions and 56 deletions

View File

@ -3,5 +3,5 @@
<component name="Black"> <component name="Black">
<option name="sdkName" value="Python 3.9 (traktor)" /> <option name="sdkName" value="Python 3.9 (traktor)" />
</component> </component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (traktor)" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (Traktor)" project-jdk-type="Python SDK" />
</project> </project>

View File

@ -2,9 +2,10 @@
<module type="PYTHON_MODULE" version="4"> <module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
<excludeFolder url="file://$MODULE_DIR$/venv" /> <excludeFolder url="file://$MODULE_DIR$/venv" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="jdk" jdkName="Python 3.9 (Traktor)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
</module> </module>

View File

@ -4,8 +4,7 @@ import pygame
# Wymiary planszy # Wymiary planszy
rows, cols = 10, 10 # Ustalona liczba wierszy i kolumn rows, cols = 10, 10 # Ustalona liczba wierszy i kolumn
size = 50 # Rozmiar pojedynczego pola na planszy size = 64 # Rozmiar pojedynczego pola na planszy
# Klasa reprezentująca planszę # Klasa reprezentująca planszę
class Board: class Board:
@ -19,46 +18,59 @@ class Board:
# Metoda do ładowania obrazów # Metoda do ładowania obrazów
def load_images(self): def load_images(self):
self.grass = pygame.Surface((size, size)) # Tworzenie powierzchni dla trawy try:
self.grass.fill((0, 255, 0)) # Wypełnienie powierzchni zielonym kolorem (trawa) self.grass = pygame.image.load("board/grass.png") # Załaduj obraz trawy
self.dirt = pygame.image.load("board/dirt.png") # Załaduj obraz ziemi
self.rock = pygame.image.load("board/rock.png") # Załaduj obraz kamienia
except pygame.error as e:
print(f"Failed to load image: {e}")
self.grass = pygame.Surface((size, size))
self.grass.fill((0, 255, 0)) # Zastępczy kolor zielony (trawa)
self.dirt = pygame.Surface((size, size))
self.dirt.fill((139, 69, 19)) # Zastępczy kolor brązowy (ziemia)
self.rock = pygame.Surface((size, size))
self.rock.fill((128, 128, 128)) # Zastępczy kolor szary (kamień)
# Tworzenie powierzchni dla różnych warzyw # Tworzenie powierzchni dla różnych warzyw
self.warzywa_images = { self.warzywa_images = {
"pomidor": [pygame.Surface((size, size)) for _ in range(9)], "marchewka": [pygame.image.load(f"warzywa/Carrot/{i}.jpg") for i in range(1, 10)],
"ogorek": [pygame.Surface((size, size)) for _ in range(9)], "ziemniak": [pygame.image.load(f"warzywa/Potato/{i}.jpg") for i in range(1, 10)],
"kalafior": [pygame.Surface((size, size)) for _ in range(9)] "pomidor": [pygame.image.load(f"warzywa/tomato/{i}.jpg") for i in range(1, 10)],
"fasola": [pygame.image.load(f"warzywa/Bean/{i}.jpg") for i in range(1, 10)],
"dynia": [pygame.image.load(f"warzywa/Pumpkin/{i}.jpg") for i in range(1, 10)],
"rzodkiewka": [pygame.image.load(f"warzywa/Radish/{i}.jpg") for i in range(1, 10)],
"ogorek": [pygame.image.load(f"warzywa/Cucumber/{i}.jpg") for i in range(1, 10)],
"kalafior": [pygame.image.load(f"warzywa/Cauliflower/{i}.jpg") for i in range(1, 10)],
"kapusta": [pygame.image.load(f"warzywa/Cabbage/{i}.jpg") for i in range(1, 10)],
"brokul": [pygame.image.load(f"warzywa/Broccoli/{i}.jpg") for i in range(1, 10)]
} }
# 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 # Typy warzyw przypisane do liczb
self.vegetable_types = { self.vegetable_types = {
"pomidor": 1, "marchewka": 2,
"ogorek": 2, "ziemniak": 3,
"kalafior": 3 "pomidor": 4,
"fasola": 5,
"dynia": 6,
"rzodkiewka": 7,
"ogorek": 8,
"kalafior": 9,
"kapusta": 10,
"brokul": 11
} }
# Metoda do generowania początkowej planszy # Metoda do generowania początkowej planszy
def generate_board(self): def generate_board(self):
self.board = [[random.choice([0, 1, 2, 3]) for _ in range(cols)] for _ in range(rows)] # Zwiększenie prawdopodobieństwa generowania trawy i kamieni
self.board = [[random.choice([0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) for _ in range(cols)] for _ in range(rows)]
self.vegetables = [[None 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)] self.vegetable_names = [[None for _ in range(cols)] for _ in range(rows)]
# Losowe przypisanie warzyw do planszy # Losowe przypisanie warzyw do planszy
for row in range(rows): for row in range(rows):
for col in range(cols): for col in range(cols):
if self.board[row][col] in (1, 2, 3): if self.board[row][col] in self.vegetable_types.values():
vegetable_type = list(self.warzywa_images.keys())[self.board[row][col] - 1] vegetable_type = list(self.warzywa_images.keys())[self.board[row][col] - 2]
vegetable_image = random.choice(self.warzywa_images[vegetable_type]) vegetable_image = random.choice(self.warzywa_images[vegetable_type])
self.vegetables[row][col] = vegetable_image self.vegetables[row][col] = vegetable_image
self.vegetable_names[row][col] = vegetable_type self.vegetable_names[row][col] = vegetable_type
@ -98,9 +110,9 @@ class Board:
for row in range(rows): for row in range(rows):
for col in range(cols): for col in range(cols):
if random.random() < mutation_rate: if random.random() < mutation_rate:
self.board[row][col] = random.choice([0, 1, 2, 3]) self.board[row][col] = random.choice([0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
if self.board[row][col] in (1, 2, 3): if self.board[row][col] in self.vegetable_types.values():
vegetable_type = list(self.warzywa_images.keys())[self.board[row][col] - 1] vegetable_type = list(self.warzywa_images.keys())[self.board[row][col] - 2]
vegetable_image = random.choice(self.warzywa_images[vegetable_type]) vegetable_image = random.choice(self.warzywa_images[vegetable_type])
self.vegetables[row][col] = vegetable_image self.vegetables[row][col] = vegetable_image
self.vegetable_names[row][col] = vegetable_type self.vegetable_names[row][col] = vegetable_type
@ -112,10 +124,8 @@ class Board:
for j in range(cols): for j in range(cols):
if i * cols + j > crossover_point: 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.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], other_board.vegetables[i][j] = other_board.vegetables[i][j], self.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]
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ę # Metoda kopiująca planszę
def copy(self): def copy(self):
@ -128,7 +138,7 @@ class Board:
# Sprawdza, czy dane pole zawiera warzywo # Sprawdza, czy dane pole zawiera warzywo
def is_vegetable(self, row, col): def is_vegetable(self, row, col):
return self.board[row][col] in (1, 2, 3) return self.board[row][col] in self.vegetable_types.values()
# Rysowanie planszy na oknie pygame # Rysowanie planszy na oknie pygame
def draw_cubes(self, win): def draw_cubes(self, win):
@ -137,64 +147,68 @@ class Board:
cube_rect = pygame.Rect(col * size, row * size, size, size) cube_rect = pygame.Rect(col * size, row * size, size, size)
cube = self.board[row][col] cube = self.board[row][col]
if cube == 0: if cube == 0:
win.blit(self.grass, cube_rect) win.blit(self.grass, cube_rect) # Użyj obrazu trawy
elif cube == 1:
rock_scale = pygame.transform.scale(self.rock, (size, size))
win.blit(self.dirt, cube_rect)
win.blit(rock_scale, cube_rect)
else: else:
if self.vegetables[row][col]: if self.vegetables[row][col]:
vegetable_image = pygame.transform.scale(self.vegetables[row][col], (size, size)) vegetable_image = pygame.transform.scale(self.vegetables[row][col], (size, size))
win.blit(vegetable_image, cube_rect) win.blit(vegetable_image, cube_rect)
# Funkcja oceniająca planszę (wywołuje metodę evaluate) # Funkcja oceniająca planszę (wywołuje metodę evaluate)
def evaluate(board): def evaluate(board):
return board.evaluate() return board.evaluate()
# Generowanie początkowej populacji plansz # Generowanie początkowej populacji plansz
def generate_population(size): def generate_population(size):
return [Board() for _ in range(size)] return [Board() for _ in range(size)]
# Selekcja metodą ruletki # Selekcja metodą ruletki
def roulette_wheel_selection(population, fitnesses): def roulette_wheel_selection(population, fitnesses):
total_fitness = sum(fitnesses) total_fitness = sum(fitnesses)
selection_probs = [f / total_fitness for f in fitnesses] selection_probs = [f / total_fitness for f in fitnesses]
return population[random.choices(range(len(population)), weights=selection_probs, k=1)[0]] return population[random.choices(range(len(population)), weights=selection_probs, k=1)[0]]
# Krzyżowanie jednopunktowe # Krzyżowanie jednopunktowe
def crossover(parent1, parent2): def crossover(parent1, parent2):
child1, child2 = parent1.copy(), parent2.copy() child1, child2 = parent1.copy(), parent2.copy()
child1.crossover(child2) child1.crossover(child2)
return child1, child2 return child1, child2
# Mutacja planszy # Mutacja planszy
def mutate(board, mutation_rate): def mutate(board, mutation_rate):
board.mutate(mutation_rate) board.mutate(mutation_rate)
# Algorytm genetyczny # Algorytm genetyczny
def genetic_algorithm(pop_size, generations, mutation_rate): def genetic_algorithm(pop_size, generations, mutation_rate):
population = generate_population(pop_size) # Generowanie początkowej populacji population = generate_population(pop_size)
for _ in range(generations): for generation in range(generations):
fitnesses = [evaluate(board) for board in population] # Ocenianie każdej planszy fitnesses = [evaluate(board) for board in population]
new_population = [] new_population = [max(population, key=evaluate).copy()] # Elityzm - zachowanie najlepszego osobnika
while len(new_population) < pop_size: while len(new_population) < pop_size:
parent1 = roulette_wheel_selection(population, fitnesses) # Wybór rodzica 1 metodą ruletki parent1 = roulette_wheel_selection(population, fitnesses)
parent2 = roulette_wheel_selection(population, fitnesses) # Wybór rodzica 2 metodą ruletki parent2 = roulette_wheel_selection(population, fitnesses)
offspring1, offspring2 = crossover(parent1, parent2) # Krzyżowanie rodziców offspring1, offspring2 = crossover(parent1, parent2)
mutate(offspring1, mutation_rate) # Mutacja potomka 1 mutate(offspring1, mutation_rate)
mutate(offspring2, mutation_rate) # Mutacja potomka 2 mutate(offspring2, mutation_rate)
new_population.extend([offspring1, offspring2]) # Dodanie potomków do nowej populacji new_population.extend([offspring1, offspring2])
population = new_population # Zamiana starej populacji na nową population = new_population[:pop_size]
best_board = max(population, key=evaluate) # Wybór najlepszej planszy z populacji print(f"Generation {generation}: Best Fitness = {max(fitnesses)}")
best_board = max(population, key=evaluate)
return best_board return best_board
# Funkcja do zapisywania planszy jako obraz PNG
def save_board_as_image(board, filename):
surface = pygame.Surface((cols * size, rows * size))
board.draw_cubes(surface)
pygame.image.save(surface, filename)
# Parametry algorytmu # Parametry algorytmu
pop_size = 50 # Rozmiar populacji pop_size = 50 # Rozmiar populacji
generations = 200 # Liczba generacji generations = 300 # Liczba generacji
mutation_rate = 0.05 # Wskaźnik mutacji mutation_rate = 0.03 # Wskaźnik mutacji
# Inicjalizacja Pygame # Inicjalizacja Pygame
pygame.init() pygame.init()
@ -210,12 +224,21 @@ pygame.display.update()
# Zapisywanie planszy do pliku # Zapisywanie planszy do pliku
np.save('generated_board.npy', best_board.board) np.save('generated_board.npy', best_board.board)
save_board_as_image(best_board, 'generated_board.png') # Zapisz planszę jako obraz PNG
# Utrzymanie okna otwartego do zamknięcia przez użytkownika # Utrzymanie okna otwartego do zamknięcia przez użytkownika
run = True run = True
needs_redraw = True # Flaga informująca, czy trzeba przerysować planszę
while run: while run:
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
run = False run = False
elif event.type == pygame.MOUSEBUTTONDOWN or event.type == pygame.KEYDOWN:
needs_redraw = True # Przerysowanie planszy w przypadku kliknięcia myszą lub naciśnięcia klawisza
if needs_redraw:
best_board.draw_cubes(win)
pygame.display.flip()
needs_redraw = False # Wyłącz przerysowywanie do momentu kolejnego zdarzenia
pygame.quit() pygame.quit()

Binary file not shown.

BIN
generated_board.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 KiB