Direzioni del vento di riferimento allo spazio della trama?

1

Ho un array 2D pieno di una semplice classe:

class Tile
{
    boolean N,E,S,W;
}

Ho anche una tessera che rappresenta tutti i possibili risultati tranne tutti i falsi (12 + crocevia). Ora ho bisogno di riferire tutte queste possibilità allo spazio delle texture sul mio foglio. Oltre ad avere una dichiarazione if per ogni risultato c'è un modo più efficace che attualmente non riesco a pensare?

    
posta Madmenyo 14.06.2014 - 18:45
fonte

1 risposta

4

Non sono sicuro di capire cosa stai facendo qui, ma la tua classe sembra essere equivalente a un intero a 4 bit e quindi potrebbe essere utile restituire il suo stato come tale o, ancora meglio, come un po ' bandiera enum. Potrebbe anche essere utile introdurre una proprietà dell'indicizzatore alla tua classe (sto usando c # qui) per scorrere facilmente i valori nelle 4 direzioni cardinali:

public enum CardinalDirection
{
    /// <summary>
    /// The +Y Direction 
    /// </summary>
    N = (1 << 0),
    /// <summary>
    /// The +X Direction 
    /// </summary>
    E = (1 << 1),
    /// <summary>
    /// The -Y Direction
    /// </summary>
    S = (1 << 2),
    /// <summary>
    /// The -X Direction
    /// </summary>
    W = (1 << 3),
}

[Flags]
public enum Direction
{
    None = 0,
    /// <summary>
    /// The +Y Direction 
    /// </summary>
    N = (1 << 0),
    /// <summary>
    /// The +X Direction 
    /// </summary>
    E = (1 << 1),
    /// <summary>
    /// The -Y Direction
    /// </summary>
    S = (1 << 2),
    /// <summary>
    /// The -X Direction
    /// </summary>
    W = (1 << 3),

    NE = N + E,
    NS = N + S,
    NW = N + W,
    ES = E + S,
    EW = E + W,
    SW = S + W,

    NES = N + E + S,
    NEW = N + E + W,
    NSW = N + S + W,
    ESW = E + S + W,

    NESW = N + E + S + W
}

public class Tile
{
    bool N, E, S, W;

    public static Direction ToDirection(bool N, bool E, bool S, bool W)
    {
        Direction dir = Direction.None;
        if (N)
            dir |= Direction.N;
        if (E)
            dir |= Direction.E;
        if (S)
            dir |= Direction.S;
        if (W)
            dir |= Direction.W;
        return dir;
    }

    public static void FromDirection(Direction dir, out bool N, out bool E, out bool S, out bool W)
    {
        N = (dir & Direction.N) == Direction.N;
        E = (dir & Direction.E) == Direction.E;
        S = (dir & Direction.S) == Direction.S;
        W = (dir & Direction.W) == Direction.W;
    }

    public Direction Direction
    {
        get
        {
            return Tile.ToDirection(N, E, S, W);
        }

        set
        {
            Tile.FromDirection(value, out N, out E, out S, out W);
        }
    }

    /// <summary>
    /// Returns the the value in the specified direction
    /// </summary>
    /// <param name="dir"></param>
    /// <returns></returns>
    public bool this[CardinalDirection cardinalDirection]
    {
        get
        {
            switch (cardinalDirection)
            {
                case CardinalDirection.N:
                    return N;
                case CardinalDirection.E:
                    return E;
                case CardinalDirection.S:
                    return S;
                case CardinalDirection.W:
                    return W;
                default:
                    throw new ArgumentOutOfRangeException("dir", cardinalDirection.ToString());
            }
        }
        set
        {
            switch (cardinalDirection)
            {
                case CardinalDirection.N:
                    N = value;
                    return;
                case CardinalDirection.E:   
                    E = value;
                    return;
                case CardinalDirection.S:
                    S = value;
                    return;
                case CardinalDirection.W:
                    W = value;
                    return;
                default:
                    throw new ArgumentOutOfRangeException("dir", cardinalDirection.ToString());
            }
        }
    }
}

Questo dovrebbe consentire di attivare comodamente le combinazioni di direzioni selezionate.

Come esempio di utilizzo della proprietà indexer per iterare attraverso i flag di direzione cardinale, il metodo seguente, dato un array 2d di tile, conta il numero di tile adiacenti a una tile specificata con valori di flag corrispondenti:

public static class TileHelper
{
    public static int CountConsistent(Tile[][] tiles, int iX, int iY)
    {
        int count = 0;
        var tile = tiles[iX][iY];
        foreach (var pair in tiles.WalkAround(iX, iY))
        {
            var dir = pair.Key;
            if (tile[dir] == pair.Value[dir.Rotate180()])
                count++;
        }
        return count;
    }

    /// <summary>
    /// Enumerate through the 4 tiles N, E, S, and W of the given tile in the tile array.
    /// Tiles off the edges of the array will be skipped.
    /// </summary>
    /// <param name="tiles"></param>
    /// <param name="iX"></param>
    /// <param name="iY"></param>
    /// <returns></returns>
    public static IEnumerable<KeyValuePair<CardinalDirection, Tile>> WalkAround(this Tile[][] tiles, int iX, int iY)
    {
        if (iX < 0 || iY < 0 || iX >= tiles.Length || iY >= tiles[iX].Length)
            yield break;
        if (iY + 1 < tiles[iX].Length)
            yield return new KeyValuePair<CardinalDirection, Tile>(CardinalDirection.N, tiles[iX][iY + 1]);
        if (iX + 1 < tiles.Length)
            yield return new KeyValuePair<CardinalDirection, Tile>(CardinalDirection.E, tiles[iX + 1][iY]);
        if (iY > 1)
            yield return new KeyValuePair<CardinalDirection, Tile>(CardinalDirection.S, tiles[iX][iY - 1]);
        if (iX > 1)
            yield return new KeyValuePair<CardinalDirection, Tile>(CardinalDirection.W, tiles[iX - 1][iY]);
    }

    public static CardinalDirection Rotate180(this CardinalDirection cardinalDirection)
    {
        switch (cardinalDirection) {
            case CardinalDirection.N:
                return CardinalDirection.S;
            case CardinalDirection.E:
                return CardinalDirection.W;
            case CardinalDirection.S:
                return CardinalDirection.N;
            case CardinalDirection.W:
                return CardinalDirection.E;
            default:
                throw new ArgumentOutOfRangeException("dir", cardinalDirection.ToString());
        }
    }
}

(Probabilmente il primo metodo potrebbe essere fatto in modo più bello con Linq).

Spero che ti aiuti.

    
risposta data 16.06.2014 - 08:44
fonte

Leggi altre domande sui tag