Introduction
In this lesson, to get an introduction to Java, you will be programming a
virtual robot so that it can navigate its way around a maze and find the
finishing (blue) tile.
Task
Create a new folder where we will store everything for the game. Call it
something like robot_project
.
Getting the Files
Your teacher should be able to give you individual instructions on how to get
the files needed for this lesson.
After obtaining the files needed, have a look in the folder, there may be a
number of files and folders, but two are particularly important:
src
- This folder contains all of our java source code.
make_and_run_gui
- This file is what you canuse to compile our java code
and run our program if you are not using eclipse.
Run Your Code
To start off, try running the program to make sure it's working correctly.
The way in which you run your program depends on how you have opened the
files.
-
If Using Eclipse: Open the folder
com.samlanning.robot_simulator.simulator
, right click
the file GUISimulator.java
, go to Run As
and then select Java Application
.
Hint: from this point onwards, you can just press
the green play button at the top of the screen.
-
If NOT Using Eclipse. Open a terminal inside the
folder where these files are, and to compile and run the program, you
need to type the command:
./make_and_run_gui
from inside
the terminal. Make sure that your terminal is in the same directory
as these new files.
Understanding The Simulator
To begin with there will not be any maps loaded into the simulator, so the
first thing you need to do is load a map. After a map is loaded, you can start
the robots navigating their way around it by hitting the Play button in the
bottom right hand corner.
Task
Load each of the different maps, and hit `Play` each time to see how the
existing bots navigate their way around the map.
In the top right hand corner are numbers which control the speed of the
simulator. Delay is how much time the robots are paused for after
performing an action (in milliseconds) and Animation Duration is how much
time the animations last for (also in milliseconts).
Task
Have a go changing these values and see how they affect the simulator.
On the right you will also see a list of robots that are currently on the map,
and what their current statuses are.
Managing Your Robots
Open up the folder src/com/samlanning/robot_simulator/robots/
. You should see
three files in there:
CustomRobot.java
- This is currently a robot that does nothing, you will later
be modifying this file to make the robot do stuff.
RandomRobot.java
- This is a type robot that moves around the map randomly.
RobotsEnum.java
- This file contains a list of all the robots that we want
to currently have on the screen, and what their individual colours are.
Open up the file RobotsEnum.java
, you should have something that looks like
this:
package com.samlanning.robot_simulator.robots;
import java.awt.Color;
import com.samlanning.robot_simulator.iface.Robot;
/**
* An enum of all robots that you want to make available.
*/
public enum RobotsEnum {
MY_ROBOT(new CustomRobot(), new Color(100, 100, 100)),
RANDOM(new RandomRobot(), new Color(0, 100, 100)),
;
public final Robot robot;
public final Color color;
private RobotsEnum(Robot robot, Color color){
this.robot = robot;
this.color = color;
}
}
The important bits are the two lines directly under public enum RobotsEnum {
.
These two lines define the two robots that we have on the screen at the moment,
one is a CustomRobot
, and the other is a RandomRobot
, named MY_ROBOT
and
RANDOM
respectively, and with custom colours.
Task
Lets modify this file to add two more random robots with different
colours to our simulation.
Under the two existing robots, but above the semicolon,
write these two lines:
RANDOM_2(new RandomRobot(), new Color(100, 0, 100)),
RANDOM_3(new RandomRobot(), new Color(100, 100, 0)),
Run Your Code
Run the program to see what effect this has had to the simulation.
Creating Your Own Map
Open up the folder src/com/samlanning/robot_simulator/maps/
. Like with the
robots
folder, this folder contains all of the information about the
different maps that are available to the simulator. The file MapsEnum.java
contains a list of all the maps that we want to use, along with names for them.
This file should look like this:
package com.samlanning.robot_simulator.maps;
import com.samlanning.robot_simulator.iface.RobotMap;
public enum MapsEnum {
BASIC_1(new BasicMap1()),
BASIC_2(new BasicMap2()),
BASIC_3(new BasicMap3()),
RANDOM_START(new RandomStartMap(new BasicMap3())),
HARD_1(new HardMap1()),
HARD_2(new HardMap2()),
HARD_2_RANDOM(new RandomStartMap(new HardMap2())),
;
public final RobotMap map;
private MapsEnum(RobotMap map){
this.map = map;
}
}
Task
Lets create a new map that we can use in the simulation.
Create a new file called BasicMap4.java
in the
maps
directory, and give it the following content:
package com.samlanning.robot_simulator.maps;
import com.samlanning.robot_simulator.iface.MapBlock;
import com.samlanning.robot_simulator.iface.RobotMap;
import com.samlanning.robot_simulator.simulator.executor.Direction;
public class BasicMap4 extends RobotMap {
public BasicMap4(){
MapBlock[][] map = new MapBlock[][]{
{MapBlock.EMPTY, MapBlock.EMPTY, },
{MapBlock.EMPTY, MapBlock.EMPTY, },
};
this.setMap(map, 0, 0, Direction.UP);
}
}
This is a new map file that has 4 tiles (it is 2 tiles wide and 2 high).
Lets add this new map to MapsEnum
.
In the MapsEnum.java
file, after the line
BASIC_3(new BasicMap3()),
add this line:
BASIC_4(new BasicMap4()),
Run Your Code
Run the program to check that your new map has appeared in the list on the
right and that you can load it correctly.
Task
Now modify this new map that you have created, by changing the lines
under the line MapBlock[][] map = new MapBlock[][]{
to make
the map bigger than 2 x 2, and add some wall and finish objects, like in
the maps BasicMap1
and BasicMap2
.
Hint: Each line should be a row of tiles in the map, and
every row needs to have the same number of tiles. You have a choice of
MapBlock.Wall
, MapBlock.FINISH
and
MapBlock.EMPTY
.
Run Your Code
Run the program to check that your new map works after your changes, and
appears how you intended when you load it.
Your First Robot
Back in the robots
folder, open the file CustomRobot.java
. You should see
something like this:
package com.samlanning.robot_simulator.robots;
import com.samlanning.robot_simulator.iface.Robot;
import com.samlanning.robot_simulator.iface.RobotControl;
public class CustomRobot implements Robot {
@Override
public void run(final RobotControl control) {
}
}
This file contains the code for a robot that currently does nothing, we will
modify this robot so that it can complete some of the maps.
The main component inside this file is the class CustomRobot
, it begins with
this line:
public class CustomRobot implements Robot {
This class defines what a CustomRobot
is and how it should behave, everything
between this line and the last line (}
) is inside the class.
At the moment there is only a single thing inside of this class, the method
run
:
@Override
public void run(final RobotControl control) {
}
This method is like a function, and is called by our simulator to control
the robot when a simulation starts. There is currently no code inside of this
function (between the curly brackets {
and }
), so this robot will do
nothing, and stop immidiately.
The file RobotsEnum.java
contains the code which uses this class, it creates
a robot called MY_ROBOT
, which is a CustomRobot
.
If you run the program, you can see that this robot is marked as STOPPED
as soon as the simulation is started because it doesn’t do anything inside this
method.
Lets make this robot do something!
Task
Inside the run
method, write these 4 lines of code:
control.moveForward();
control.moveForward();
control.turnLeft();
control.turnRight();
control
is a variable that is accessible from inside the method, it allows
the robot to move forwards, or turn left / right in the simulator, and allows
it to detect what the tile infront of it is.
In this example, the robot requests to move forward twice, and then move left
and right.
Run Your Code
Run the program to see how the robot behaves in the maps
BASIC_1
and BASIC_2
. What happens to the robot in
the map BASIC_3
?
Task
Add one extra call to control.moveForward();
at the end of the
code you have just written, and run it again to see what happens in the
maps BASIC_1
and BASIC_2
.
Complete The First Map
Now that you have learned the first building blocks needed to move your robot
around the screen, you have got enough tools to help you make a robot that can
navigate its way around one of the maps.
Task
Modify your current robot (CustomRobot
) so that it can
navigate its way to the finish tile (the blue one) in the map
BASIC_1
.
Hint: you only need to use these three statements, the
correct number of times and in the right order:
control.moveForward();
control.turnLeft();
control.turnRight();
Run Your Code
Run your code to make sure that your robot can finish the first map.
A Robot With A Graphical Remote Control
We are now going to make a robot that you can give commands to at each step of
the way so that you can allow it to navigate to the finish manually.
Task
In the robots folder, create a new class and call it
RemoteRobot
, and paste in the following start code:
package com.samlanning.robot_simulator.robots;
import com.samlanning.robot_simulator.iface.Robot;
import com.samlanning.robot_simulator.iface.RobotControl;
public class RemoteRobot implements Robot {
@Override
public void run(RobotControl control) {
}
}
Now open the file RobotsEnum.java
and on a new line under
the line where you create the MY_ROBOT
robot, write this:
REMOTE_ROBOT(new RemoteRobot(), new Color(50, 50, 50)),
Note: You can get rid of the lines that define the
random robots now if you like.
Run Your Code
Run your code to make sure that a new robot called
REMOTE_ROBOT
has appeared on the side and in the map.
Task
Under the first line of code in this new file, that starts with
package
, write the following line:
import javax.swing.JOptionPane;
This imports a class into our file which we can use in a
little bit that will allow us to create a popup message that asks the
user a question.
Inside the empty run
method, write the following lines of
code:
Object[] moves = { "Forwards", "Left", "Right", "Stop" };
int selection = JOptionPane.showOptionDialog(null,
"Please Pick a Next Move",
"Next Move",
JOptionPane.DEFAULT_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
moves,
null);
This code firstly creates a new variable called moves
that
is a list of options that we will allow the user to choose from to
control the robot.
Secondly, this code opens up a dialog box asking the user to select an
option, this code will then wait until the user has selected an option,
and then the variable selection
will become a number between
0
and 3
that represents the move that the user
selected.
Run Your Code
Run your code, you should see that when you load a map and start the
simulation, that a dialog box pops up asking the user for a choice. If you
select an option, the robot will not do anything and will shut down
immidiately because we do not actually tell the robot to do anything after
we ask the user for input.
We need to now get the robot to move in the correct way depending on user
input.
Task
Under the code you have just written, write the following:
if(selection == 0){
control.moveForward();
} else if(selection == 1){
control.turnLeft();
} else if(selection == 2){
control.turnRight();
} else {
control.stop();
}
Run Your Code
Run your code, after the user chooses an option, you can see that the robot
will perform the correct action, but it will only ever do one action.
At the moment, the robot will never perform more than 1 action, let’s get the
robot to continually ask for actions while it is running.
Task
Above the line where we set the selection
variable, write
this:
while(true) {
And under the last line of code that you added in the previous step, add
this:
}
What this does is it wraps the code that asks for a user request and
performs an action in a while loop that goes on forever
(or until the simulator stops the robot, or until the user selects the
stop action.
Now that we have added some extra code around our previous code, the
indentation is probably all wrong and it would be nice to fix this! If
you are using eclipse, press the key combination
Ctrl + Shift + F
, and it will automatically format all of
your code in a nice way to try and make it more readable.
The reason it can do this is because, unlike python
for
example, Java
is not whitespace-sensitive,
it has other ways of working out what code is "inside" other
bits of code (the curly braces {
and }
), so it
has the freedom to add extra spaces anywhere it likes without changing
the meaning of the code.
Run Your Code
Run your code, and if all is working, you should be able to control the
robot to get it to the finish tile.
Task
The final thing that we want to do is move the code in the while loop
into a separate method.
Firstly, move the line which creates the variable moves
(the
one that starts with Object[] moves ...
),
above the line that says @Override
.
Next, before the final bracket at the end of the file, write this:
private void doAStep(RobotControl control){
}
This is a new method, which takes control
as an argument.
Next, move all the code from inside the
while loop to inside this new method.
Finally, inside the old while loop, write this:
doAStep(control);
Don't forget to re-format your code! It's good practice
to do it every time you make a change to your code.
Run Your Code
Run your code, and if all is working, you should be able to control the
robot to get it to the finish tile.
Detecting what is infront
As well as being able to move the robot around, the variable control
allows
the robot to check what the tile infront of it is, later we will use this to
create a more intelligent robot that can work its way round many maps, but for
now lets just see how to access this information.
Task
Above the line
import com.samlanning.robot_simulator.iface.Robot;
, write
the following:
import com.samlanning.robot_simulator.iface.MapBlock;
This imports the type MapBlock
which will allow us to
inspect the block infront of us.
Inside the new doAStep
method, right at the start, write
this:
MapBlock ahead = control.lookAhead();
And below that, where we have the string
"Please Pick a Next Move"
, replace it with this:
"The next block ahead is " + ahead.name()
Run Your Code
Run your code, and if all is working, when the robot asks the user for the
next move, it should also say what is currently infront of it.
Making a Robot that works for Many Maps
We are now going to make a robot that is based on a simple idea, try and keep
to the left as much as possible, if there is a wall keep going, and if there is
no wall to the left, turn left and keep going down there. If there is a wall to
your left and infront, turn right, and if there is a wall to the left, the
front and the right, turn all the way around and come back the way you came.
Implementing this robot is made a little bit tricky by the fact that the robot
can only look ahead and not to the side, so it will need to turn to the left
often.
Lets make this robot.
Task
In the robots
folder, create a new class called
SmartRobot
, and write this inside it:
package com.samlanning.robot_simulator.robots;
import com.samlanning.robot_simulator.iface.MapBlock;
import com.samlanning.robot_simulator.iface.Robot;
import com.samlanning.robot_simulator.iface.RobotControl;
public class SmartRobot implements Robot {
@Override
public void run(final RobotControl control) {
while(true){
control.turnLeft();
while(control.lookAhead() == MapBlock.WALL)
control.turnRight();
control.moveForward();
}
}
}
This robot behaves exactly as described in the paragraphs above, but we
still need to add it to RobotsEnum
.
Add this new robot to RobotsEnum
like we have done
previously, call it SMART_ROBOT
, and give it any color you
like.
Run Your Code
Run your code, you should now have a new robot, and it should be able to
finish the maps BASIC_1
, BASIC_2
,
BASIC_3
and RANDOM_START
.
For the map BASIC_1
, this robot goes the long way round. Lets make a version
that instead keeps to the right and will solve this map quicker.
Task
Create a new robot called SmartRobot2
, and using the same
starting code as SmartRobot
, make it keep to the right
instead of to the left.
Add this robot to RobotsEnum
like we have done previously.
Run Your Code
Run your code and make sure your new robot behaves as you would expect.
Challenges (Extension Material - Hard)
When you are comfortable enough with Java, here are some tasks you can do if
you return to this lesson.
- Make a robot that works for the hard maps (without hard-coding anything).
- Locate the part of the simulator code that draws the robots on the screen,
and change the look of the robots to a different shape, and potentially make
them very detailed.
- Modify
RobotControl
so that a robot is also able to look left and right,
update the simulator for this to work, and create an up-to-date robot that
can finish a maze using less moves.
- Modify
RobotControl
so that a robot can also move backwards one space, and
create a robot that uses this functionality. Make sure that you handle
crashes correctly.