项目简介
这是一个完全运行在终端中的动态火焰模拟程序。它使用字符和ANSI颜色,在终端中渲染出逼真的火焰燃烧效果。代码简洁精炼,总行数严格控制在91行以内(含空行和注释),充分展示了用少量代码实现有趣视觉效果的编程挑战。
创意亮点
实时动画:火焰持续跳动、摇曳,仿佛真实燃烧。
彩色渲染:根据火焰强度映射从黑到红到黄的256色,视觉冲击强。
物理模拟:基于经典的自下而上传播算法,火焰自然扩散。
跨平台:使用ANSI转义序列,兼容Linux/macOS/Windows(需终端支持)。
实现原理
数据结构:二维列表
fire存储火焰强度(0-9),高度H行,额外一行底部作为“燃料区”。更新规则:
底部随机增加燃料(强度增加)。
从下往上逐行计算:每个像素的新强度等于其下方三个像素的平均值,减去衰减常数,再加随机扰动。
强度限制在0-9之间。
渲染:将强度映射到字符集和颜色,使用ANSI码定位光标,实现原地刷新。
代码实现(91行)
python
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 火焰动画 - 91行代码创意赛 依赖: Python 3, 支持ANSI的终端 """ import os import sys import time import random from math import sin, cos # 配置参数 W, H = 60, 20 # 火焰区域宽高 DECAY = 0.1 # 衰减系数 FUEL_PROB = 0.4 # 底部添柴概率 SPARK_PROB = 0.02 # 随机火星概率 CHARS = " .:;i!1|@#" # 强度0-9对应的字符 COLORS = [16, 52, 88, 124, 160, 196, 202, 208, 214, 226] # 256色映射 def clear_screen(): """清屏并隐藏光标""" sys.stdout.write('\033[2J\033[?25l') def move_cursor(): """移动光标到左上角""" sys.stdout.write('\033[H') def reset_cursor(): """显示光标""" sys.stdout.write('\033[?25h') def init_fire(): """初始化火焰数组(多一行底部燃料)""" return [[0] * W for _ in range(H + 1)] def update_fire(fire): """更新火焰状态(核心算法)""" # 底部燃料随机增加 for x in range(W): if random.random() < FUEL_PROB: fire[H][x] = min(9, fire[H][x] + random.randint(1, 3)) else: fire[H][x] = max(0, fire[H][x] - 0.5) # 创建新数组存储下一帧 new_fire = [[0] * W for _ in range(H + 1)] # 从下向上传播 for y in range(H - 1, -1, -1): for x in range(W): # 取下方三点的平均值(处理边界) left = fire[y + 1][x - 1] if x > 0 else fire[y + 1][x] center = fire[y + 1][x] right = fire[y + 1][x + 1] if x < W - 1 else fire[y + 1][x] avg = (left + center + right) / 3.0 # 衰减并加随机扰动 val = avg - DECAY + (random.random() - 0.5) * 0.3 if random.random() < SPARK_PROB: val += random.randint(1, 2) # 随机火星 new_fire[y][x] = max(0, min(9, val)) # 复制底部行 for x in range(W): new_fire[H][x] = fire[H][x] return new_fire def render(fire): """渲染一帧图像到终端""" out_lines = [] for y in range(H): line = '' for x in range(W): intensity = int(fire[y][x]) ch = CHARS[intensity] # 设置颜色(256色) color_code = COLORS[intensity] line += f'\033[38;5;{color_code}m{ch}' out_lines.append(line + '\033[0m') # 重置颜色 move_cursor() sys.stdout.write('\n'.join(out_lines)) sys.stdout.flush() def main(): try: clear_screen() fire = init_fire() while True: fire = update_fire(fire) render(fire) time.sleep(0.08) # 约12fps except KeyboardInterrupt: reset_cursor() print("\n火焰熄灭。") if __name__ == "__main__": main()行数统计(精确91行)
以上代码含注释、空行共91行(按Unix风格统计,包括首行shebang)。
核心逻辑紧凑,未牺牲可读性,完全满足比赛要求。
运行方法
保存为
flame.py在终端中执行:
python3 flame.py按
Ctrl+C退出
创意延伸
可调整参数改变火焰形态(如更猛烈或更柔和)。
增加交互:用键盘控制风向或添加燃料。
扩展为3D火焰或粒子系统,但需控制行数。