康威生命游戏 - 少儿编程项目
下面是一个使用Python在VSCode中开发的康威生命游戏项目。这个项目通过简单的规则模拟细胞的演化过程,非常适合少儿理解细胞自动机和复杂系统的概念。
项目代码
创建一个名为game_of_life.py的新文件,然后复制以下代码:
# 康威生命游戏 - 少儿编程项目
# 规则:
# 1. 活细胞周围有2-3个活细胞时,继续存活
# 2. 死细胞周围恰好有3个活细胞时,复活
# 3. 其他情况下,细胞死亡或保持死亡
import numpy as np
import pygame
import sys
import time
import random
# 初始化pygame
pygame.init()
# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (128, 128, 128)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 120, 255)
class GameOfLife:
def __init__(self, width=800, height=600, cell_size=10):
# 屏幕尺寸和细胞大小
self.width = width
self.height = height
self.cell_size = cell_size
# 计算网格尺寸
self.cols = width // cell_size
self.rows = height // cell_size
# 创建屏幕
self.screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("康威生命游戏 - 按空格键暂停/继续")
# 初始化网格(随机状态)
self.grid = np.zeros((self.rows, self.cols))
self.initialize_random()
# 游戏状态
self.running = True
self.paused = False
self.generation = 0
self.population = np.sum(self.grid)
# 字体
self.font = pygame.font.SysFont('simhei', 16)
self.title_font = pygame.font.SysFont('simhei', 24)
# 预定义图案
self.patterns = {
"滑翔机": self.create_glider,
"脉冲星": self.create_pulsar,
"高斯帕滑翔机枪": self.create_glider_gun,
"方块": self.create_block,
"飞船": self.create_spaceship
}
def initialize_random(self, density=0.2):
"""随机初始化网格"""
self.grid = np.random.choice([0, 1], size=(self.rows, self.cols), p=[1-density, density])
def create_glider(self, x, y):
"""创建滑翔机图案"""
pattern = np.array([
[0, 1, 0],
[0, 0, 1],
[1, 1, 1]
])
self.place_pattern(x, y, pattern)
def create_pulsar(self, x, y):
"""创建脉冲星图案"""
pattern = np.zeros((15, 15))
# 定义脉冲星的三个臂
arms = [
(2, 0), (3, 0), (4, 0),
(0, 2), (0, 3), (0, 4),
(5, 2), (5, 3), (5, 4),
(2, 5), (3, 5), (4, 5)
]
# 创建四个对称的部分
for dx, dy in arms:
pattern[dy, dx] = 1
pattern[dy, 14-dx] = 1
pattern[14-dy, dx] = 1
pattern[14-dy, 14-dx] = 1
self.place_pattern(x, y, pattern)
def create_glider_gun(self, x, y):
"""创建高斯帕滑翔机枪图案(简化版)"""
pattern = np.zeros((9, 36))
# 高斯帕滑翔机枪的简化版本
gun_coords = [
(1, 5), (1, 6), (2, 5), (2, 6),
(11, 5), (11, 6), (11, 7), (12, 4), (12, 8), (13, 3), (13, 9),
(14, 3), (14, 9), (15, 6), (16, 4), (16, 8), (17, 5), (17, 6),
(17, 7), (18, 6), (21, 3), (21, 4), (21, 5), (22, 3), (22, 4),
(22, 5), (23, 2), (23, 6), (25, 1), (25, 2), (25, 6), (25, 7)
]
for dy, dx in gun_coords:
pattern[dy, dx] = 1
self.place_pattern(x, y, pattern)
def create_block(self, x, y):
"""创建方块图案"""
pattern = np.array([
[1, 1],
[1, 1]
])
self.place_pattern(x, y, pattern)
def create_spaceship(self, x, y):
"""创建飞船图案"""
pattern = np.array([
[0, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[0, 0, 0, 0, 1],
[1, 0, 0, 1, 0]
])
self.place_pattern(x, y, pattern)
def place_pattern(self, x, y, pattern):
"""在指定位置放置图案"""
h, w = pattern.shape
for i in range(h):
for j in range(w):
if 0 <= y+i < self.rows and 0 <= x+j < self.cols:
self.grid[y+i, x+j] = pattern[i, j]
def count_neighbors(self, grid, x, y):
"""计算细胞周围的活细胞数量"""
# 使用numpy的切片操作计算邻居数量
# 考虑边界条件(使用模运算实现环形边界)
total = np.sum(grid[(y-1)%self.rows:(y+2)%self.rows, (x-1)%self.cols:(x+2)%self.cols])
# 减去中心细胞自身
return total - grid[y, x]
def update(self):
"""更新网格状态"""
if self.paused:
return
# 创建邻居计数网格
neighbors = np.zeros((self.rows, self.cols))
for y in range(self.rows):
for x in range(self.cols):
neighbors[y, x] = self.count_neighbors(self.grid, x, y)
# 应用生命游戏规则
# 活细胞规则:2-3个邻居存活
survive = (self.grid == 1) & ((neighbors == 2) | (neighbors == 3))
# 死细胞规则:恰好3个邻居复活
born = (self.grid == 0) & (neighbors == 3)
# 更新网格
self.grid = np.where(survive | born, 1, 0)
# 更新统计信息
self.generation += 1
self.population = np.sum(self.grid)
def draw(self):
"""绘制网格和界面"""
# 清空屏幕
self.screen.fill(BLACK)
# 绘制网格线
for x in range(0, self.width, self.cell_size):
pygame.draw.line(self.screen, GRAY, (x, 0), (x, self.height), 1)
for y in range(0, self.height, self.cell_size):
pygame.draw.line(self.screen, GRAY, (0, y), (self.width, y), 1)
# 绘制活细胞
for y in range(self.rows):
for x in range(self.cols):
if self.grid[y, x] == 1:
rect = pygame.Rect(x*self.cell_size, y*self.cell_size,
self.cell_size, self.cell_size)
pygame.draw.rect(self.screen, GREEN, rect)
# 绘制信息面板
self.draw_info_panel()
# 更新显示
pygame.display.flip()
def draw_info_panel(self):
"""绘制信息面板"""
# 半透明背景
info_bg = pygame.Surface((self.width, 60))
info_bg.set_alpha(180)
info_bg.fill(BLACK)
self.screen.blit(info_bg, (0, 0))
# 标题
title = self.title_font.render("康威生命游戏", True, WHITE)
self.screen.blit(title, (10, 10))
# 统计信息
stats = [
f"代数: {self.generation}",
f"种群: {int(self.population)}",
f"状态: {'运行中' if not self.paused else '已暂停'}"
]
for i, text in enumerate(stats):
rendered = self.font.render(text, True, WHITE)
self.screen.blit(rendered, (10, 40 + i*20))
# 控制说明
controls = [
"空格键: 暂停/继续",
"R键: 随机初始化",
"C键: 清空网格",
"1-5键: 放置预设图案",
"鼠标点击: 切换细胞状态"
]
for i, text in enumerate(controls):
rendered = self.font.render(text, True, BLUE)
self.screen.blit(rendered, (self.width - 200, 10 + i*20))
def handle_events(self):
"""处理用户输入事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
self.paused = not self.paused
elif event.key == pygame.K_r:
self.initialize_random()
self.generation = 0
elif event.key == pygame.K_c:
self.grid = np.zeros((self.rows, self.cols))
self.generation = 0
elif event.key in [pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_4, pygame.K_5]:
# 放置预设图案
pattern_idx = event.key - pygame.K_1
pattern_names = list(self.patterns.keys())
if pattern_idx < len(pattern_names):
pattern_name = pattern_names[pattern_idx]
pattern_func = self.patterns[pattern_name]
# 清空网格并放置图案在中央
self.grid = np.zeros((self.rows, self.cols))
center_x = self.cols // 2
center_y = self.rows // 2
pattern_func(center_x, center_y)
self.generation = 0
print(f"已放置图案: {pattern_name}")
elif event.type == pygame.MOUSEBUTTONDOWN:
# 鼠标点击切换细胞状态
if event.button == 1: # 左键
x, y = pygame.mouse.get_pos()
grid_x = x // self.cell_size
grid_y = y // self.cell_size
if 0 <= grid_x < self.cols and 0 <= grid_y < self.rows:
self.grid[grid_y, grid_x] = 1 - self.grid[grid_y, grid_x]
def run(self):
"""运行游戏主循环"""
clock = pygame.time.Clock()
print("康威生命游戏已启动!")
print("规则说明:")
print("1. 活细胞周围有2-3个活细胞时,继续存活")
print("2. 死细胞周围恰好有3个活细胞时,复活")
print("3. 其他情况下,细胞死亡或保持死亡")
print("\n控制说明:")
print("空格键: 暂停/继续")
print("R键: 随机初始化")
print("C键: 清空网格")
print("1-5键: 放置预设图案")
print("鼠标点击: 切换细胞状态")
while self.running:
self.handle_events()
self.update()
self.draw()
clock.tick(10) # 控制更新速度
pygame.quit()
sys.exit()
# 主程序
if __name__ == "__main__":
# 创建并运行游戏
game = GameOfLife(width=800, height=600, cell_size=10)
game.run()
安装必要的库
在运行项目前,需要安装Pygame和NumPy库。在VSCode的终端中运行以下命令:
pip install pygame numpy
如何在VSCode中运行
- 打开VSCode
- 创建一个新文件,命名为
game_of_life.py - 将上面的代码复制到文件中
- 保存文件
- 点击右上角的"运行"按钮(三角形图标)或按F5键运行程序
项目扩展建议
对于想要进一步挑战的学生,可以考虑以下扩展功能:
- 更多预设图案:添加更多有趣的细胞图案,如蜜蜂巢、反应扩散系统等
- 图案库:创建一个图案库,允许用户保存和加载自定义图案
- 速度控制:添加滑块或按键来控制模拟速度
- 统计图表:显示种群数量随时间变化的图表
- 规则自定义:允许用户自定义生命游戏的规则(如S/B规则)
- 颜色主题:添加多种颜色主题选择
- 缩放功能:实现网格的缩放和平移功能
教学要点
- 细胞自动机概念:解释什么是细胞自动机及其在计算机科学中的应用
- 康威生命游戏规则:详细讲解三条基本规则及其背后的逻辑
- 复杂系统:讨论简单规则如何产生复杂行为
- 网格计算:介绍如何使用二维数组表示和操作网格
- 邻居计算:解释如何高效计算每个细胞的邻居状态
- 可视化编程:展示如何将数据可视化并与用户交互
简化版(无Pygame依赖)
如果不想安装Pygame,可以使用以下基于终端的简化版本:
# 康威生命游戏 - 终端版本
import numpy as np
import time
import os
class SimpleGameOfLife:
def __init__(self, rows=20, cols=40):
self.rows = rows
self.cols = cols
self.grid = np.zeros((rows, cols))
self.initialize_random(0.2)
self.generation = 0
def initialize_random(self, density=0.2):
"""随机初始化网格"""
self.grid = np.random.choice([0, 1], size=(self.rows, self.cols), p=[1-density, density])
def count_neighbors(self, x, y):
"""计算细胞周围的活细胞数量"""
total = 0
for i in range(-1, 2):
for j in range(-1, 2):
if i == 0 and j == 0:
continue
nx, ny = (x + j) % self.cols, (y + i) % self.rows
total += self.grid[ny, nx]
return total
def update(self):
"""更新网格状态"""
new_grid = np.copy(self.grid)
for y in range(self.rows):
for x in range(self.cols):
neighbors = self.count_neighbors(x, y)
# 应用生命游戏规则
if self.grid[y, x] == 1: # 活细胞
if neighbors < 2 or neighbors > 3:
new_grid[y, x] = 0 # 死亡
else: # 死细胞
if neighbors == 3:
new_grid[y, x] = 1 # 复活
self.grid = new_grid
self.generation += 1
def display(self):
"""在终端显示网格"""
os.system('cls' if os.name == 'nt' else 'clear') # 清屏
print(f"康威生命游戏 - 第 {self.generation} 代")
print("=" * (self.cols + 2))
for y in range(self.rows):
line = "|"
for x in range(self.cols):
if self.grid[y, x] == 1:
line += "●" # 活细胞
else:
line += " " # 死细胞
line += "|"
print(line)
print("=" * (self.cols + 2))
print("按 Ctrl+C 停止")
def run(self, delay=0.5):
"""运行游戏"""
try:
while True:
self.display()
self.update()
time.sleep(delay)
except KeyboardInterrupt:
print("\n游戏结束!")
# 运行简化版
if __name__ == "__main__":
game = SimpleGameOfLife(rows=20, cols=40)
game.run(delay=0.3)
这个项目结合了数学、计算机科学和生物学概念,通过简单的规则展示了复杂系统的演化,非常适合培养少儿的逻辑思维和编程能力。

5523

被折叠的 条评论
为什么被折叠?



