3

I was hoping to get some help with this. The only real issue I'm having is that this code is not as efficient as it could be. Basically I have a set of tiles and need to decide what kind of tiles to instantiate based on the combination of tiles around them. In the code below, the position of the tile I'm checking is the key in my map (ex map[right] is the tile to the right, topLeft is the tile adjacent diagonally to the top left and top2 etc. is the tile two spaces in that direction).

The code in question:

if (map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.NOTHING && map[bottom].Type == TileType.NOTHING)
                    {
                        Instantiate(wallEdgeTopLeftInternalCornerTile, t.Position, Quaternion.identity);
                    }
                    else if (map[left].Type == TileType.NOTHING && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.NOTHING)
                    {
                        Instantiate(wallEdgeTopRightInternalCornerTile, t.Position, Quaternion.identity);
                    }
                    else if (map[left].Type == TileType.WALL && map[top].Type == TileType.NOTHING && map[right].Type == TileType.NOTHING && map[bottom].Type == TileType.WALL)
                    {
                        Instantiate(wallEdgeBottomLeftInternalCornerTile, t.Position, Quaternion.identity);
                    }
                    else if (map[left].Type == TileType.NOTHING && map[top].Type == TileType.NOTHING && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL)
                    {
                        Instantiate(wallEdgeBottomRightInternalCornerTile, t.Position, Quaternion.identity);
                    }
                    else if (map[left].Type == TileType.WALL && map[top].Type == TileType.FLOOR && map[right].Type == TileType.FLOOR && map[bottom].Type == TileType.WALL)
                    {
                        Instantiate(wallEdgeCornerTopRightTile, t.Position, Quaternion.identity);
                    }
                    else if (map[left].Type == TileType.FLOOR && map[top].Type == TileType.FLOOR && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL)
                    {
                        Instantiate(wallEdgeCornerTopLeftTile, t.Position, Quaternion.identity);
                    }

                    else if (map[left].Type == TileType.FLOOR && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL && map[topRight].Type == TileType.NOTHING)
                    {
                        Instantiate(wallEdgeCornerBottomLeftTile, t.Position, Quaternion.identity);
                    }
                    else if (map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.FLOOR && map[bottom].Type == TileType.WALL && map[topLeft].Type == TileType.NOTHING)
                    {
                        Instantiate(wallEdgeCornerBottomRightTile, t.Position, Quaternion.identity);
                    }

                    else if ((map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL && map[top2].Type == TileType.NOTHING && map[left2].Type == TileType.NOTHING) || (map[left].Type == TileType.FLOOR && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL && map[top2].Type == TileType.WALL && map[left2].Type == TileType.FLOOR && map[bottom2].Type == TileType.WALL))
                    {
                        Instantiate(wallTopLeftTile, t.Position, Quaternion.identity);
                    }
                    else if ((map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL && map[top2].Type == TileType.NOTHING && map[right2].Type == TileType.NOTHING) || (map[right].Type == TileType.FLOOR && map[top].Type == TileType.WALL && map[left].Type == TileType.WALL && map[bottom].Type == TileType.WALL && map[top2].Type == TileType.WALL && map[right2].Type == TileType.FLOOR && map[bottom2].Type == TileType.WALL))
                    {
                        Instantiate(wallTopRightTile, t.Position, Quaternion.identity);
                    }

                    else if ((map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.FLOOR && map[top2].Type == TileType.WALL && map[left2].Type == TileType.NOTHING) || (map[left].Type == TileType.FLOOR && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.FLOOR && map[top2].Type == TileType.WALL && map[left2].Type == TileType.FLOOR && map[bottom2].Type == TileType.FLOOR))
                    {
                        Instantiate(wallBottomLeftTile, t.Position, Quaternion.identity);
                    }
                    else if ((map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.FLOOR && map[top2].Type == TileType.WALL && map[right2].Type == TileType.NOTHING) || (map[right].Type == TileType.FLOOR && map[top].Type == TileType.WALL && map[left].Type == TileType.WALL && map[bottom].Type == TileType.FLOOR && map[top2].Type == TileType.WALL && map[right2].Type == TileType.FLOOR && map[bottom2].Type == TileType.FLOOR))
                    {
                        Instantiate(wallBottomRightTile, t.Position, Quaternion.identity);
                    }
                    else if ((map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL && map[left2].Type == TileType.NOTHING && map[bottom2].Type == TileType.FLOOR) || (map[left].Type == TileType.FLOOR && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL && map[left2].Type == TileType.FLOOR && map[bottom2].Type == TileType.FLOOR))
                    {
                        Instantiate(wallMidLeftTile, t.Position, Quaternion.identity);
                    }
                    else if ((map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL && map[right2].Type == TileType.NOTHING && map[bottom2].Type == TileType.FLOOR) || (map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.FLOOR && map[bottom].Type == TileType.WALL && map[right2].Type == TileType.FLOOR && map[bottom2].Type == TileType.FLOOR))
                    {
                        Instantiate(wallMidRightTile, t.Position, Quaternion.identity);
                    }
                    else if ((map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL && map[top2].Type == TileType.NOTHING && map[bottom2].Type == TileType.WALL))
                    {
                        Instantiate(wallTopTile, t.Position, Quaternion.identity);
                    }
                    else if ((map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.FLOOR && map[top2].Type == TileType.WALL && map[bottom2].Type == TileType.FLOOR))
                    {
                        Instantiate(wallBottomTile, t.Position, Quaternion.identity);
                    }
                    else if (map[top].Type == TileType.NOTHING && map[bottom].Type == TileType.WALL)
                    {
                        Instantiate(wallEdgeBottomTile, t.Position, Quaternion.identity);
                    }
                    else if ((map[left].Type == TileType.NOTHING && map[right].Type == TileType.FLOOR) || (map[left].Type == TileType.NOTHING && map[right].Type == TileType.WALL && map[top].Type != TileType.NOTHING))
                    {
                        Instantiate(wallEdgeRightTile, t.Position, Quaternion.identity);
                    }
                    else if ((map[left].Type == TileType.FLOOR && map[right].Type == TileType.NOTHING) || (map[left].Type == TileType.WALL && map[right].Type == TileType.NOTHING && map[top].Type != TileType.NOTHING))
                    {
                        Instantiate(wallEdgeLeftTile, t.Position, Quaternion.identity);
                    }
                    else if (map[bottom].Type == TileType.NOTHING && map[top].Type == TileType.FLOOR)
                    {
                        Instantiate(wallEdgeTopTile, t.Position, Quaternion.identity);
                    }
                    else if ((map[left].Type == TileType.WALL && map[top].Type == TileType.WALL && map[right].Type == TileType.WALL && map[bottom].Type == TileType.WALL && map[top2].Type == TileType.WALL && map[bottom2].Type == TileType.FLOOR))
                    {
                        Instantiate(wallMiddleTile, t.Position, Quaternion.identity);
                    }
                    else
                    {
                        // Should never get here, so if a white Tile is seen, something went wrong!
                        Instantiate(whiteTile, t.Position, Quaternion.identity);
                    }

