tutorials.de Buch-Aktion 05/2012
RSS-Feed anzeigen

Dem Dennis sein Blogdingen da...

Revival fuer meine alten QBasic-Games

Bewerten
von Dennis Wronka am 17.03.09 um 10:43 (1050 Hits)
Wie ich sicher mal erwaehnt hab hab ich meinen Programmiereinstieg in Basic "gefeiert".
Nachdem ich einen Monopoly-Clone auf dem Schneider in Basic lediglich abgetippt habe hab ich auf meinem ersten PC (einem 486 SX-25, mit sagenhaften 4MB Speicher und einer gewaltigen 120MB Festplatte) mit QBasic angefangen.

Nach anfaenglichem Rumtesten hab ich dann Text-Adventures geschrieben.
Da QBasic ja nun nicht mehr Teil von Windows ist ein Download den ich bei Microsoft gefunden habe nicht geholfen hat, oder zumindest nicht mittels Wine zum Laufen ueberredet werden koennte, dachte ich mir dass das ja mal eine nette Uebung waere etwas mehr in C# reinzukommen.

Gesagt, getan. Den heutigen Nachmittag habe ich also damit verbracht einen minimalen QBasic-Parser in C# zu bauen.
Minimal heisst hier dass nur die fuer meine Text-Adventures noetigen Funktionen, CLS, PRINT, INPUT, IF und GOTO, umgesetzt wurden.

Sicherlich ist der Code nicht wirklich optimal, so lese ich z.B. die QBasic-Datei 2 mal aus. Da werd ich noch dran arbeiten. Wahrscheinlich einmal komplett auslesen und dann einfach splitten.

Auf jeden Fall hab ich den Code nun soweit dass ich meine alten Spiele wieder spielen kann.
Nicht dass sie besonders gut waeren, aber das ganze soll ja eine Uebung in C# sein.

Das groesste Problem war im Grunde genommen ein konzeptuelles. GOTO unterscheidet sich ja insofern von einer Funktion dass nach Ausfuehrung des durch GOTO angegebenen Abschnitts nicht wieder zum Aufrufort zurueckspringt.
Aber auch das schein ich hingekriegt zu haben.

C# bietet sich hier ja auch deshalb an damit das fertige Programm schoen platformunabhaengig ist. Und da ich das Projekt als Konsolenanwendung umgesetzt hab gibt es auch keine Abhaengigkeiten zu Mono oder GTK#.

Nachher werd ich nochmal durch den Code wuseln und schauen was ich noch auf die Schnelle verbessern kann und werde den Code dann wohl mal hier zur allgemeinen Belustigung posten.

"Revival fuer meine alten QBasic-Games" bei Twitter speichern "Revival fuer meine alten QBasic-Games" bei Facebook speichern

Kategorien
Programming

