tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
0
ZUGRIFFE
429
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
  1. #1
    SteffenBoerner SteffenBoerner ist offline Mitglied
    Registriert seit
    Aug 2004
    Beiträge
    24
    So, dann hier doch noch meine Version in JavaScript. (Danke Alexander)
    zu erkklären gibts nicht viel - Im Prinzip die gleiche herangehensweise wie bei der C#-Variante.

    Hier der Code:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    
    var svgNS = "http://www.w3.org/2000/svg";
    var msg = "";
    // fügt Replacement-Zeile im Eingabeformular hinzu
    function AddReplacement(){
        var rpl_table = document.getElementById("replacements");
        var lineCount = rpl_table.getElementsByTagName("tr").length;
        
        // die erste Tabellenzeile kopieren ... 
        var rpl_line = rpl_table.getElementsByTagName("tr")[0].cloneNode(true);
        // ... Attribute ändern ..
        var rpl_cells = rpl_line.getElementsByTagName("input");
        for(var i = 0; i < rpl_cells.length; i++)
        {
            rpl_cells[i].id = rpl_cells[i].name + "_" + (lineCount + 1);
        }
        // ... und am Ende der Tabelle einfügen
        rpl_table.appendChild(rpl_line);
    }
    // entfernt alle ChildNodes eines Elements aus dem DOM-Baum
    function ClearNode(node){
        for(var i = 0; i < node.childNodes.length; i++)
        {
            var Child = node.childNodes[i];
            node.removeChild(Child);
        }
    }
    // Berechnet und erstellt die erfordelichen polyline-Knoten
    // und fügt diese als Childs in den svg-Knoten im DOM-Baum ein
    function Berechnen(){
        // Knoten für die svg-Ausgabe über Id holen ...
        var svg_node = document.getElementById("drawing");
        // ... und alten Inhalt entfernen
        ClearNode(svg_node);
     
        svg_node.setAttributeNS(null, "width", 0);
        svg_node.setAttributeNS(null, "height", 0);
        
        // die polylines berechnen
        var multilines = CalcMultiLines();
     
        // Attribute für Breite und Höhe der Zeichenflöche einfügen
        svg_node.setAttributeNS(null, "width", Width);
        svg_node.setAttributeNS(null, "height", Height);
        
        // Polyline-Knoten erstellen und einfügen
        for(var i = 0; i < multilines.length; i++)
        {
            // für jede Multiline wird ein neuer polyline-Eintrag im svg-Knoten eingefügt
            lineString = GetMultiLineString(multilines[i]);
            var childNode = document.createElementNS(svgNS, "polyline");
            childNode.setAttributeNS(null, "points", lineString);
            svg_node.appendChild(childNode);
        }
    }
    // berechnet aus dem multiline-Array den String, wie er im polyline-Knoten benötigt wird
    function GetMultiLineString(multiline){
        var list = "";
        var PointList = multiline[0];
        
        for(var i = 0; i < PointList.length; i++)
        {
            var Point = AdaptPoint(PointList[i]);
            list += String(" " + Point[0]) + " " + String(Point[1] + ",");
        }
        
        // erstes Leerzeichen und letztes Komma werden noch entfernt
        return list.substring(1, list.length - 1);
    }
    // nur zu Debug-Zwecken 
    function GetFullMultiLineString(multiline){
        var list = "Direction:" + multiline[1] + ";";
        var PointList = multiline[0];
        
        for(var i = 0; i < PointList.length; i++)
        {
            var Point = AdaptPoint(PointList[i]);
            list += String(" " + Point[0]) + " " + String(Point[1] + ",");
        }
        
        // erstes Leerzeichen und letztes Komma werden noch entfernt
        return list.substring(0, list.length - 1);
    }
    // Umrechnen der Punkt-Koordinaten --> Berechnung karthesisches Koordinatensystem
    // Darstellung: Ursprung oben rechts
    function AdaptPoint(point){
        return new Array(point[0], Height - point[1]);
    }
    // Nur zu Debug-Zwecken (2x)
    function ShowNodeContent(node){
        var inhalt = GetNodeContent(node);
        alert(inhalt);
    }
    function GetNodeContent(node){
        var i;
        var result = "<" + node.nodeName + " ";
        // Attribute ausgeben
        for(i = 0; i < node.attributes.length; i++)
        {
            var attr = node.attributes[i];
            result += attr.nodeName + '="' + attr.nodeValue + '" ';
        }
        result += ">\n";
        
        // Childs ausgeben
        for(i = 0; i < node.childNodes.length; i++)
        {
            var child = node.childNodes[i];
            if(child.nodeValue == null)
                result += GetNodeContent(child);
            else
                result += child.nodeValue;
            result += "\n";
        }
        result += "</" + node.nodeName + ">\n";
        return result;
    }
     
    // Replacements ist ein Array von Replacements
    // jedes Replacement ist ein Array mit zwei Feldern: [0] Key, der Schlüssel-String; [1] ein Array von Einzel-Replacements für diesen Schlüssel
    // jedes Einzel-Replacement ist ein Array von zwei Werten: [0] Chance, die Wahrscheinlichkeit für die Auswahl; [1] der eigentliche Ersetzungsstring
     
    // liest Ersetzungen aus den Eingabefeldern des Formulars
    function GetReplacements(){
        var Replacements = new Array();
        var Keys=document.getElementsByName("key");
        for(var i = 0; i < Keys.length; i++)
        {
            var Key = document.getElementById("key_" + (i + 1)).value;
            if(Key == "")
                Key = 'F';
            var Chance = parseInt(document.getElementById("chance_" + (i + 1)).value);
            if(isNaN(Chance))
                Chance = 1;
            var Val = document.getElementById("rValue_" + (i + 1)).value;
            if((Val == null) || (Val.length == 0))
                continue;
        
            var Replacement;
            if(ContainsKey(Replacements, Key))
                Replacement = GetEntry(Replacements, Key)
            else
                Replacement = new Array(Key, new Array());
            Replacement[1].push(new Array(Chance, Val));
     
            Replacements.push(Replacement);
        }
        
        return Replacements;
    }
    // Ausführen der Ersetzungen (rekursiv)
    function ApplyReplacements(actionList, replacements, iteration){
        var List = actionList;
        // Ende der Itration erreicht --> zurück
        if(iteration == 0)
            return List;
     
        var result = "";
        for(var i = 0; i < List.length; i++)
        {
            var key = List[i];
            if(ContainsKey(replacements, key))
            {
                var Entry = GetEntry(replacements, key);
                result += GetReplacement(Entry);
            }
            else
                result += key;
        }
        
        // rekursiver Aufruf, Iterationsstufe um 1 verringert --> bei '0' = ENDE
        return ApplyReplacements(result, replacements, iteration - 1);
    }
    // die beiden folgenden Funktionen realisieren eine Art Wörterbuch (oder Map)
    // list ist ein Array von zweispaltigen Arrays, von denen index '0' der Key und index '1' der zugehörige Entry/Value ist.
    function ContainsKey(list, key){
        for(var i = 0; i < list.length; i++)
            if(list[i][0]==key)
                return true;
        return false;
    }
    function GetEntry(list, key){
        for(var i = 0; i < list.length; i++)
            if(list[i][0] == key)
                return list[i];
        return null;
    }
    // bestimmt bei bedarf die zu übergebende Ersetzung anhand der Wahrscheinlichkeitswerte (sofern vorhanden
    // gibt eine Ersetzung zuück
    function GetReplacement(replacement){
        var Key = replacement[0];
        var replList = replacement[1];
        
        // Sonderfall: nur eine Ersetzung vorhanden: --> wahrscheinlichkeit ist 1.0
        if(replList.length == 1)
        {
            return replList[0][1];
        }
     
        // bei mehreren Ersetzungen zufälligen Wert nach Wahrscheinlichkeit berechnen
        var Values = new Array();
        // jeder Wert wird [Wahrscheinlichkeit]-mal in eine Liste geschrieben
        // danach wird mittels einer Zufallszahl ein Wert dieser Liste ausgewählt und zurückgegeben
        for(var i = 0; i < replList.length; i++)
        {
            var repl = replList[i];
            // repl[0] ist die Wahrscheinlichkeit, repl[1] der Wert
            for(var j = 0; j < repl[0]; j++)
                Values.push(repl[1]);
        }
        var Index = 0;
        Index = Math.random() * Values.length;
        // jetzt ist Index vom Typ float, zur Indecieerung des Array wird jedoch ein integer benötigt
        // deshalb der folgende Umweg über den String --- Sch... Laufzeittypisierung bei JavaScript
        Index=parseInt(Index);
        return Values[Index];
    }
     
    // die Ausmasse der Zeichenfläche - global weil an verschiedenen Stellen benötigt
    var Width;
    var Height;
    // Berechnet alle MultiLines auf Grundlage der Eingabeparameter
    // jede Multiline ist ein Array mit genau zwei Werten: [0] ein Array von Punkten, [1] die aktuelle Blickrichtung der Schildkröte
    // Jeder Punkt ist ein Array aus genau zwei Float-Werten: [0] X-Koordinate  [1] Y-Koordinate
    function CalcMultiLines(){
        // Werte aus den Eingabefeldern
        Width = parseInt(document.getElementById("width").value);
        Height = parseInt(document.getElementById("height").value);
        var StartX = parseFloat(document.getElementById("startX").value);
        var StartY = parseFloat(document.getElementById("startY").value);
        var StepWidth = parseFloat(document.getElementById("length").value);
        var RotationAngle = parseFloat(document.getElementById("angle").value);
        var ActionList = document.getElementById("action").value;
        var Iterations = parseInt(document.getElementById("iteration").value);
        var Replacements = GetReplacements();
        
        // der Rückgabewert
        // hier sind alle Multilines verpackt, also ein Array von Multilines
        // jede Multiline ist ein Array mit genau zwei Werten: [0] ein Array von Punkten, [1] die aktuelle Blickrichtung der Schildkröte
        // Jeder Punkt ist ein Array aus genau zwei Float-Werten: [0] X-Koordinate  [1] Y-Koordinate
        var MultiLines = new Array();
        
        // Werte für die Berechnung
        var currentMultiLine;                   // die MultiLine, die gerade gezeichnet wird
        var TotalActionList = "";               // ActionList mit ausgeführten Ersetzungen
     
        // die erste Multiline beginnt mit dem Startpunkt, die Startrichtung ist 0.0
        currentMultiLine = new Array(2);
        var PointList = new Array();
        PointList.push(new Array(StartX, StartY));
        currentMultiLine[0] = PointList;
        currentMultiLine[1] = 0.0;
        MultiLines.push(currentMultiLine);
     
        // den Stack für die Push- / Pop-Funktionen initialisieren
        // der Stack ist ein Array von integer-Zahlen
        // jeder eintrag repräsentiert den Indes der gemerken Multiline im Multilines-Array
        var Stack = new Array();
        var currentIndex = 0;                   // der Index der Multiline, die aktuell bearbeitet wird
     
        // Actionlist mit Replacements auflösen
        if(Replacements.length > 0)
            TotalActionList = ApplyReplacements(ActionList, Replacements, Iterations);
        else
            TotalActionList = ActionList;
        
        // jetzt werden die einzelnen Aktionen ausgeführt
        for(var i = 0; i < TotalActionList.length; i++)
        {
            var action = TotalActionList[i];
            switch(action)
            {
                case 'F': DrawLine(currentMultiLine, StepWidth); break;
                case '+': RotatePlus(currentMultiLine, RotationAngle); break;
                case '-': RotateMinus(currentMultiLine, RotationAngle); break;
                case '[':
                    currentIndex = Push(MultiLines, currentMultiLine, Stack, currentIndex);
                    currentMultiLine = MultiLines[currentIndex];
                    break;
                case ']':
                    currentIndex = Pop(MultiLines, currentMultiLine, Stack);
                    currentMultiLine = MultiLines[currentIndex];
                    break;
            }
        }
        
        return MultiLines;
    }
     
    // berechnet einen neuen Punkt der MultiLine in abhängigkeit von aktuellem Blickwinkel und Schrittweite
    // und fügt diesen zur Multiline hinzu
    function DrawLine(multiLine, StepWidth){
        var PointList = multiLine[0];
        var StartPoint = PointList[PointList.length - 1];
        var Direction = multiLine[1] * Math.PI / 180;
        
        var dX = StepWidth * Math.cos(Direction);
        var dY = StepWidth * Math.sin(Direction);
        
        multiLine[0].push(new Array(StartPoint[0] + dX, StartPoint[1] + dY));
    }
    // die beiden Funktionen zur Änderung der Blickrichtung der Schildkröte
    function RotatePlus(multiLine, Angle){
        multiLine[1] += Angle;
    }
    function RotateMinus(multiLine, Angle){
        multiLine[1] -= Angle;
    }
    // die aktuelle Multiline wird auf Stack gemerkt und eine neue Multiline begonnen und in die Gesamt-Liste eingefügt
    function Push(lines, currentLine, stack, index){
        var newLine = new Array(2);
        // Anfangs-Blickrichtung der neuen Linie ist aktuelle Blichrichtung der derzeitig aktuellen Linie
        newLine[1] = currentLine[1];
        // die Punkteliste für die neue Linie
        newLine[0] = new Array();
        // Startpunkt der neuen Linie ist der letzte Punkt der derzeitigen Linie
        newLine[0].push(currentLine[0][currentLine[0].length - 1]);
        
        // neue Linie in Liste
        lines.push(newLine);
        // mit neuer Linie weiter
        currentLine = newLine;
        // alten Index auf Stack
        stack.push(index);
        // neuer Index ist der der zuletzt eingefügten Linie
        index = lines.length - 1;
     
        return index;
    }
    // der zuletzt gemerkte Index wird vom Stack geholt;
    // die zu diesem Index gehörige Linie wird zurückgegeben
    function Pop(lines, currentLine, stack){
        var idx = stack.pop();
        currentLine = lines[idx];
     
        return idx;
    }
     
    /* Nur Für DEBUG
    function Log(text){
        var Textfeld = document.getElementById("log");
        Textfeld.value += text + "\n";
    }
    function ClearLog(){
        var Textfeld = document.getElementById("log");
        Textfeld.value = "";
    }
    */

    Die zugehörige Xhtml-Seite findet ihr im Anhang.

    Gruß Steffen
    Angehängte Dateien Angehängte Dateien
     

Thema nicht erledigt

Ähnliche Themen

  1. [Quiz #12] OnlyFoo (JavaScript)
    Von OnlyFoo im Forum Archiv
    Antworten: 5
    Letzter Beitrag: 15.11.09, 18:39
  2. [QUIZ#9] SteffenBoerner (C#)
    Von SteffenBoerner im Forum Archiv
    Antworten: 3
    Letzter Beitrag: 02.08.09, 14:15
  3. [Quiz#9] OnlyFoo (Javascript)
    Von OnlyFoo im Forum Archiv
    Antworten: 0
    Letzter Beitrag: 21.07.09, 18:22
  4. [QUIZ#05] OnlyFoo (JavaScript + SVG)
    Von OnlyFoo im Forum Archiv
    Antworten: 0
    Letzter Beitrag: 02.11.08, 01:36
  5. eine art quiz mit javascript
    Von DonMarkeZ im Forum Javascript & Ajax
    Antworten: 6
    Letzter Beitrag: 30.03.06, 19:51