I had made a table because I thought that I would instead check each position, assign it a number from 0-2, convert that number from base 3 to decimal, then use a switch statement on the outcome to determine which tile to instantiate. The number codes are on the very right. But there are so many combinations, I feel like there has to be a better or easier way. Any ideas at all are appreciated!

Table: Table of conditions

  • 2
    Use a Switch statement http://stackoverflow.com/questions/767821/is-else-if-faster-than-switch-case – LumbusterTick Apr 09 '16 at 23:35
  • I don't think a switch statement would solve my problem because I need to check for combinations of values, rather than just one specific value. – user3754585 Apr 10 '16 at 00:49
  • 1
    Move "Instantiate([value], t.Position, Quaternion.identity);" to the end of the control structure.Set the value of [value] to a variable, this way you only have one line with "Instantiate()". Also, you're repeating operands (e.g. map[left].Type == TileType.WALL). Try to find a way to where each equality comparer occurs only once. – Matt Cullinan Apr 10 '16 at 01:42
  • What is `map`? Is it a grid (2d array), or something else? – levelonehuman Apr 11 '16 at 18:00

1 Answers1

0

To simply reduce the number of caparison operations, I would suggest arrange your AND conditionals in a tree-type fashion. here is a simplified example.

note: I'm using single & for readability- I mean logical AND.

starting with:

if(a&b&c) {functionW(a);return;}  //1 comparison, 2 ANDops
else if(a&b&!c) {functionX(a);return;}//2 comparison, 4 ANDops
else if(a&!b&!c) {functionX(b);return;}//3 comparison, 6 ANDops
else if(a&!b&c) {functionX(c);return;}//4 comparison, 8 ANDops
else if(!&a&b&c) {functionY(b);return}//5 comparison, 10 ANDops
else if(!a&!b&c){functionZ(c);return}//6 comparison, 12 ANDops
else if(!b&!e){functionZ(c);return;}//7 comparison, 13 ANDops

Tree-format: take a branch for each element we are checking, so first check for a:

//out here,first, go all the statements, where it doesn't mater what value a has.  We haveonly one condition in our example, but if we had many, we could create a separate "tree" out here.
if(!b&!e){functionZ(c);return;}//1 comparison, 1 ANDops
//now we start a branch based on a
if(a)
{//in here go all the if statements where a is true
    //now we create onther tree branch based on b
    if(b)
    {   
        if(!c){ functionW(a); return;}// total 4 comparisons to get here. 1 ANDops
    }
    else 
    {//all option where b is false
        if(c) {functionX(c); return;}// total 4 comparisons to get here, 1 ANDops
        else {functionX(b); return;}// total 4 comparisons to get here, 1 ANDops
    }
}
else
{//in here go all the if statements where a is false (there are only two, so no need for a branch)
    if(b&c) {functionY(b);return}// total 3 comparisons to get here. 2 ANDops
    else if(!b&c){functionZ(c);return}// total 3 comparisons to get here, 3 ANDops
}

Obviously you don't get a huge advantage with only 7 different conditionals, but this improvement grows, with the amount of conditionals you start with.

Glurth
  • 290
  • 1
  • 17