Kommentare

  1. Avatar von Dennis Wronka
    So, hier nun der Code.
    Sicher nicht perfekt, aber er scheint soweit zu funktionieren.

    Hab auch nun das 2. auslesen der QBasic-Datei durch einen Regex-Split ersetzt, viel Zeit wird dadurch aber scheinbar nicht eingespart. Zumindest nicht bei den kleinen Spielchen die ich damals zusammengetippt hab.

    Also, wie gesagt, nun zur allgemeinen Belustigung mein sozusagen ersten "fertiges" C#-Programm:
    Code csharp:
    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
    
    // Main.cs created with MonoDevelop
    // User: dennis at 10:10 AM 3/17/2009
    //
    // To change standard headers go to Edit->Preferences->Coding->Standard Headers
    //
    using System;
    using System.IO;
    using System.Text.RegularExpressions;
     
    namespace GotoExec
    {
        class MainClass
        {
            private static string[] blocks;
            private static string functionblocklist;
     
            public static void parseblock(int block)
            {
                string input="";
                string[] blocklines=blocks[block].Split('\n');
     
                for (int line=0;line<blocklines.Length;line++)
                {
                    Regex reg=new Regex("^[0-9]+");
                    string blockline=reg.Replace(blocklines[line],"").Trim();
                    reg=new Regex(": ");
                    string[] blocklineparts=reg.Split(blockline);
     
                    for (int part=0;part<blocklineparts.Length;part++)
                    {
                        reg=new Regex("^CLS");
        
                        if (reg.IsMatch(blocklineparts[part]))
                        {
                            Console.Clear();
                            continue;
                        }
     
                        reg=new Regex("^PRINT \".*\"");
     
                        if (reg.IsMatch(blocklineparts[part]))
                        {
                            string output=reg.Match(blocklineparts[part]).ToString().Split('"')[1];
                            Console.WriteLine(output);
                            continue;
                        }
     
                        reg=new Regex("^INPUT \".*\"; .*");
     
                        if (reg.IsMatch(blocklineparts[part]))
                        {
                            string output=reg.Match(blocklineparts[part]).ToString().Split('"')[1];
                            Console.Write(output);
                            input=Console.ReadLine();
                            continue;
                        }
     
                        reg=new Regex("^IF .* THEN GOTO [0-9]+");
     
                        if ((reg.IsMatch(blocklineparts[part])) && (input.Length>0))
                        {
                            Match m=reg.Match(blocklineparts[part]);
                            string condition=m.ToString().Split('"')[1];
                            string jump=m.ToString().Split(' ')[6];
     
                            if (input==condition)
                            {
                                reg=new Regex(jump+"-.*");
     
                                if (reg.IsMatch(functionblocklist))
                                {
                                    parseblock(Convert.ToInt32(reg.Match(functionblocklist).ToString().Split('-')[1]));
                                    return;
                                }
                            }
     
                            continue;
                        }
     
                        reg=new Regex("^GOTO [0-9]+");
     
                        if (reg.IsMatch(blocklineparts[part]))
                        {
                            string jump=reg.Match(blocklineparts[part]).ToString().Split(' ')[1];
                            reg=new Regex(jump+"-.*");
     
                            if (reg.IsMatch(functionblocklist))
                            {
                                parseblock(Convert.ToInt32(reg.Match(functionblocklist).ToString().Split('-')[1]));
                                return;
                            }
     
                            continue;
                        }
                    }
                }
            }
     
            public static void Main(string[] args)
            {
                if (args.Length==0)
                {
                    Console.WriteLine("No QBasic file has been specified.");
                    return;
                }
     
                if (!File.Exists(args[0]))
                {
                    Console.WriteLine("File not found.");
                }
     
                string code=File.ReadAllText(args[0]);
                Regex reg=new Regex(".*\r\n\r\n");
                blocks=new string[reg.Matches(code).Count];
                reg=new Regex(".*GOTO [0-9]+");
                MatchCollection jumps=reg.Matches(code);
                reg=new Regex("GOTO ");
                string jumpliststring="";
     
                for (int jump=0;jump<jumps.Count;jump++)
                {
                    string[] jumpinfo=reg.Split(jumps[jump].ToString());
                    jumpliststring+=jumpinfo[1]+'\n';
                }
     
                string[] jumplist=jumpliststring.Split('\n');
                jumpliststring="";
     
                for (int jump=0;jump<jumplist.Length;jump++)
                {
                    reg=new Regex(jumplist[jump].ToString()+'\n');
     
                    if (!reg.IsMatch(jumpliststring))
                    {
                        jumpliststring+=jumplist[jump]+'\n';
                    }
                }
     
                jumplist=jumpliststring.Split('\n');
                reg=new Regex("\r\n");
                string[] lines=reg.Split(code);
                int block=0;
     
                for (int line=0;line<lines.Length;line++)
                {
                    if (lines[line].Length==0)
                    {
                        block++;
                    }
                    else
                    {
                        blocks[block]+=lines[line]+'\n';
                    }
                }
     
                for (int jump=0;jump<jumplist.Length;jump++)
                {
                    if (jumplist[jump].Length>0)
                    {
                        reg=new Regex("^"+jumplist[jump]+".*",RegexOptions.Compiled);
     
                        for (block=0;block<blocks.Length;block++)
                        {
                            if (reg.IsMatch(blocks[block]))
                            {
                                functionblocklist+=jumplist[jump]+"-"+block.ToString()+'\n';
                                break;
                            }
                        }
                    }
                }
     
                string mainblockliststring="";
     
                for (block=0;block<blocks.Length;block++)
                {
                    reg=new Regex(".*-"+block.ToString()+'\n');
     
                    if (!reg.IsMatch(functionblocklist))
                    {
                        mainblockliststring+=block.ToString()+'\n';
                    }
                }
     
                string [] mainblocklist=mainblockliststring.Split('\n');
     
                for (block=0;block<mainblocklist.Length;block++)
                {
                    if (mainblocklist[block].Length>0)
                    {
                        parseblock(Convert.ToInt32(mainblocklist[block]));
                    }
                }
            }
        }
    }
  2. Avatar von Navy
    Hey Dennis,

    auch wenn es Mono gibt, so ist das .net Framework nicht Plattformunabhängig, denn dafür gibt es noch viel zu viele Unterschiede zu dem Pendant von MS. Deswegen wäre es eleganter es in Java umzusetzen...