using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace Zelvaci { public enum prikaz { FORWARD, PEN, LEFT, RIGHT, COLOR, REPEAT, IF, DEFINE }; public struct pair { public prikaz typ; public List parameters; }; public partial class Zelvaci : Form { Image result; InteractiveViewForm iv; Dictionary functions = new Dictionary(); public Zelvaci() { DocumentationForm d = new DocumentationForm(); d.ShowDialog(); InitializeComponent(); } /// /// Naparsuje vstup do seznamu příkazů které poté vykreslí pomocí další metody draw /// /// private List parse(string input) { int readed = 0; // počet přečtených znaků ze vstupu int start = 0; // index prvního znaku nového příkazu List prog = new List(); while (readed < input.Length) { if (input[readed] == '}') readed++; start = readed; while (readed < input.Length && input[readed] != ')') { readed++; } if (readed == input.Length) break; int end = readed; // konec příkazu bez parametrů while(input[end] != '(') end--; pair next = new pair(); string name = input.Substring(start, end-start); string funcname = ""; if(name.Length > 6 && name.Substring(0, 6) == "define") { funcname = name.Substring(6); StringBuilder sb = new StringBuilder(input); sb[start+6] = 'ř'; input = sb.ToString(); name = "define"; } next.typ = (prikaz)Enum.Parse(typeof(prikaz), name.ToUpper()); next.parameters = new List(); // načteme parametry do seznamu int i = end + 1; while(i < input.Length && input[i] != ')') { int lastEnd = i; while (i < input.Length && input[i] != ')' && input[i] != ',') { i++; } next.parameters.Add(int.Parse(input.Substring(lastEnd, i-(lastEnd)))); if (input[i] == ',') i++; } if (next.typ == prikaz.IF || next.typ == prikaz.REPEAT || next.typ == prikaz.DEFINE) // blokové příkazy { int startBlock = i + 1; // index znaku se složenou závorkou (otevírací) i = startBlock; int slozene = 0; while (i < input.Length) { if(input[i] == '{') slozene++; else if(input[i] == '}') slozene--; if(slozene == 0) break; i++; } int endBlock = i-1; if (next.typ == prikaz.IF) { if (next.parameters[0] > 0) { List subprog = parse(input.Substring(startBlock+1, endBlock - startBlock)); foreach (pair p in subprog) prog.Add(p); readed = endBlock; } else { readed = endBlock; } readed++; } else if (next.typ == prikaz.REPEAT) { if (next.parameters[0] > 0) { List subprog = parse(input.Substring(startBlock + 1, endBlock - startBlock)); for (int j = 0; j < next.parameters[0]; j++) { foreach (pair p in subprog) { prog.Add(p); } } } readed = endBlock+1; } else if(next.typ == prikaz.DEFINE) { functions.Add(funcname + "()", input.Substring(startBlock + 1, endBlock - startBlock)); readed = endBlock - 1; } } else { prog.Add(next); } readed++; foreach(KeyValuePair kv in functions) { input = input.Replace(kv.Key, kv.Value); } } return prog; } /// /// Vykreslí program do obrázku /// /// public void draw(List prog) { result = (Image)new Bitmap(700, 700); Graphics g = Graphics.FromImage(result); g.FillRectangle(Brushes.White, 0, 0, 700, 700); // výchozí parametry Color c = Color.Black; float x = 350, y = 350; // pozice želvy int rotation = -90; int pen = 0; int stepsDone = 0; int maxSteps = 0; if (tbSteps.Text.Length == 0 || int.Parse(tbSteps.Text) == 0) { int pppp = 0; foreach (pair p in prog) { switch (p.typ) { case prikaz.FORWARD: if (pppp > 0) { maxSteps++; } break; case prikaz.PEN: pppp = p.parameters[0]; break; } } } else { maxSteps = int.Parse(tbSteps.Text); } foreach(pair p in prog) { switch (p.typ) { case prikaz.FORWARD: float endX = x + p.parameters[0] * (float)Math.Cos(rotation * (Math.PI / 180)); float endY = y + p.parameters[0] * (float)Math.Sin(rotation * (Math.PI / 180)); if (pen > 0) { float startX = x; float startY = y; stepsDone++; g.DrawLine(new Pen(c, pen), new PointF(startX, startY), new PointF(endX, endY)); } x = endX; y = endY; break; case prikaz.LEFT: rotation -= p.parameters[0]; break; case prikaz.RIGHT: rotation += p.parameters[0]; break; case prikaz.PEN: pen = p.parameters[0]; break; case prikaz.COLOR: int r, gg, b; r = Math.Max(0, Math.Min(255, p.parameters[0])); gg = Math.Max(0, Math.Min(255, p.parameters[1])); b = Math.Max(0, Math.Min(255, p.parameters[2])); c = Color.FromArgb(r, gg, b); break; } if (stepsDone == maxSteps) break; } result.Save(tbOutput.Text); MessageBox.Show("Soubor byl uložen."); } /// /// Rutina pro spojení řádků a odstranění bílých mezer /// /// /// private void button1_Click(object sender, EventArgs e) { string path = tbInput.Text; string[] prog = File.ReadAllLines(path); string input = String.Join("", prog); input = input.Replace(" ", ""); List lp = parse(input); draw(lp); } /// /// Dialog pro otevření souboru /// /// /// private void button2_Click(object sender, EventArgs e) { if (openFile.ShowDialog() == DialogResult.OK) { tbInput.Text = openFile.FileName; } } /// /// Dialog pro uložení souboru /// /// /// private void button3_Click(object sender, EventArgs e) { if (saveFile.ShowDialog() == DialogResult.OK) { tbOutput.Text = saveFile.FileName; } } /// /// Zobrazení interaktivního režimu /// /// /// private void button4_Click(object sender, EventArgs e) { iv = new InteractiveViewForm(); string path = tbInput.Text; string[] prog = File.ReadAllLines(path); string input = String.Join("", prog); input = input.Replace(" ", ""); iv.prog = parse(input); iv.Show(); } } }