/*
Online Java - IDE, Code Editor, Compiler

Online Java is a quick and easy tool that helps you to build, compile, test your programs online.
*/

import java.util.Random;

interface Movable
{
    public void assignSnakesLadders();
    public void setGrid();
    public void checkSnakesLadder();
    public void defineMoves();
    public void diceThrow();
    public boolean performMove();
    public boolean validMove();
    
}


class SnakesLadders implements Movable
{
    //to hold all enum values....
    PositionSnakesLadders[] psl;
    
    int lengthEnum;
    boolean previousCompletedMove=false;
    int i;
    int j;
    int currentPosition;
    int newPosition;
    int diceValue;
    int [][] Board;
    StringJoiner sj = new StringJoiner(" ");
    int grids=100;
    
    enum PositionSnakesLadders
    {
        SNAKE1(16,6), SNAKE2(48,26), SNAKE3(49,11), SNAKE4(56,53), SNAKE5(62,19), SNAKE6(64,60),  SNAKE7(87,24), SNAKE8(93,73), SNAKE9(95,75), SNAKE10(98,78),
        LADDERS1(1,38), LADDERS2(4,14), LADDERS3(9,31), LADDERS4(21,42), LADDERS5(28,84), LADDERS6(36,44),  LADDERS7(51,67), LADDERS8(71,91), LADDERS9(80,100);
        
        int startPos;
        int endPos;
        
        PositionSnakesLadders(int startPos, int endPos)
        {
            this.startPos=startPos;
            this.endPos=endPos;
        }
        
    }
    
    //this is using logic described below....
    public void everyPossibleDieRoll()
    {
        for (int i=0; i<grids; i++)
        {
            if (i<95)
            {
                //more straight forward.
                //if its not completed this move, everyPossibleDieRoll is false..
                if (Board[i][diceValue][0]==0)
                {
                    previousCompletedMove=false;
                    
                }
                
            }
            
            if (i>=95)
            {
                for (int j=i; j<grids-i; j++)
                {
                    //if there is a 0  (reminder  [i][j][0=startPos  1=endPos])
                    //it means that this die roll has not occured from this situation...
                    //note as reminder of the logic below commented out, it is required
                    //to treat situation differently....
                    //j can not be treated as die value since values are not suitable from 95 upwards..
                    
                    if (Board[i][j][0]==0)
                    {
                        previousCompletedMove=false;
                    }
                }
                
                //the lengths of   [100][0][0]  is expected to be 0
        //the length of    [99][0][0] is expected to be one  {99,100}
        //the length of    [98][0][0] is expected to be two  {98,99},  {98,100}
        //the length of    [97][0][0] is expected to be three  {97,98}, {97,99}, {97,100}
         //the length of   [96][0][0] is expected to be four  {96,97}, {96,98}, {96,99}, {96,100}
         //the length of   [95][0][0] is expected to be five  {95,96}, {95,97}, {95,98}, {95,99}, {95,100}
                
            }
        }
        
        return previousCompletedMove;
    }
    
    
    
    
    public void defineMoves()
    {
        
        //[startPos] [ dicevalue] [ two elements, startPos and endPos ] 
        //this might be startPos on the grid between  1-99 
        //(excluding squares with Snake Head or base of ladder)…
        //{         diceValue{startPos,  endPos},  diceValue{startPos,  endPos}     };
        
        
        int [][][] moves = new int [100][6][2];
        grids = 100;
        
    }
    
    
    public void diceThrow()
    {
        Random rand = new Random();
        
        do
        {
     
        do
        {
        diceValue = (rand.nextInt(6)+1);
        
        System.out.println("value thrown:" + diceValue);
        
        
        //it would write the details here into the 3D array...
        Board[currentPosition][diceValue][0]=startPos;
        Board[currentPosition][diceValue][1]=endPos;
        
        //it has to also store the movements in a String since this is the only technique
        //for Set to differentiate if this path has been taken....
        
        sj.add(diceValue);
        sj.add("{");
        sj.add(startPos);
        sj.add(",");
        sj.add(endPos);
        sj.add("}");
        
        }while (performMove());
        
        
        //also need to add the number of moves to the String...
        path[count]=sj.toString();
        
        
        
        sj=new StringJoiner(" ");
        
        //ready to start again...
        //resets variables...
        
        currentPosition=0;
        previousCompletedMove=true;
        
    }while (everyPossibleDieRoll());
    
        // IT was iniitally envisaged to check the landscape of the board from the current position
        // to examine if avoiding a snake and getting maximum six values to get shortest path...
        //but in game of snakes and ladders, it might be beneficial slipping down a snake... and climbing a missed ladder since the differential
        //newPosition might be further than than getting a six.
        //The problem states smallest number of turns, hence it is utilizing the snakes and ladders to advantage.
        //and not necessarily getting a 6 on each throw...
        
        //this is where it needs another while loop
        //it has to keep going until...
        
        //when the combinations aspect is introduced, it needs to ensure there is a valid value that has
        //been inputted into each array position. This is the only way to ensure all possibilities have been explored..
        //from each position on the board..
        
        //the lengths of   [100][0][0]  is expected to be 0
        //the length of    [99][0][0] is expected to be one  {99,100}
        //the length of    [98][0][0] is expected to be two  {98,99},  {98,100}
        //the length of    [97][0][0] is expected to be three  {97,98}, {97,99}, {97,100}
         //the length of   [96][0][0] is expected to be four  {96,97}, {96,98}, {96,99}, {96,100}
         //the length of   [95][0][0] is expected to be five  {95,96}, {95,97}, {95,98}, {95,99}, {95,100}
         
         //FROM HERE ONWARDS, EXPECT lengths to be 6
         //the length of   [94][0][0] is expected to be six  {94,95}, {94,96}, {94,97}, {94,98}, {94,99}, {94,100}
        
    
    }
    
    
    public boolean performMove()
    {
        System.out.println("Current position on board: " + currentPosition);
        
        newPosition = currentPosition + diceValue;
        
        return validMove();
    }
    
