# L-System：規則換字長出一棵樹

正式網址：https://newmediaart.course.monolab.world/snippets/lsystem-grow

一個 grow(axiom, rules, n) 函式，把起始字串照規則改寫 n 代（F 換成 F[+F]F[-F]F）再交給畫字串函式，字串越長樹越茂密，點一下多長一代。

- **分類**：自然的演算法
- **行數**：47 行（p5.js 1.x／2.x）
- **在哪一堂用到**：[第 3 堂](https://newmediaart.course.monolab.world/lesson/03)

把 grow() 和 drawString() 複製進自己的 sketch，在 setup() 用 grow(起始字, 規則, 代數) 算好字串，draw() 裡 translate() 到出發點再 drawString()；改 RULES 就是改樹的長相。

```js
// L-System：每一代把字串裡的 F 換成規則，再用海龜畫出來。點一下多長一代
const RULES = { F: 'F[+F]F[-F]F' };
let gen = 3;
let sentence;

function setup() {
  createCanvas(640, 420);
  sentence = grow('F', RULES, gen);
}

function draw() {
  background(18, 25, 40);
  stroke(135, 218, 160);
  strokeWeight(1.5);
  translate(width / 2, height - 20); // 從畫面底部中間長出來
  rotate(-HALF_PI); // 朝上
  drawString(sentence, 60 / pow(2, gen), 25); // 每多一代，步長減半
}

function mousePressed() {
  gen = gen % 4 + 1; // 1 到 4 代輪流
  sentence = grow('F', RULES, gen);
}

// 長 n 代：每一代都讀舊字串、寫進新字串（不能邊讀邊改自己）
function grow(axiom, rules, n) {
  let s = axiom;
  for (let i = 0; i < n; i++) {
    let next = '';
    for (let c of s) next += rules[c] || c; // 有規則就換，沒有就原樣留下
    s = next;
  }
  return s;
}

// 照字串畫（跟 turtle-draw 的 turtle 是同一套，兩段一起用只要留一份）
function drawString(cmds, len, angle) {
  for (let c of cmds) {
    if (c === 'F') {
      line(0, 0, len, 0);
      translate(len, 0);
    } else if (c === '+') rotate(radians(angle));
    else if (c === '-') rotate(-radians(angle));
    else if (c === '[') push();
    else if (c === ']') pop();
  }
}
```

## 同類常用指令・自然的演算法

- [海龜繪圖：照字串畫線](https://newmediaart.course.monolab.world/snippets/turtle-draw)
- [遞迴樹：branch 自己呼叫自己](https://newmediaart.course.monolab.world/snippets/recursive-branch)
- [Noise 年輪：接得起來的不規則圈](https://newmediaart.course.monolab.world/snippets/noise-ring)
- [Boid 三條規則：分離、對齊、聚合](https://newmediaart.course.monolab.world/snippets/boid-rules)

[回到全部常用指令](https://newmediaart.course.monolab.world/snippets)

[到 Hahow 報名](https://hahow.in/cr/creative-code)。價格與優惠以 Hahow 頁面為準。
