Question
I'm very lost with where to begin on this program, any advice would be greatly appreciated. There were some prerequisites to run this, we had to add pictures to our workspace as well as several maze templates, and I can add those if necessary. These were the instructions.
In Recitation 10 you should have started on P6.java. If not, follow the directions here. Leave in the code you wrote that instantiates the Maze object and retrieves the dimensions. Remove any code from the recitation that moves Chihiro around in the maze. Then add code to implement the algorithm shown below. This will require multiple control loops, which can be either while or for statements. Here is a complete specification of the Maze methods you can call:
To solve the assignment, you may want to implement the following methods:
Algorithm
The mazes can be of any size.
Haku is always in the top left corner.
Chihiro can start anywhere, as specified by the maze.
Yubabas can be anywhere, as specified by the maze.
If you follow the rules, Chihiro will never meet Yubaba, and will find Haku.
Row and column numbers are zero based, so the first row and column is index 0.
Here is the exact algorithm for finding Haku, each step requires a loop:
If Chihiro is not on any edge, move straight up to the top row.
If Chihiro is on the top edge, move right to the top-right corner.
If Chihiro is on the right edge, move down to the bottom-right corner.
If Chihiro is on the bottom edge, move left to the bottom-left corner.
If Chihiro is on the left edge, move up to the top-left corner.
If you go outside the maze, the maze will print an error and exit.
If you go run into Yubaba, the maze will print an error and exit.
When Chihiro finds Haku, you must immediately break out of all loops, and exit the program.
There are mazes that cannot be solved using the algorithm, but we will not test your program with any of them.
This is the code we were given.
Thank you again!!
Explanation / Answer
import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import mazewar.server.MazePacket; import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; import java.io.EOFException; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; import java.util.ArrayList; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CopyOnWriteArrayList; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static mazewar.server.MazePacket.ClientAction; import static mazewar.server.MazePacket.PacketType; /** * The entry point and glue code for the game. It also contains some helpful * global utility methods. * * @author Geoffrey Washburn <
geoffw@cis.upenn.edu> * @version $Id: Mazewar.java 371 2004-02-10 21:55:32Z geoffw $ */ public class Mazewar extends JFrame implements Runnable { /** * The default width of the {@link Maze}. */ private final int mazeWidth = 20; /** * The default height of the {@link Maze}. */ private final int mazeHeight = 10; /** * The default random seed for the {@link Maze}. * All implementations of the same protocol must use * the same seed value, or your mazes will be different. */ private long mazeSeed = 1989; /** * The {@link Maze} that the game uses. */ private Maze maze = null; /** * The {@link GUIClient} for the game. */ private GUIClient guiClient = null; /** * The panel that displays the {@link Maze}. */ private OverheadMazePanel overheadPanel = null; /** * The table the displays the scores. */ private JTable scoreTable = null; /** * Create the textpane statically so that we can * write to it globally using * the static consolePrint methods */ private static final JTextPane console = new JTextPane(); /** * Write a message to the console followed by a newline. * * @param msg The {@link String} to print. */ public static synchronized void consolePrintLn(String msg) { console.setText(console.getText() + msg + " "); } /** * Write a message to the console. * * @param msg The {@link String} to print. */ public static synchronized void consolePrint(String msg) { console.setText(console.getText() + msg); } /** * Clear the console. */ public static synchronized void clearConsole() { console.setText(""); } /** * Static method for performing cleanup before exiting the game. */ public static void quit() { // Put any network clean-up code you might have here. // (inform other implementations on the network that you have // left, etc.) System.exit(0); } /* Event Bus to implement action pub/sub */ private static EventBus eventBus; /* Socket to communicate with server */ private Socket mazeSocket; private ObjectOutputStream toServer; private ObjectInputStream fromServer; private int sequenceNumber; /* Client details */ private String clientId; private CopyOnWriteArrayList clients; /* Runnables for additional tasks */ private final int QUEUE_SIZE = 1000; public BlockingQueue packetQueue; /** * The place where all the pieces are put together. */ public Mazewar(String server, int port) { super("ECE419 Mazewar"); consolePrintLn("ECE419 Mazewar started!"); // Throw up a dialog to get the GUIClient name. clientId = JOptionPane.showInputDialog("Enter your name"); if ((clientId == null) || (clientId.length() == 0)) { Mazewar.quit(); } /* Connect to server and then add client */ MazePacket connectPacket = null, connectResponse = null; try { mazeSocket = new Socket(server, port); toServer = new ObjectOutputStream(mazeSocket.getOutputStream()); fromServer = new ObjectInputStream(mazeSocket.getInputStream()); connectPacket = new MazePacket(); connectPacket.type = PacketType.CONNECT; connectPacket.clientId = Optional.of(clientId); toServer.writeObject(connectPacket); connectResponse = (MazePacket) fromServer.readObject(); if(connectResponse.type != PacketType.CLIENTS) { System.err.println("Error: " + connectResponse.error.get().getMessage()); System.exit(1); } sequenceNumber = connectResponse.sequenceNumber.get(); mazeSeed = connectResponse.seed.get(); } catch (Exception e) { e.printStackTrace(); System.exit(1); } // Create the maze maze = new MazeImpl(new Point(mazeWidth, mazeHeight), mazeSeed); assert (maze != null); // Have the ScoreTableModel listen to the maze to find // out how to adjust scores. ScoreTableModel scoreModel = new ScoreTableModel(); assert (scoreModel != null); maze.addMazeListener(scoreModel); /* Initialize packet queue */ packetQueue = new ArrayBlockingQueue(QUEUE_SIZE); /* Inject Event Bus into Client */ Client.setEventBus(eventBus); /* Loop through clients and add to maze */ clients = new CopyOnWriteArrayList(); for(String client : connectResponse.clients.get()) { if(client.equals(clientId)) { guiClient = new GUIClient(clientId); clients.add(guiClient); maze.addClient(guiClient); eventBus.register(guiClient); } else { RemoteClient remoteClient = new RemoteClient(client); clients.add(remoteClient); maze.addClient(remoteClient); eventBus.register(remoteClient); } } checkNotNull(guiClient, "Should have received our clientId in CLIENTS list!"); // Create the GUIClient and connect it to the KeyListener queue this.addKeyListener(guiClient); // Use braces to force constructors not to be called at the beginning of the // constructor. /*{ maze.addClient(new RobotClient("Norby")); maze.addClient(new RobotClient("Robbie")); maze.addClient(new RobotClient("Clango")); maze.addClient(new RobotClient("Marvin")); }*/ // Create the panel that will display the maze. overheadPanel = new OverheadMazePanel(maze, guiClient); assert (overheadPanel != null); maze.addMazeListener(overheadPanel); // Don't allow editing the console from the GUI console.setEditable(false); console.setFocusable(false); console.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder())); // Allow the console to scroll by putting it in a scrollpane JScrollPane consoleScrollPane = new JScrollPane(console); assert (consoleScrollPane != null); consoleScrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Console")); // Create the score table scoreTable = new JTable(scoreModel); assert (scoreTable != null); scoreTable.setFocusable(false); scoreTable.setRowSelectionAllowed(false); // Allow the score table to scroll too. JScrollPane scoreScrollPane = new JScrollPane(scoreTable); assert (scoreScrollPane != null); scoreScrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Scores")); // Create the layout manager GridBagLayout layout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); getContentPane().setLayout(layout); // Define the constraints on the components. c.fill = GridBagConstraints.BOTH; c.weightx = 1.0; c.weighty = 3.0; c.gridwidth = GridBagConstraints.REMAINDER; layout.setConstraints(overheadPanel, c); c.gridwidth = GridBagConstraints.RELATIVE; c.weightx = 2.0; c.weighty = 1.0; layout.setConstraints(consoleScrollPane, c); c.gridwidth = GridBagConstraints.REMAINDER; c.weightx = 1.0; layout.setConstraints(scoreScrollPane, c); // Add the components getContentPane().add(overheadPanel); getContentPane().add(consoleScrollPane); getContentPane().add(scoreScrollPane); // Pack everything neatly. pack(); // Let the magic begin. setVisible(true); overheadPanel.repaint(); this.requestFocusInWindow(); } /** * Listen on socket for more packets from server */ @Override public void run() { try { while(!mazeSocket.isClosed()) { MazePacket packetFromServer = (MazePacket) fromServer.readObject(); assert(packetFromServer.sequenceNumber.get() == ++sequenceNumber); if(packetFromServer.type == PacketType.DISCONNECT) { if(clientId.equals(packetFromServer.clientId.get())) { eventBus.unregister(this); mazeSocket.close(); System.exit(0); } /* Search for client and remove it if isn't us */ for(int i = 0; i