    public boolean validMove()
    {
        if (newPosition>100)
        {
            newPosition=currentPosition;   //it performs a roll back
            
            return false;
        }
     
     //due to zero index  (diceValue-1)
     //{         diceValue-1{startPos,  endPos},  diceValue-1{startPos,  endPos}     };
     
     //it is irrelevant if the move has happened before, however it can perform quick check
     
     //if (Board[currentPosition][diceValue-1][0]!=0)
     //{
         //move has been performed since there is an entry...
     //}
         //this is a bit wasteful checking all the entries...
         //but there is no real reference point
         
         //this will go through all enums unconditionally
         //since it does not know which is snakes and ladders, it has to check the startPos and endPos
         //
         for (PositionSnakesLadders enum1: psl)
         {
             //if its a snake, start point is head.
             //if its a ladder, start point is bottom.
             if (currentPosition==enum1.startPos)
             {
                 //this has to be a snake since there is a descent...
                 if (enum1.startPos>enum1.endPos)
                 {
                     currentPosition=enum1.endPos;
                     
                     return true;
                     
                 }
             
              //this has to be a ladder since ascend
             if (enum1.startPos<enum1.endPos)
             {
                 currentPosition=enum1.endPos;
                 
                 return true;
             }
             
             }
             
         }  //end for 
         
         return false;
        
    }  //end boolean method
    
    
    //checking if board is valid...
    //not part of requirements.
    //but it is quite impossible creating other test scenarios without this...
    
    public void checkSnakesLadder()
    {
        for (PositionSnakesLadders enum1: psl)
        {
            //with the single Enum collection, it is not possible to validate if the endPos is greater than
            //startPos for ladder.
            //and if endPos is less than startPos for snakes...
            //since there is no way to distinguish the constants.....
            //Ignoring this aspect.
            //can potentially partition in future.
            
            for (PositionSnakesLadders enum2: psl)
            {
                //ensures no two enums are compared against each other....
                if (i==j)
                {
                    j++;
                }
                
                //this logic ensures it does not exceed boundary of the available enum constants...
                if (j!=(lengthEnum-1))
                {
                    //System.out.println("j: " + j);
                    //System.out.println("enum-1: " + (lengthEnum-1));
                    //System.out.println(enum2.name());
                    //System.out.println(enum2.startPos);
                    //System.out.println(enum2.endPos);
                    
                    //it will store the enum value of the i loop
                        
                        PositionSnakesLadders current = enum1;
                        
                    //looking at a real life board, it can be seen that no two elements (snake or ladders)
                    //have their ends simultaneously on any grid....
                    //so to ensure that all the logic holds, I will just run few checks for validation of
                    //data entry...
                        
                        if (current.startPos == enum2.endPos)
                        {
                            System.out.println("Invalid board configuration1: " + "{" + current.startPos+","+ current.endPos+"}");
                            System.out.println("Invalid board configuration1: " + "{" + enum2.startPos+","+ enum2.endPos+"}");
                            
                        }
                        
                        
                        if (current.endPos == enum2.startPos)
                        {
                            System.out.println("Invalid board configuration2: " + "{" + current.startPos+","+ current.endPos+"}");
                            System.out.println("Invalid board configuration2: " + "{" + enum2.startPos+","+ enum2.endPos+"}");
                            
                        }
                        
                
                        if (current.startPos == enum2.startPos)
                        {
                            System.out.println("Invalid board configuration3: " + "{" + current.startPos+","+ current.endPos+"}");
                            System.out.println("Invalid board configuration3: " + "{" + enum2.startPos+","+ enum2.endPos+"}");
                            
                        }
                        
                        if (current.endPos == enum2.endPos)
                        {
                            System.out.println("Invalid board configuration4: " + "{" + current.startPos+","+ current.endPos+"}");
                            System.out.println("Invalid board configuration4: " + "{" + enum2.startPos+","+ enum2.endPos+"}");
                            
                        }
             
                j++; 
            
                }
            }
         
         i++;   
        }
        
    }
    
    public SnakesLadders()
    {
        
        psl = PositionSnakesLadders.values();
        lengthEnum = psl.length;
        
        assignSnakesLadders();
        
    }
    
    public void setBoard()
    {
        Board = new int[][]  { 
                                        {100,99,98,97,96,95,94,93,92,91},
                                         {90,89,88,87,86,85,84,83,82,81},
                                        { 80,79,78,77,76,75,74,73,72,71},
                                        { 70,69,68,67,66,65,64,63,62,61},
                                        { 60,59,58,57,56,55,54,53,52,51},
                                        { 50,49,48,47,46,45,44,43,42,41},
                                        { 40,39,38,37,36,35,34,33,32,31},
                                        { 30,29,28,27,26,25,24,23,22,21},
                                        { 20,19,18,17,16,15,14,13,12,11},
                                        { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
                                        
                                        };
                                        
        
        
        
    }
    
    // without converting the board other than int[][], this method will always ensure that
    //all values of the enum
    //since the 
    public void assignSnakesLadders()
    {
        //validates the board....
        checkSnakesLadder();
        
    }
    
     public void setGrid()
    {
        
    }
    
}

public class Main
{
    public static void main(String[] args) {
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
        
        SnakesLadders sl = new SnakesLadders();
        
       
}
}
