3
\$\begingroup\$

I am creating a roguelike which will use an ASCII based tile set. There is a text file that represents the map (ie. walls, floor, items). I believe the next steps are to read this file in and use a 2D array to hold objects that represent each of the characters.

My question is, is there a more efficient way to parse through that file and create the object map without using one huge switch statement to create the proper object? If not, is there a better approach I can take overall?

\$\endgroup\$
  • 2
    \$\begingroup\$ Best approach I've found for reading map files is to do the simplest thing at the beginning, and then revisit it later. A huge switch statement is fine. The engineering tradeoffs (especially with performance) aren't always apparent until I get farther into the project. \$\endgroup\$ – amitp Jul 16 '15 at 22:10
  • \$\begingroup\$ I'm not sure if this is answerable without knowing your file format and what kinds of objects you need to parse your text into. Having said that, I agree that there's nothing wrong with a switch statement. Stick it in a factory if you don't want it cluttering up your map parsing method. \$\endgroup\$ – Sandalfoot Jul 17 '15 at 0:57
  • \$\begingroup\$ The text file is just a formatted plain ol' file with symbols in them that stand for different tile types (ie. wall, floor, door...) \$\endgroup\$ – The Sheek Geek Jul 17 '15 at 19:24
1
\$\begingroup\$

Any modern compiler will almost always convert a large Switch statement into a jump table; not into a succession of nested IF's. This may be ugly code, violating your sense of aesthetics, but is the most efficient means to parse such a structure. If you were to use a Lexer- or Parser-Generator tool such as LEX or YACC or any of their modern descendants, that is exactly what they generate.

Note that if you have different classes to represent the different terrain types, then you have replaced a multitude of repetitive switch statements during game operation with a single switch statement at class generation time. That in and f itself is a very significant performance improvement.

\$\endgroup\$
  • \$\begingroup\$ I did have the objects for each tile type. I thought it would make keeping track of mobs and loot much easier. Ultimately, I did use the switch statement. As you said, it didn't seem to be bogged down at all. \$\endgroup\$ – The Sheek Geek Jul 24 '15 at 13:27
1
\$\begingroup\$

Can you set them up as a generic Dictionary<String, Object>?

private readonly Dictionary<String, Object> _tileDefinitions =
    new Dictionary<String, Object>
    {
       {"_", nothing},
       {"#", wallobj},
       {"$", treasureobj}
    };

public Map Parse(string fileContents)
{
    var x = 0;
    var y = 0;
    var map = new Map();
    for(var i = 0; i < fileContents.Length; i++)
    {
        x++;
        if(fileContents[i] == Environment.NewLine)
        {
            x = 0;
            y++;
            continue;
        }
        Tile tile;
        if(_tileDefinitions.TryGetValue(fileContents[i], out tile))
            map[x, y] = tile;
        else
            throw new Exception("Invalid tile " + fileContents[i]);
    }
    return map;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.