100 baris penerjemah logo mini JS murni – Beragampengetahuan
Logo adalah bahasa pemrograman yang dirancang pada tahun 1960an. Fiturnya yang paling terkenal adalah grafik penyu: pemrogram mengontrol “kura-kura” (kursor) dengan instruksi berikut maju, kiri, benar, mengulang Kura-kura meninggalkan “jejak” di layar.
Hari ini kita akan membuat penerjemah logo file tunggal yang ringkas dalam sekitar 100 baris JavaScript murni. Agar kodenya tetap singkat, kami hanya akan menerapkan empat instruksi di atas, plus siklus warna (Bukan bagian dari logo standar) Berputar melalui 36 warna HSV.
Klik tombol “Jalankan” di bawah untuk melihatnya beraksi!
Contents
penyu logo mini
Ulangi 60 [ color_cycle forward 200 right 91 ]
Memesan: forward N, left N, right N, repeat N [ ... ], color_cycle
Ringkasan
Penerjemah terdiri dari tiga bagian utama: tokenizer Bagi input menjadi token, a pengurai Bangun AST sederhana, dan Pelaksana Itu melintasi AST dan menggunakan status penyu untuk menggambar di kanvas HTML5. ini siklus warna Petunjuknya menyempurnakan warna pena melalui 36 rona dengan jarak yang sama pada roda warna HSV.
File dan pengaturan
Yang Anda butuhkan hanyalah file HTML. File ini berisi kontrol UI, kanvas, dan semua JavaScript. Simpan file dan buka di browser modern apa pun.
- kanvas untuk menggambar.
- bidang teks Untuk program logo.
- tombol Jalankan, hapus, dan setel ulang.
Komponen utama dijelaskan
tokenizer
Tokenizer menormalkan tanda kurung siku dan membagi input berdasarkan spasi. Ini menurunkan huruf kecil token sehingga perintahnya tidak peka huruf besar-kecil. Tanda kurung disimpan sebagai token terpisah sehingga parser dapat mendeteksi blok duplikat.
// Example tokenizer snippet
function tokenize(input)
input = input.replace(/\[/g, ' [ ').replace(/\]/g, ' ] ');
const raw = input.trim().split(/\s+/).filter(Boolean);
return raw.map(t => t.toLowerCase());
pengurai
Parser membaca token dan membangun node: forward, left, right, repeat memiliki tubuh bersarang, dan color_cycle. Ini mendukung pengulangan bersarang dengan menggunakan rekursi parseBlock Fungsi.
// Parser returns an array of nodes
// Node examples:
// type: 'forward', value: 100
// type: 'repeat', count: 4, body: [...]
// type: 'color_cycle'
Status eksekutor dan penyu
Pelaksana melintasi AST dan memperbarui status penyu: X, kamuDan sudut. satu forward Menarik garis dari posisi sekarang ke posisi baru yang dihitung menggunakan trigonometri. left Dan right Ubah sudutnya. repeat Jalankan tubuhnya beberapa kali.
pohon sintaksis abstrak
satu pohon sintaksis abstrak atau aminotransferase aspartat adalah representasi memori terstruktur dari program yang Anda tulis. Penerjemah tidak menggunakan teks mentah atau markup, namun mengubah program menjadi pohon node, di mana setiap node mewakili perintah atau konstruksi yang bermakna. AST adalah apa yang digunakan pelaksana untuk melakukan tindakan.
Mengapa menggunakan AST
- jernih — AST secara eksplisit mengungkapkan struktur program (perintah, parameter, blok bersarang), sehingga tahapan selanjutnya tidak perlu mengurai ulang teks.
- memeriksa — Parser dapat memeriksa struktur yang salah sebelum dieksekusi dan menghasilkan kesalahan yang berguna.
- Optimalkan dan perluas — Bila Anda memiliki representasi terstruktur, Anda dapat dengan mudah menambahkan perintah, transformasi, atau prosedur analisis baru.
- men-debug — Anda dapat memeriksa AST untuk melihat bagaimana parser menafsirkan program Anda.
Contoh AST
Untuk program ini:
repeat 4 [ color_cycle forward 150 right 90 ]
Parser menghasilkan AST yang mirip dengan JSON ini:
[
"type": "repeat",
"count": 4,
"body": [
"type": "color_cycle" ,
"type": "forward", "value": 150 ,
"type": "right", "value": 90
]
]
Bagaimana pelaksana menggunakan AST
Pelaksana melakukan traversal sederhana terhadap AST. Untuk setiap simpul:
- Periksa jenis simpul (mis.
forwardataurepeat). - Lakukan tindakan yang sesuai (gerakan kura-kura, ubah sudut, ubah warna).
- Jika node memiliki prinsipal bersarang (mis.
repeat), pelaksana secara rekursif melintasi tubuh sebanyak beberapa kali.
function execNodes(nodes)
for (const node of nodes)
if (node.type === 'forward') ...
else if (node.type === 'repeat')
for (let k = 0; k < node.count; k++) execNodes(node.body);
// other node types...
// Forward example
const rad = degToRad(turtle.angle);
const nx = turtle.x + Math.cos(rad) * dist;
const ny = turtle.y + Math.sin(rad) * dist;
ctx.beginPath();
ctx.moveTo(turtle.x, turtle.y);
ctx.lineTo(nx, ny);
ctx.stroke();
turtle.x = nx; turtle.y = ny;
siklus warna
Lingkaran warna menghitung terlebih dahulu 36 string RGB dengan mengambil sampel nilai rona secara seragam dari 0 hingga 360 derajat dan mengonversi HSV ke RGB. setiap color_cycle Node meningkatkan indeks dan pembaruan ctx.strokeStyle. tempat color_cycle Sebelum forward Warnai bagian tersebut dengan salah satu warna berikut.
// colorIndex advances and updates strokeStyle
colorIndex = (colorIndex + 1) % colors.length;
turtle.strokeStyle = colors[colorIndex];
ctx.strokeStyle = turtle.strokeStyle;
Contoh lengkap
Di bawah ini adalah file HTML lengkap yang dapat dijalankan. Ini termasuk UI, tokenizer, parser, eksekutor, konversi HSV dan color_cycle Petunjuk Pengoperasian.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Mini Logo Turtle with color_cycle Tutorial</title>
<style>
body font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial; display:flex; gap:16px; padding:16px;
#controls width:360px;
textarea width:100%; height:240px; font-family: monospace;
canvas border:1px solid #ccc; background:#fff;
button margin-top:8px; padding:8px 12px;
</style>
</head>
<body>
<div id="controls">
<h3>Mini Logo Turtle</h3>
<textarea id="program">
repeat 36 [ color_cycle forward 200 right 170 ]
</textarea>
<div>
<button id="run">Run</button>
<button id="clear">Clear</button>
<button id="reset">Reset Turtle</button>
</div>
<p><strong>Commands:</strong> <code>forward N</code>, <code>left N</code>, <code>right N</code>, <code>repeat N [ ... ]</code>, <code>color_cycle</code></p>
</div>
<canvas id="c" width="700" height="700"></canvas>
<script>
// Canvas setup
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
const W = canvas.width, H = canvas.height;
// Turtle state
let turtle = x: W/2, y: H/2, angle: 0, pen: true, strokeStyle: '#000', lineWidth: 1.5 ;
// Color cycle
const COLOR_STEPS = 36;
let colorIndex = 0;
const colors = generateHSVColors(COLOR_STEPS);
function generateHSVColors(steps)
const arr = [];
for (let i = 0; i < steps; i++)
const h = (i / steps) * 360;
const rgb = hsvToRgb(h, 1, 1);
arr.push(`rgb($rgb.r,$rgb.g,$rgb.b)`);
return arr;
function hsvToRgb(h, s, v)
const c = v * s;
const hp = h / 60;
const x = c * (1 - Math.abs((hp % 2) - 1));
let r1=0,g1=0,b1=0;
if (0 <= hp && hp < 1) r1=c; g1=x; b1=0;
else if (1 <= hp && hp < 2) r1=x; g1=c; b1=0;
else if (2 <= hp && hp < 3) r1=0; g1=c; b1=x;
else if (3 <= hp && hp < 4) r1=0; g1=x; b1=c;
else if (4 <= hp && hp < 5) r1=x; g1=0; b1=c;
else if (5 <= hp && hp < 6) r1=c; g1=0; b1=x;
const m = v - c;
return r: Math.round((r1 + m) * 255), g: Math.round((g1 + m) * 255), b: Math.round((b1 + m) * 255) ;
// Reset
function resetTurtle()
turtle.x = W/2; turtle.y = H/2; turtle.angle = 0; turtle.pen = true;
turtle.strokeStyle="#000"; turtle.lineWidth = 1.5;
colorIndex = 0;
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0,0,W,H);
ctx.lineWidth = turtle.lineWidth;
ctx.strokeStyle = turtle.strokeStyle;
ctx.fillStyle="#000";
ctx.beginPath(); ctx.arc(turtle.x, turtle.y, 2, 0, Math.PI*2); ctx.fill();
resetTurtle();
// Tokenizer
function tokenize(input)
input = input.replace(/\[/g, ' [ ').replace(/\]/g, ' ] ');
const raw = input.trim().split(/\s+/).filter(Boolean);
return raw.map(t => t.toLowerCase());
// Parser
function parseTokens(tokens) {
let i = 0;
function parseBlock()
const nodes = [];
while (i < tokens.length) tok === 'rt')
const val = tokens[i++]; nodes.push(type:'right', value: Number(val)); continue;
if (tok === 'repeat')
const count = Number(tokens[i++]); const next = tokens[i++];
if (next !== '[') throw new Error("Expected '[' after repeat count");
const body = parseBlock();
nodes.push(type:'repeat', count: count, body: body);
continue;
if (tok === 'color_cycle')
nodes.push(type:'color_cycle'); continue;
if (tok.startsWith(';')) continue;
throw new Error('Unknown token: ' + tok);
return nodes;
return parseBlock();
}
// Executor
function degToRad(d) return d * Math.PI / 180;
function execNodes(nodes)
for (const node of nodes)
if (node.type === 'forward')
const dist = node.value;
const rad = degToRad(turtle.angle);
const nx = turtle.x + Math.cos(rad) * dist;
const ny = turtle.y + Math.sin(rad) * dist;
if (turtle.pen)
ctx.beginPath(); ctx.moveTo(turtle.x, turtle.y); ctx.lineTo(nx, ny); ctx.stroke();
turtle.x = nx; turtle.y = ny;
else if (node.type === 'left')
turtle.angle -= node.value;
else if (node.type === 'right')
turtle.angle += node.value;
else if (node.type === 'repeat')
for (let k = 0; k < node.count; k++) execNodes(node.body);
else if (node.type === 'color_cycle')
colorIndex = (colorIndex + 1) % colors.length;
turtle.strokeStyle = colors[colorIndex];
ctx.strokeStyle = turtle.strokeStyle;
else
throw new Error('Unknown node type: ' + node.type);
// UI wiring
document.getElementById('run').addEventListener('click', () =>
try
ctx.lineWidth = turtle.lineWidth;
ctx.strokeStyle = turtle.strokeStyle;
const program = document.getElementById('program').value;
const tokens = tokenize(program);
const ast = parseTokens(tokens);
execNodes(ast);
catch (err)
alert('Error: ' + err.message);
);
document.getElementById('clear').addEventListener('click', () => ctx.clearRect(0,0,W,H));
document.getElementById('reset').addEventListener('click', resetTurtle);
</script>
</body>
</html>
Tip dan Ekstensi
- Coba loop bersarang:
repeat 18 [ repeat 40 [ color_cycle forward 100 right 170 ] right 60 ]
- kontrol pena Tambahkan ke
penupDanpendownBergerak tanpa menggambar. - Parameter warna mengizinkan
color_cycle NMaju N langkah maju atau tambahkansetcolor H S VSiapkan HSV apa pun. - kartun Gunakan stepper async untuk menggantikan pelaksana langsung
requestAnimationFrameMenganimasikan gerakan kura-kura. - laporan kesalahan Peningkatan kesalahan parser menggunakan indeks token dan nomor baris untuk memudahkan proses debug.
Tutorial JS lainnya:
Balok berputar – efek visual (baris 25)
Kembang api (baris 60)
Mesin fisika untuk pemula
Mesin Fisika – Kotak Pasir Interaktif
Mesin fisika adalah alat yang bodoh
Langit berbintang (baris 21)
Putaran Yin dan Yang (4 lingkaran dan 20 garis)
Editor peta ubin (70 baris)
Rol sinus (30 baris)
Sprite animasi interaktif
Efek transisi gambar (baris 16)

rencana pengembangan website
metode pengembangan website
jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website
#baris #penerjemah #logo #mini #murni