Coding the Java Explorer


Collapse Content

You could see the whole board in all the challenges in the Advanced Java Explorer except the last. This means you could hand-code the Explorer to defeat the enemies and one contestant actually used this approach to beat the challenges. You look at the board and figure out the plan of attack and then encode it in a long String / Array of moves where the explorer looks at the next character to determine each turn.

A more general solution would be to create an AI for the explorer to analyze the board each turn and decide what to do. You can build up the AI from level to level, until it easily beats the final level. This was the approach mostly followed by the winner of the contest, Egor Kulikov. This post will look at solving the first two challenges.

Hello Again

In this level, the explorer needs to get by a Pawn and then reach the Goal.

▥▥▥▥▥▥▥▥▥▥
▥♖...▥...▥
▥....▥...▥
▥...♟....▥
▥..♟.....▥
▥▥▥.....↢▥
▥........▥
▥......↢.▥
▥.....▥.☆▥
▥▥▥▥▥▥▥▥▥▥

A direct move-or-fight method would die when facing the Archers, so you need to recharge at some point. If you just recharge when you're energy is low, you'll get stuck in a loop when facing the Archer's attack. Instead, you should recharge when low on energy unless you're under attack. One way to solve it is to keep track of your health, and only recharge if it's low but not decreasing. This is similar to the Archer and Archers! levels from Java Explorer 1D and 2D:

class Player{   
    int health = 100;
    public void play(Explorer explorer){
        if(explorer.getHealth() < 90 && health == explorer.getHealth()){
            explorer.recharge();
        }
        else if(explorer.getSpace(Direction.DOWN).isEnemy()){
            explorer.poke(Direction.DOWN);  
        }
        else if(explorer.getSpace(Direction.RIGHT).isWall()){
            explorer.walk(Direction.DOWN);
        }
        else{
            explorer.walk(Direction.RIGHT);
        }
        health = explorer.getHealth();
    }   
}

Knights

Knights are much more dangerous than other enemies, since one you come into their line of sight, there's almost no escaping them. To defeat them you need to carefully encounter one at a time, bring it away from its friends and fight it there. Then you can recharge and face another Knight, until you've cleared a path forward.

Although you can use lookAround in this level to detect Knights, you can also use your previous code to detect when you're under attack and then follow the 'flight then fight' pattern. You'll just need to make sure you don't get to close to more than one Knight. In the code below, the Explorer pauses when moving down to see if anything attacks.

class Player {

    int y = 1;
    int moves = 0;
    int health = 100;
    boolean flee = false;
    public void play(Explorer explorer){
        if(explorer.getHealth() < 80 && !underAttack(explorer)){
            explorer.recharge();
        }
        else if(attackEnemy(explorer)){         
        }
        else if(flee){
            if(y>2){
                explorer.walk(Direction.UP);
            }
            else{
                explorer.walk(Direction.DOWN); //meet your enemy
                flee=false;
            }
        }
        else if(underAttack(explorer) && y>2){ //retreat
            flee = true;
            y--;
            explorer.walk(Direction.UP);
        }
        else if(explorer.getSpace(Direction.RIGHT).isWall()){
            if(moves%2==0){ //wait a move to see if attacked
                explorer.walk(Direction.DOWN);
                y++;
            }
        }
        else{
            explorer.walk(Direction.RIGHT);
        }
        health = explorer.getHealth();
        moves++;
    }   

    boolean attackEnemy(Explorer explorer){
        for(Direction d: Direction.values()){
            if(explorer.getSpace(d).isEnemy()){
                explorer.poke(d);
                return true;
            }
        }
        return false;
    }

    boolean underAttack(Explorer explorer){
        return health != explorer.getHealth();      
    }   

}

The alternative would be to just hand-code a solution, as mentioned above. For example, this solution reaches the goal in only 51 moves:

class Player{

    int move = 0;
    char[] ar = "rrr>>>>>>>hhhhhhhrrrrddulvvvvvvvvhhhhhhhhhrlddddddr".toCharArray();

    public void play(Explorer explorer){
        switch(ar[move]){
            case 'r':
                explorer.walk(Direction.RIGHT);
            break;
            case 'l':
                explorer.walk(Direction.LEFT);
            break;
            case 'd':
                explorer.walk(Direction.DOWN);
            break;
            case 'u':
                explorer.walk(Direction.UP);
            break;
            case '>':
                explorer.poke(Direction.RIGHT);
            break;
            case '<':
                explorer.poke(Direction.LEFT);
            break;
            case '^':
                explorer.poke(Direction.UP);
            break;
            case 'v':
                explorer.poke(Direction.DOWN);
            break;
            case 'h':
                explorer.recharge();
            break;
        }
        move++;
    }   
}
Contact Us
Sign in or email us at [email protected]