Search code examples
c#sliding-tile-puzzle

Need explanation on these bits of codes


i have recently stumbled upon a project(8-puzzle solver using A* alg) in which some codes are weird to me , because i have never seen the likes of it before .

what does this line mean ? what is this ?!

this[StateIndex]

whats this notation ? i cant undersand it at all ! i posted a sample of the class so that you can see it almost all together . and one more question , is it not wrong to have a class implemented like StateNode? it used only a constructor to initialize its fields , and yet worst, declared them all public ! should he/she not have implemented Propertise for this task?

public enum Direction 
{
    Up = 1, Down = 2, Left = 3, Right = 4, UpUp = 5, DownDown = 6, LeftLeft = 7, RightRight = 8, Stop = 9
}

class StateNode
{
    public int Parent;
    public List<int> Childs;
    public Direction Move;
    public Direction ParentMove;
    public byte[,] State;
    public byte Depth;
    public byte NullRow;
    public byte NullCol;
public StateNode()
{ }
public StateNode(int NewParent, Direction NewMove, Direction ParentMove, byte NewDepth, byte NewNullRow, byte NewNullCol)
{
    this.Parent = NewParent;
    this.State = new byte[5, 5];
    this.Move = NewMove;
    this.ParentMove = ParentMove;
    this.Depth = NewDepth;
    this.NullRow = NewNullRow;
    this.NullCol = NewNullCol;
    this.Childs = new List<int>();
}
}

class StateTree : List<StateNode>
{
    public static long MakedNodes;
    public static long CheckedNodes;
    public static byte MaxDepth;

    public List<int> Successor1(int StateIndex)
    {
        List<int> RetNodes = new List<int>();
        StateNode NewState = new StateNode();

        //Up
    if (this[StateIndex].NullRow + 1 <= 3 && this[StateIndex].ParentMove != Direction.Up)
    {
        NewState = ChangeItemState(this[StateIndex], StateIndex, Direction.Up, Direction.Down, Convert.ToByte(this[StateIndex].Depth + 1), this[StateIndex].NullRow, this[StateIndex].NullCol, Convert.ToByte(this[StateIndex].NullRow + 1), this[StateIndex].NullCol);

        this.Add(NewState);
        RetNodes.Add(this.Count - 1);
        StateTree.MakedNodes++;
        this[StateIndex].Childs.Add(this.Count - 1);
        if (NewState.Depth > StateTree.MaxDepth)
            StateTree.MaxDepth = NewState.Depth;

    }
    //Down
    //Left
    //Right

    return RetNodes;
}
}

Solution

  • this[StateIndex] is using the current class' indexer property. The indexer property is what allows you to access an element in a collection or list object as if it was an array. For instance:

    List<string> strings = new List<string>();
    strings.Add("Item 1");
    strings.Add("Item 2");
    strings.Add("Item 3");
    string x = strings[0];  // Returns the first item in the list ("Item 1")
    

    When you want to access the indexer property of your own class, however, you have to preface it with the this keyword. You'll notice that in your example, the StateTree class doesn't implement an indexer property, so that may be adding to your confusion. The reason it works is because StateTree inherits from List<StateNode> which does implement an indexer property.

    But don't get confused between classes with indexer properties and arrays. Arrays are a completely different thing, though the syntax is similar. An array is a list of objects which can be accessed by an index. An indexer property is an unnamed property of a single object that acts as an array. So for instance, List<string> has an indexer property, so you can access the items it contains using the same syntax as an array index (as shown in the above example). However, you can still make an array of List<string> objects. So for instance:

    List<string> strings1 = new List<string>();
    strings1.Add("Item 1.1");
    strings1.Add("Item 1.2");
    
    List<string> strings2 = new List<string>();
    strings2.Add("Item 2.1");
    strings2.Add("Item 2.2");
    
    List<string>[] stringsArray = new List<string>[] { strings1, strings2 };
    object result;
    result = stringsArray[0];  // Returns strings1
    result = stringsArray[0][1];  // Returns "Item 1.2"
    result = stringsArray[1][0];  // Returns "Item 2.1"
    

    As far as StateNode goes, there's nothing technically wrong with it, and it's not unusual to have a constructor that initializes all the field values, but it's always better to use properties instead of public fields.