Python 生命游戏-覆盖当前一代而不是更新到下一代
下面我添加了我的生活游戏代码。规则定义正确,运行平稳。然而,这个游戏并不像想象的那样有效。它没有更新到下一代,但似乎正在覆盖当前一代。举个例子:三个水平点应该在下一代变成三个垂直点,但这并没有发生 解决方案: 我有两代人,现在和下一代。它必须将规则应用于当前一代,并在下一代中进行更新。然后,它必须一次性用下一代覆盖当前一代,而不是逐个单元。我怎样才能解决这个问题Python 生命游戏-覆盖当前一代而不是更新到下一代,python,pygame,iteration,python-3.7,conways-game-of-life,Python,Pygame,Iteration,Python 3.7,Conways Game Of Life,下面我添加了我的生活游戏代码。规则定义正确,运行平稳。然而,这个游戏并不像想象的那样有效。它没有更新到下一代,但似乎正在覆盖当前一代。举个例子:三个水平点应该在下一代变成三个垂直点,但这并没有发生 解决方案: 我有两代人,现在和下一代。它必须将规则应用于当前一代,并在下一代中进行更新。然后,它必须一次性用下一代覆盖当前一代,而不是逐个单元。我怎样才能解决这个问题 import tkinter as tk import itertools, os, platform, pygame, random
import tkinter as tk
import itertools, os, platform, pygame, random
# Defining the grid dimensions.
GRID_SIZE = WIDTH, HEIGHT = 750, 1000
# Defining the cell size and the number of cells in the X and Y direction.
CELL_SIZE = 10
X_CELLS = int(WIDTH/CELL_SIZE)
Y_CELLS = int(HEIGHT/CELL_SIZE)
# Defining the number and color for dead and living cells.
COLOR_DEAD = 0
COLOR_ALIVE = 1
colors = []
colors.append((0, 0, 0)) # Black
colors.append((0, 128, 128)) # blue
# Defining two lists: current generation and next generation.
current_generation = [[COLOR_DEAD for y in range(Y_CELLS)] for x in range(X_CELLS)]
next_generation = [[COLOR_DEAD for y in range(Y_CELLS)] for x in range(X_CELLS)]
# Defining the max frames per second/speed of the game.
FPS_MAX = 10
class GameOfLife:
"""
describe what the method does.
"""
def __init__(self):
# Initializing the interpreter and creating a root window and title.
self.root = tk.Tk()
self.root.title("Game of Life - Created by - Have fun")
# Defining the main frame, left-side frame and right-side frame.
self.frame = tk.Frame(self.root , width=1000, height=1000, highlightbackground='red')
self.menu = tk.Frame(self.frame, width=250, height=1000, highlightbackground='#595959', highlightthickness=10)
self.game_border = tk.Frame(self.frame, width=750, height=1000, highlightbackground='green', highlightthickness=10)
# Packing the windows.
self.frame.pack()
self.frame.pack_propagate(0)
self.menu.pack(side="left")
self.menu.pack_propagate(0)
self.game_border.pack()
# Defining the buttons.
self.button_start = tk.Button(self.menu, text="Start", height=5, width=20, fg="black", activeforeground="red", background="grey80", activebackground="grey80", command=self.start_button)
self.button_stop = tk.Button(self.menu, text="Stop", height=5, width=20, fg="black", activeforeground="red", background="grey80", activebackground="grey80", command=self.stop_button)
self.button_iteration = tk.Button(self.menu, text="Next iteration", height=5, width=20, fg="black", activeforeground="red", background="grey80", activebackground="grey80", command=self.create_next_gen)
self.button_random = tk.Button(self.menu, text="Random", height=5, width=20, fg="black", activeforeground="red", background="grey80", activebackground="grey80", command=self.random_grid)
self.button_reset = tk.Button(self.menu, text="Reset", height=5, width=20, fg="black", activeforeground="red", background="grey80", activebackground="grey80", command=self.reset_button)
self.button_quit = tk.Button(self.menu, text="Quit", height=5, width=20, fg="black", activeforeground="red", background="grey80", activebackground="grey80", command=self.quit_button)
# Packing the buttons.
self.button_start.pack()
self.button_stop.pack()
self.button_iteration.pack()
self.button_random.pack()
self.button_reset.pack()
self.button_quit.pack()
# Placing the buttons.
self.button_start.place(x=40, y=50)
self.button_stop.place(x=40, y=200)
self.button_iteration.place(x=40, y=350)
self.button_random.place(x=40, y=500)
self.button_reset.place(x=40, y=650)
self.button_quit.place(x=40, y=800)
# Defining the slider.
self.slider_random = tk.Scale(self.menu, from_=0, to=100, orient="horizontal", command=self.slider_value)
self.slider_random.set(50)
# Packing the slider.
self.slider_random.pack()
# Placing the slider.
self.slider_random.place(x=62, y=590)
# Defining a dropdown menu for the form and color.
"""
self.options_figures = [
"circles",
"squares",
"surprise"
]
self.var_figure = tk.StringVar(self.root)
self.dropdown_figure = tk.OptionMenu(self.menu, self.var_figure,
self.options_figures[0], self.options_figures[1],
self.options_figures[2])
self.var_figure.set(self.options_figures[0])
#self.var_color.trace("w", FUNCTIONNAME)
self.dropdown_figure.pack()
# Dropdown menu for the cell color
self.options_colors = [
"blue",
"red",
"white",
"green",
"yellow",
"purple",
"grey",
"pink"
]
self.var_color = tk.StringVar(self.root)
self.dropdown_colors = tk.OptionMenu(self.menu, self.var_color,
self.options_colors[0], self.options_colors[1],
self.options_colors[2], self.options_colors[3],
self.options_colors[4], self.options_colors[5],
self.options_colors[6], self.options_colors[7])
self.var_color.set(self.options_colors[0])
#self.var_color.trace("w", FUNCTION NAME)
self.dropdown_colors.pack()
"""
# Defining the labels that count the dead and living cells.
"""
self.label_alive = tk.Label(self.menu, text="Living cells:"+" 1000", height=5, width=20, fg="black", background="grey80")
self.label_dead = tk.Label(self.menu, text="Dead cells"+" 1000", height=1, width=20, fg="black", background="grey80")
Packing the labels
self.label_alive.pack()
self.label_dead.pack()
self.label_alive.place(x=40, y=900)
self.label_alive.place(x=40, y=900)
"""
# This embeds the pygame window in the tkinter frame.
os.environ['SDL_WINDOWID'] = str(self.game_border.winfo_id())
system = platform.system()
if system == "Windows":
os.environ['SDL_VIDEODRIVER'] = 'windib'
elif system == "Linux":
os.environ['SDL_VIDEODRIVER'] = 'x11'
# Initializing pygame.
pygame.init()
self.screen = pygame.display.set_mode(GRID_SIZE)
# Initializing the generations.
self.init_gen(current_generation, COLOR_DEAD)
# Defining a clock to set the FPS.
self.fps_clock = pygame.time.Clock()
# Setting variables for later use.
self.next_iteration = False
self.game_over = False
# Get the slider value to change the % of randomness.
def slider_value(self, value):
self.value = value
# Button functions.
def start_button(self):
self.next_iteration = True
def stop_button(self):
self.next_iteration = False
def reset_button(self):
self.next_iteration = False
self.init_gen(next_generation, COLOR_DEAD)
def quit_button(self):
self.game_over = True
# Initializing all the cells.
def init_gen(self, generation, c):
for y in range(Y_CELLS):
for x in range(X_CELLS):
generation[x][y] = c
# Creates a random grid based on the slider value.
def random_grid(self):
self.next_iteration = False
self.init_gen(next_generation, COLOR_DEAD)
self.percentage_zero = list(itertools.repeat(0,
(100 - self.slider_random.get())))
self.percentage_one = list(itertools.repeat(1,
(self.slider_random.get())))
# print(self.percentage_zero)
# print(self.percentage_one)
for row in range(X_CELLS):
for col in range(Y_CELLS):
next_generation[row][col] = random.choice(self.percentage_zero + self.percentage_one)
# print(next_generation[row][col])
# Drawing the cells, color black or blue at location (x,y).
def draw_cell(self, x, y, c):
pos = (int(x * CELL_SIZE + CELL_SIZE / 2),
int(y * CELL_SIZE + CELL_SIZE / 2))
# pygame.draw.rect(screen, colors[c], pygame.Rect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE-1, CELL_SIZE-1))
# pygame.draw.circle(screen, colors[c], pos, CELL_SIZE, CELL_SIZE) #Weird form, can also be used instead of rectangles
pygame.draw.circle(self.screen, colors[c], pos, 5, 0)
# Updating the cells in the current generation.
def update_gen(self):
global current_generation
for y in range(Y_CELLS):
for x in range(X_CELLS):
c = next_generation[x][y]
self.draw_cell(x, y, c)
current_generation = list(next_generation)
# Activate a living cell.
def activate_living_cell(self, x, y):
global next_generation
next_generation[x][y] = COLOR_ALIVE
# Deactivate a living cell.
def deactivate_living_cell(self, x, y):
global next_generation
next_generation[x][y] = COLOR_DEAD
# Function to check neighbor cells.
def check_cells(self, x, y):
# Check the edges.
if (x < 0) or (y < 0):
return 0
if (x >= X_CELLS) or (y >= Y_CELLS):
return 0
if current_generation[x][y] == COLOR_ALIVE:
return 1
else:
return 0
def check_cell_neighbors(self, row_index, col_index):
# Get the number of alive cells surrounding the current cell.
num_alive_neighbors = 0
num_alive_neighbors += self.check_cells(row_index - 1, col_index - 1)
num_alive_neighbors += self.check_cells(row_index - 1, col_index)
num_alive_neighbors += self.check_cells(row_index - 1, col_index + 1)
num_alive_neighbors += self.check_cells(row_index, col_index - 1)
num_alive_neighbors += self.check_cells(row_index, col_index + 1)
num_alive_neighbors += self.check_cells(row_index + 1, col_index - 1)
num_alive_neighbors += self.check_cells(row_index + 1, col_index)
num_alive_neighbors += self.check_cells(row_index + 1, col_index + 1)
return num_alive_neighbors
# Rules:
# 1 Any live cell with fewer than two live neighbors dies, as if by underpopulation.
# 2 Any live cell with two or three live neighbors lives on to the next generation.
# 3 Any live cell with more than three live neighbors dies, as if by overpopulation.
# 4 Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
def create_next_gen(self):
for y in range(Y_CELLS):
for x in range(X_CELLS):
n = self.check_cell_neighbors(x, y) # Number of neighbors.
c = current_generation[x][y] # Current cell (either dead or alive).
if c == COLOR_ALIVE:
if (n < 2): # Rule number 1.
next_generation[x][y] = COLOR_DEAD
elif (n > 3): # Rule number 3.
next_generation[x][y] = COLOR_DEAD
else: # Rule number 2.
next_generation[x][y] = COLOR_ALIVE
elif c == COLOR_DEAD:
if (n == 3): # Rule number 4.
next_generation[x][y] = COLOR_ALIVE
else:
next_generation[x][y] = COLOR_DEAD
#Problem: first counting, then next iteration.
# Defines button and mouse clicks.
def handle_events(self):
for event in pygame.event.get():
# Turns the mouse position into a position in the grid.
posn = pygame.mouse.get_pos()
x = int(posn[0] / CELL_SIZE)
y = int(posn[1] / CELL_SIZE)
# Pressing quit --> quit the game.
if event.type == pygame.QUIT:
self.game_over = True
# Pressing the left mouse button to activate or deactivate a cell.
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if next_generation[x][y] == COLOR_DEAD:
self.activate_living_cell(x, y)
else:
self.deactivate_living_cell(x, y)
# Keeping the right mouse button pressed activates drawing mode.
if event.type == pygame.MOUSEMOTION and event.buttons[2]:
self.activate_living_cell(x, y)
# Define the keyboard key presses for q, space, a, s, r.
if event.type == pygame.KEYDOWN:
# Quit the game.
if event.unicode == 'q':
self.game_over = True
print("q")
# Next iteration - manually.
elif event.key == pygame.K_SPACE:
self.create_next_gen()
print("keypress")
# Next iteration - automated.
elif event.unicode == 'a': # a to automate the iterations.
self.next_iteration = True
print("a")
# Stop the automated iterations.
elif event.unicode == 's':
self.next_iteration = False
print("s")
# Empty the grid.
elif event.unicode == 'r':
self.next_iteration = False
self.init_gen(next_generation, COLOR_DEAD)
print("r")
# Runs the game loop
def run(self):
while not self.game_over:
self.handle_events()
if self.next_iteration:
self.create_next_gen()
self.update_gen()
pygame.display.flip()
self.fps_clock.tick(FPS_MAX)
self.root.update()
if __name__ == "__main__":
GAME = GameOfLife()
GAME.run()
将tkinter作为tk导入
导入itertools、操作系统、平台、pygame、随机
#定义栅格尺寸。
网格尺寸=宽度,高度=7501000
#定义X和Y方向上的单元大小和单元数。
单元大小=10
X_单元=int(宽度/单元大小)
Y_单元=int(高度/单元大小)
#定义死细胞和活细胞的数量和颜色。
颜色=0
颜色=1
颜色=[]
颜色。附加((0,0,0))#黑色
颜色。附加((0,128,128))#蓝色
#定义两个列表:当前一代和下一代。
当前_生成=[[COLOR_DEAD for y in range(y_单元格)]for x in range(x_单元格)]
下一代=[[COLOR\u DEAD for y in range(y\u CELLS)]for x in range(x\u CELLS)]
#定义游戏的最大每秒帧数/速度。
FPS_MAX=10
生命的类别:
"""
描述该方法的作用。
"""
定义初始化(自):
#初始化解释器并创建根窗口和标题。
self.root=tk.tk()
self.root.title(“生命的游戏-创造-享受乐趣”)
#定义主框架、左侧框架和右侧框架。
self.frame=tk.frame(self.root,宽度=1000,高度=1000,highlightbackground='red')
self.menu=tk.Frame(self.Frame,宽度=250,高度=1000,highlightbackground='#595959',highlightthickness=10)
self.game_border=tk.Frame(self.Frame,宽度=750,高度=1000,highlightbackground='green',highlightthickness=10)
#收拾窗户。
self.frame.pack()
self.frame.pack_传播(0)
self.menu.pack(side=“left”)
self.menu.pack_传播(0)
self.game_border.pack()
#定义按钮。
self.button\u start=tk.button(self.menu,text=“start”,height=5,width=20,fg=“black”,activeforeground=“red”,background=“grey80”,activebackground=“grey80”,command=self.start\u按钮)
self.button\u stop=tk.button(self.menu,text=“stop”,height=5,width=20,fg=“black”,activeforeground=“red”,background=“grey80”,activebackground=“grey80”,command=self.stop\u按钮)
self.button\u iteration=tk.button(self.menu,text=“Next iteration”,height=5,width=20,fg=“black”,activefront=“red”,background=“grey80”,activebackground=“grey80”,command=self.create\u Next\u gen)
self.button\u random=tk.button(self.menu,text=“random”,height=5,width=20,fg=“black”,activeforeground=“red”,background=“grey80”,activebackground=“grey80”,command=self.random\u grid)
self.button_reset=tk.button(self.menu,text=“reset”,height=5,width=20,fg=“black”,activefront=“red”,background=“grey80”,activebackground=“grey80”,command=self.reset_按钮)
self.button\u quit=tk.button(self.menu,text=“quit”,height=5,width=20,fg=“black”,activeforeground=“red”,background=“grey80”,activebackground=“grey80”,command=self.quit\u按钮)
#包装好钮扣。
self.button_start.pack()
self.button\u stop.pack()
self.button_iteration.pack()
self.button_random.pack()
self.button_reset.pack()
self.button_quit.pack()
#放置按钮。
自启动按钮位置(x=40,y=50)
自停按钮位置(x=40,y=200)
self.button_迭代位置(x=40,y=350)
自身按钮随机放置(x=40,y=500)
自复位按钮位置(x=40,y=650)
自我按钮退出位置(x=40,y=800)
#定义滑块。
self.slider\u random=tk.Scale(self.menu,从0到100,orient=“horizontal”,command=self.slider\u值)
自滑动随机设置(50)
#包装滑块。
self.slider_random.pack()
#放置滑块。
自滑动随机位置(x=62,y=590)
#定义窗体和颜色的下拉菜单。
"""
self.options\u数字=[
“圆圈”,
“广场”,
“惊喜”
]
self.var\u figure=tk.StringVar(self.root)
self.dropdown\u figure=tk.OptionMenu(self.menu,self.var\u figure,
self.options\u图[0],self.options\u图[1],
self.options_图[2])
self.var\u figure.set(self.options\u figures[0])
#self.var\u color.trace(“w”,函数名)
self.dropdown_figure.pack()
#单元格颜色的下拉菜单
self.options\u颜色=[
“蓝色”,
“红色”,
“白色”,
“绿色”,
“黄色”,
“紫色”,
“灰色”,
“粉红”
]
self.var_color=tk.StringVar(self.root)
self.dropdown\u colors=tk.OptionMenu(self.menu,self.var\u color,
self.options\u colors[0],self.options\u colors[1],
self.options_colors[2],self.options_colors[3],
self.options_colors[4],self.options_colors[5],
self.options\u colors[6],self.options\u colors[7])
self.var\u color.set(self.options\u colors[0])
#self.var_color.trace(“w”,函数名)
self.dropdown_colors.pack()
"""
#定义计数的标签
current_generation = list(next_generation)
class GameOfLife:
# [...]
# Updating the cells in the current generation.
def update_gen(self):
global current_generation
for y in range(Y_CELLS):
for x in range(X_CELLS):
c = next_generation[x][y]
self.draw_cell(x, y, c)
current_generation[x][y] = next_generation[x][y] # assign element by element
while not self.game_over:
self.handle_events() # change "next_generation" by click
if self.next_iteration:
self.create_next_gen() # compute "next_generation" from "current_generation"
self.update_gen() # copy "current_generation" from "next_generation"