basic planet wars ai issues - java

I am programming a very basic bot for planet wars in java and I cant seem to find the errors in my code. I am receiving a few different error messages but the main issue for me is the error: class, interface, or enum expected. Ive checked my brackets about a thousand times. Any help would be appreciated. Here's my bot code:
import java.util.List;
import java.util.Random;
import shared.Planet;
import shared.PlanetWars;
public class MyNewBot {
public static void doTurn(PlanetWars pw) {
// (1) If we currently have a fleet in flight, then do nothing until
// it arrives.
if (pw.myFleets().size() >= 10) {
return;
}
// (2) Pick one of my planets based on the number of ships
Planet source = null;
int largestForce = 0;
for (Planet p : pw.myPlanets()){
int force = pw.numShips();
if( force > largestForce){
largestForce = force;
source = p;
}
}
// (3) Pick a target planet at random.
Planet dest = null;
int highestGrowthRate = 0;
int shortestDistance = 9999;
for (Planet p = pw.notMyPlanets()){
int growthRate = pw.growthRate();
if( growthRate > highestGrowthRate){
highestGrowthRate = growthRate;
dest = p;
}else if (growthRate == highestGrowthRate){
int distance = pw.distance(source,p);
if (distance < shortestDistance){
shortestDistance = distance;
dest = p;
}
}
}
// (4) Send half the ships from source to destination.
if (source != null && dest != null) {
int numShips = source.numShips() / 2;
pw.issueOrder(source, dest, numShips);
}
}
// Ignore the main method unless you know what you're doing.
// Refer to the doTurn function to code your bot.
public static void main(String[] args) {
String line = "";
String message = "";
int c;
try {
while ((c = System.in.read()) >= 0) {
switch (c) {
case '\n':
if (line.equals("go")) {
PlanetWars pw = new PlanetWars(message);
doTurn(pw);
pw.finishTurn();
message = "";
} else {
message += line + "\n";
}
line = "";
break;
default:
line += (char) c;
break;
}
}
} catch (Exception e) {
// Owned.
}
}
}
and the supporting class files:
package shared;
public class Planet implements Cloneable {
private int planetID;
private int owner;
private int numShips;
private int growthRate;
private double x, y;
public Planet(int planetID, int owner, int numShips, int growthRate,
double x, double y) {
this.planetID = planetID;
this.owner = owner;
this.numShips = numShips;
this.growthRate = growthRate;
this.x = x;
this.y = y;
}
public int planetID() {
return planetID;
}
public int owner() {
return owner;
}
public int numShips() {
return numShips;
}
public int growthRate() {
return growthRate;
}
public double x() {
return x;
}
public double y() {
return y;
}
public void owner(int newOwner) {
this.owner = newOwner;
}
public void numShips(int newNumShips) {
this.numShips = newNumShips;
}
public void addShips(int amount) {
numShips += amount;
}
public void removeShips(int amount) {
numShips -= amount;
}
private Planet(Planet _p) {
planetID = _p.planetID;
owner = _p.owner;
numShips = _p.numShips;
growthRate = _p.growthRate;
x = _p.x;
y = _p.y;
}
public Object clone() {
return new Planet(this);
}
}
package shared;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
public class PlanetWars {
// Constructs a PlanetWars object instance, given a string containing a
// description of a game state.
public PlanetWars(String gameStateString) {
planets = new ArrayList<Planet>();
fleets = new ArrayList<Fleet>();
parseGameState(gameStateString);
}
// Returns the number of planets. Planets are numbered starting with 0.
public int numPlanets() {
return planets.size();
}
// Returns the planet with the given planet_id. There are NumPlanets()
// planets. They are numbered starting at 0.
public Planet getPlanet(int planetID) {
return planets.get(planetID);
}
// Returns the number of fleets.
public int numFleets() {
return fleets.size();
}
// Returns the fleet with the given fleet_id. Fleets are numbered starting
// with 0. There are NumFleets() fleets. fleet_id's are not consistent from
// one turn to the next.
public Fleet getFleet(int fleetID) {
return fleets.get(fleetID);
}
// Returns a list of all the planets.
public List<Planet> planets() {
return planets;
}
// Return a list of all the planets owned by the current player. By
// convention, the current player is always player number 1.
public List<Planet> myPlanets() {
List<Planet> r = new ArrayList<Planet>();
for (Planet p : planets) {
if (p.owner() == 1) {
r.add(p);
}
}
return r;
}
// Return a list of all neutral planets.
public List<Planet> neutralPlanets() {
List<Planet> r = new ArrayList<Planet>();
for (Planet p : planets) {
if (p.owner() == 0) {
r.add(p);
}
}
return r;
}
// Return a list of all the planets owned by rival players. This excludes
// planets owned by the current player, as well as neutral planets.
public List<Planet> enemyPlanets() {
List<Planet> r = new ArrayList<Planet>();
for (Planet p : planets) {
if (p.owner() >= 2) {
r.add(p);
}
}
return r;
}
// Return a list of all the planets that are not owned by the current
// player. This includes all enemy planets and neutral planets.
public List<Planet> notMyPlanets() {
List<Planet> r = new ArrayList<Planet>();
for (Planet p : planets) {
if (p.owner() != 1) {
r.add(p);
}
}
return r;
}
// Return a list of all the fleets.
public List<Fleet> fleets() {
List<Fleet> r = new ArrayList<Fleet>();
for (Fleet f : fleets) {
r.add(f);
}
return r;
}
// Return a list of all the fleets owned by the current player.
public List<Fleet> myFleets() {
List<Fleet> r = new ArrayList<Fleet>();
for (Fleet f : fleets) {
if (f.owner() == 1) {
r.add(f);
}
}
return r;
}
// Return a list of all the fleets owned by enemy players.
public List<Fleet> enemyFleets() {
List<Fleet> r = new ArrayList<Fleet>();
for (Fleet f : fleets) {
if (f.owner() != 1) {
r.add(f);
}
}
return r;
}
// Returns the distance between two planets, rounded up to the next highest
// integer. This is the number of discrete time steps it takes to get
// between the two planets.
public int distance(int sourcePlanet, int destinationPlanet) {
Planet source = planets.get(sourcePlanet);
Planet destination = planets.get(destinationPlanet);
double dx = source.x() - destination.x();
double dy = source.y() - destination.y();
return (int) Math.ceil(Math.sqrt(dx * dx + dy * dy));
}
// Returns the distance between two planets, rounded up to the next highest
// integer. This is the number of discrete time steps it takes to get
// between the two planets.
public int distance(Planet source, Planet destination) {
double dx = source.x() - destination.x();
double dy = source.y() - destination.y();
return (int) Math.ceil(Math.sqrt(dx * dx + dy * dy));
}
// Sends an order to the game engine. An order is composed of a source
// planet number, a destination planet number, and a number of ships. A
// few things to keep in mind:
// * you can issue many orders per turn if you like.
// * the planets are numbered starting at zero, not one.
// * you must own the source planet. If you break this rule, the game
// engine kicks your bot out of the game instantly.
// * you can't move more ships than are currently on the source planet.
// * the ships will take a few turns to reach their destination. Travel
// is not instant. See the Distance() function for more info.
public void issueOrder(int sourcePlanet, int destinationPlanet, int
numShips) {
System.out.println("" + sourcePlanet + " " + destinationPlanet + " "
+ numShips);
System.out.flush();
}
// Sends an order to the game engine. An order is composed of a source
// planet number, a destination planet number, and a number of ships. A
// few things to keep in mind:
// * you can issue many orders per turn if you like.
// * the planets are numbered starting at zero, not one.
// * you must own the source planet. If you break this rule, the game
// engine kicks your bot out of the game instantly.
// * you can't move more ships than are currently on the source planet.
// * the ships will take a few turns to reach their destination. Travel
// is not instant. See the Distance() function for more info.
public void issueOrder(Planet source, Planet dest, int numShips) {
System.out.println("" + source.planetID() + " " + dest.planetID() + " "
+ numShips);
System.out.flush();
}
// Sends the game engine a message to let it know that we're done sending
// orders. This signifies the end of our turn.
public void finishTurn() {
System.out.println("go");
System.out.flush();
}
// Returns true if the named player owns at least one planet or fleet.
// Otherwise, the player is deemed to be dead and false is returned.
public boolean isAlive(int playerID) {
for (Planet p : planets) {
if (p.owner() == playerID) {
return true;
}
}
for (Fleet f : fleets) {
if (f.owner() == playerID) {
return true;
}
}
return false;
}
// If the game is not yet over (ie: at least two players have planets or
// fleets remaining), returns -1. If the game is over (ie: only one player
// is left) then that player's number is returned. If there are no
// remaining players, then the game is a draw and 0 is returned.
public int winner() {
Set<Integer> remainingPlayers = new TreeSet<Integer>();
for (Planet p : planets) {
remainingPlayers.add(p.owner());
}
for (Fleet f : fleets) {
remainingPlayers.add(f.owner());
}
switch (remainingPlayers.size()) {
case 0:
return 0;
case 1:
return ((Integer) remainingPlayers.toArray()[0]).intValue();
default:
return -1;
}
}
// Returns the number of ships that the current player has, either located
// on planets or in flight.
public int numShips(int playerID) {
int numShips = 0;
for (Planet p : planets) {
if (p.owner() == playerID) {
numShips += p.numShips();
}
}
for (Fleet f : fleets) {
if (f.owner() == playerID) {
numShips += f.numShips();
}
}
return numShips;
}
// Returns the production of the given player.
public int production(int playerID) {
int prod = 0;
for (Planet p : planets) {
if (p.owner() == playerID) {
prod += p.growthRate();
}
}
return prod;
}
// Parses a game state from a string. On success, returns 1. On failure,
// returns 0.
private int parseGameState(String s) {
planets.clear();
fleets.clear();
int planetID = 0;
String[] lines = s.split("\n");
for (int i = 0; i < lines.length; ++i) {
String line = lines[i];
int commentBegin = line.indexOf('#');
if (commentBegin >= 0) {
line = line.substring(0, commentBegin);
}
if (line.trim().length() == 0) {
continue;
}
String[] tokens = line.split(" ");
if (tokens.length == 0) {
continue;
}
if (tokens[0].equals("P")) {
if (tokens.length != 6) {
return 0;
}
double x = Double.parseDouble(tokens[1]);
double y = Double.parseDouble(tokens[2]);
int owner = Integer.parseInt(tokens[3]);
int numShips = Integer.parseInt(tokens[4]);
int growthRate = Integer.parseInt(tokens[5]);
Planet p = new Planet(planetID++, owner, numShips, growthRate,
x, y);
planets.add(p);
} else if (tokens[0].equals("F")) {
if (tokens.length != 7) {
return 0;
}
int owner = Integer.parseInt(tokens[1]);
int numShips = Integer.parseInt(tokens[2]);
int source = Integer.parseInt(tokens[3]);
int destination = Integer.parseInt(tokens[4]);
int totalTripLength = Integer.parseInt(tokens[5]);
int turnsRemaining = Integer.parseInt(tokens[6]);
Fleet f = new Fleet(owner, numShips, source, destination,
totalTripLength, turnsRemaining);
fleets.add(f);
} else {
return 0;
}
}
return 1;
}
// Store all the planets and fleets. OMG we wouldn't wanna lose all the
// planets and fleets, would we!?
private ArrayList<Planet> planets;
private ArrayList<Fleet> fleets;
}
package shared;
public class Fleet implements Comparable<Fleet>, Cloneable {
private int owner;
private int numShips;
private int sourcePlanet;
private int destinationPlanet;
private int totalTripLength;
private int turnsRemaining;
public Fleet(int owner, int numShips, int sourcePlanet,
int destinationPlanet, int totalTripLength, int turnsRemaining) {
this.owner = owner;
this.numShips = numShips;
this.sourcePlanet = sourcePlanet;
this.destinationPlanet = destinationPlanet;
this.totalTripLength = totalTripLength;
this.turnsRemaining = turnsRemaining;
}
public Fleet(int owner, int numShips) {
this.owner = owner;
this.numShips = numShips;
this.sourcePlanet = -1;
this.destinationPlanet = -1;
this.totalTripLength = -1;
this.turnsRemaining = -1;
}
public int owner() {
return owner;
}
public int numShips() {
return numShips;
}
public int sourcePlanet() {
return sourcePlanet;
}
public int destinationPlanet() {
return destinationPlanet;
}
public int totalTripLength() {
return totalTripLength;
}
public int turnsRemaining() {
return turnsRemaining;
}
public void removeShips(int amount) {
numShips -= amount;
}
// Subtracts one turn remaining. Call this function to make the fleet get
// one turn closer to its destination.
public void TimeStep() {
if (turnsRemaining > 0) {
--turnsRemaining;
} else {
turnsRemaining = 0;
}
}
#Override
public int compareTo(Fleet f) {
return this.numShips - f.numShips;
}
private Fleet(Fleet _f) {
owner = _f.owner;
numShips = _f.numShips;
sourcePlanet = _f.sourcePlanet;
destinationPlanet = _f.destinationPlanet;
totalTripLength = _f.totalTripLength;
turnsRemaining = _f.turnsRemaining;
}
public Object clone() {
return new Fleet(this);
}
}

for (Planet p = pw.notMyPlanets()){ should be for (Planet p : pw.notMyPlanets()){.
You've not posted the Fleet class, so as it is the code won't compile for me. However, the above is the only other error I could see.

Related

How to use array of objects in this context?

Assuming that the array is populated with 20 shipments, calculate the total cost of local shipments in the array.
I tried to create a for loop and then call out the method calcCost() and += it to the variable local so it would save the values I guess
I'm pretty sure the way I wrote the code is wrong so if someone could help me with it that would be great!
package question;
public class TestShipment {
public static void main(String[] args) {
Shipment r1 = new Shipment(
new Parcel("scientific calculator " , 250),
new Address("Dubai","05512345678"),
new Address("Dubai","0505432123"),
"Salim"
);
System.out.println(r1);
Shipment[] arr = new Shipment[100];
arr[5] = r1;
Shipment[] a = new Shipment[20];
double local = 0;
for (int i = 0; i < a.length; i++) {
if (a[i].isLocalShipment()) {
System.out.println(a[i].calcCost());
}
}
}
}
public class Shipment {
public Parcel item;
private Address fromAddress;
private Address toAddress;
public String senderName;
public Shipment(Parcel i, Address f, Address t, String name) {
item = i;
fromAddress = f;
toAddress = t;
senderName = name;
}
//setter
public void setFromAddress(String c, String p) {
c = fromAddress.getCity();
p = fromAddress.getPhone();
}
public boolean isLocalShipment() {
boolean v = false;
if (fromAddress.getCity() == toAddress.getCity()) {
v = true;
} else {
v = false;
}
return v;
}
public double calcCost() {
double cost = 0;
if (fromAddress.getCity() == toAddress.getCity()) {
cost = 5;
} else {
cost = 15;
}
if(item.weight > 0 && item.weight <= 200) {
cost += 5.5;
}
if(item.weight > 200) {
cost += 10.5;
}
return cost = cost * (1 + 0.5); //fix the tax
}
public String toString() {
return "From: " + senderName + "\nTo: " + toAddress
+ "\nParcel: " + item.desc+item.weight + "\ncost: " + calcCost();
}
}

MiniMax chess algoritm returns bad moves

I'm having problems with my implementation of the MiniMax algoritm for my chess game. Most parts of it seems to work, but it either never makes the good moves or something is wrong with the evaluation (score based of both players active pieces) of them.
For example if I set up check (fool's mate for example) the ai does something random instead of killing the king. I really can't pin out what I'm doing wrong.
The class that evaluates the board, StandardBoardEvaluator, seems to work after some testing, so the problem is most likely somewhere within the MiniMax implementation. The game is made up from a class Board, which has and 2D array with 8x8 objects of my own class Square, which in itself has a reference to an Piece (that can be null, or any of the typical chess pieces).
In the algoritm i constantly makes new Board instances as going down the searchthree, which is why i made these "deep clone" constructors in Board and Square, so that does not seem to be the problem. Like this:
public Board(Board originalBoard) {
this.turnIsWhite = originalBoard.getTurnIsWhite();
winner = null;
squares = new Square[8][8];
for (int rank=0; rank<squares.length; rank++) {
for(int file=0; file<squares[rank].length; file++) {
squares[rank][file] = new Square(originalBoard.getSquare(posStringFromFileRank(rank, file)));
}
}
}
AND
public Square(Square originalSquare) {
this.pos = new String(originalSquare.getPos());
this.piece = originalSquare.getPiece();
}
I have an typical command class, MovePiece, for moving pieces. This uses another class, MoveCheck, to check if the move command is legal. MovePiece returns a boolean representing if the move is legal. Both these classes have been heavily tested and are working, so I don't think the problem is within these classes.
Here is the algoritm:
public class MiniMax implements MoveStrategy{
BoardEveluator bV;
MoveGenerator mGen;
int depth;
public MiniMax(int depth){
bV = new StandardBoardEvaluator();
mGen = new MoveGenerator();
this.depth = depth;
}
#Override
public MovePiece execute(Board board) {
MovePiece bestMove = null;
int lowestValue = Integer.MAX_VALUE;
int highestValue = Integer.MIN_VALUE;
int currentValue = 0;
String color = (board.getTurnIsWhite() ? "white" : "black");
System.out.println(color + " is evaluation best move with MiniMax depth " + depth);
List<MovePiece> allPossibleMoves = mGen.getLegalMoves(board, board.getTurnIsWhite());
for (MovePiece mp : allPossibleMoves){
Board tempBoard = new Board(board);
mp.setBoard(tempBoard);
if (mp.execute()){
currentValue = tempBoard.getTurnIsWhite() ? min(tempBoard, depth -1) : max(tempBoard, depth -1);
if (board.getTurnIsWhite() && currentValue >= highestValue){
highestValue = currentValue;
bestMove = mp;
}
else if (!board.getTurnIsWhite() && currentValue <= lowestValue){
lowestValue = currentValue;
bestMove = mp;
}
mp.unexecute();
}
}
return bestMove;
}
int min (Board board, int depth){
if (depth == 0 || board.getWinner() != null){
return bV.eveluate(board);
}
int lowestValue = Integer.MAX_VALUE;
List<MovePiece> legalMoves = mGen.getLegalMoves(board, board.getTurnIsWhite());
for (MovePiece mp : legalMoves){
Board tempBoard = new Board(board);
mp.setBoard(tempBoard);
if (mp.execute()){
int currentValue = max(tempBoard, depth - 1);
if (currentValue <= lowestValue){
lowestValue = currentValue;
}
mp.unexecute();
}
}
return lowestValue;
}
int max (Board board, int depth){
if (depth == 0 || board.getWinner() != null){
return bV.eveluate(board);
}
int highestValue = Integer.MIN_VALUE;
List<MovePiece> legalMoves = mGen.getLegalMoves(board, board.getTurnIsWhite());
for (MovePiece mp : legalMoves){
Board tempBoard = new Board(board);
mp.setBoard(tempBoard);
if (mp.execute()){
int currentValue = min(tempBoard, depth - 1);
if (currentValue >= highestValue){
highestValue = currentValue;
}
mp.unexecute();
}
}
return highestValue;
}
And the evalutor class
public class StandardBoardEvaluator implements BoardEveluator {
private int scorePlayer(Board board, boolean isWhite){
return pieceValue(board, isWhite) + mobolity(isWhite, board);
}
private int mobolity(boolean isWhite, Board board){
return (int) (board.getActiveSquares(isWhite).size() * 1.5);
}
private static int pieceValue(Board board, boolean isWhite){
int piceValueScore = 0;
for (Square square : board.getActiveSquares(isWhite)){
piceValueScore += square.getPiece().getPieceValue();
}
return piceValueScore;
}
#Override
public int eveluate(Board board) {
return scorePlayer(board, true) - scorePlayer(board, false);
}
}
Here is the MovePiece class:
private Square from;
private Square to;
private Board board;
private MoveCheck mCheck;
private RulesCheck rCheck;
private boolean done = false;
private Piece killed;
public MovePiece(Board board, String from, String to) {
this.board = board;
this.from = board.getSquare(from);
this.to = board.getSquare(to);
mCheck = new MoveCheck();
}
public MovePiece(Board board, Square from, Square to) {
this.board = board;
this.from = from;
this.to = to;
mCheck = new MoveCheck();
rCheck = new RulesCheck(board);
}
public void setBoard(Board board) {
this.board = board;
}
public Board getBoard() {
return board;
}
public Square getFrom() {
return from;
}
public Square getTo() {
return to;
}
public void setFrom(Square from) {
this.from = from;
}
public void setTo(Square to) {
this.to = to;
}
public void setFrom(String from) {
this.from = board.getSquare(from);
}
public void setTo(String to) {
this.to = board.getSquare(to);
}
#Override
public boolean execute() {
rCheck = new RulesCheck(board);
if (done) {
board.movePiece(from, to);
return true;
}
else if (mCheck.isLegal(board, from, to)){
if (to.getPiece() != null) {
killed = to.getPiece();
rCheck.winCheck(killed);
}
board.setGameOutput("Moved " + from.pieceToString() + " at " + from.getPos() + " - to " + to.getPos() + "(" + to.pieceToString() + ")");
board.movePiece(from, to);
rCheck.checkPromotion(to);
done = true;
return true;
}
return false;
}
#Override
public void unexecute() {
if (to.getPiece().getClass() == Pawn.class)
((Pawn) to.getPiece()).decreaseMoves();
board.movePiece(to, from);
if (killed != null) {
to.setPiece(killed);
}
}
The MoveCheck class merely looks if the move is legal for the piece (path is clear, target is an enemy or empty and so on), don't think it's relevant for my problem since the code is tested and works.
The piece value is declared as an int in the subclasses (all the types of pieces) of the abstract class Piece. 100 points for a pawn, 300 for bishop and knight, 500 for rook, 900 for queen and 10 000 for the king.
If anyone could help me figure out the problem i would be eternally grateful! Please let me know if you need to se some other code i haven't showed.
You haven't shared the MovePiece implementation neither the main game loop, but I indentified two possible problems inside MiniMax.execute method:
currentValue = tempBoard.getTurnIsWhite() ? min(tempBoard, depth -1) : max(tempBoard, depth -1)
According to the above code, you are assuming that the MinMax player will always be black, as it evaluates min for white and max for black. For a generic algorithm this is a wrong assumption, don't know if it works for you though.
Second thing is after calling mp.execute() and assigning bestMove = mp you call mp.unexecute(), so effectively call bestMove.unexecute() since the variables point to the same object.
Please consider the suggestions above and if it does not fix the problem, share the abovementioned implementation pieces.

How do I configure this Java method connected to several classes that all get more specific?

All of the program's templates. This was a past assignment but at this point, I'm just trying to understand what's going on.
Under the Apartment class, I'm confused on how to correctly return an array of window orders for one unit, all units, and then the #Override method under ThreeBedroom.
Just for reference of what I've done so far (probably not all correct):
public class Window {
private final int width, height;
public Window(int width, int height) {
this.width = width;
this.height = height;
}
// print text like: 4 X 6 window
public String toString() {
String s = "";
s = width + " x " + height + " window";
return s;
}
// compare window objects by their dimensions
public boolean equals(Object that) {
if (that instanceof Window) {
Window w = (Window) that;
return this.width == w.width && this.height == w.height;
}
else { return false; }
}
}
class WindowOrder {
final Window window; // window description (its width and height)
int num; // number of windows for this order
WindowOrder(Window window, int num) {
this.window = window;
this.num = num;
}
// add the num field of the parameter to the num field of this object
//
// BUT
//
// do the merging only of two windows have the same size
// do nothing if the size does not match
//
// return the current object
WindowOrder add(WindowOrder order) {
if (order.equals(window)) {
this.num -= num;
return order;
}
else {
return order;
}
}
// update the num field of this object by multiplying it with the parameter
// and then return the current object
WindowOrder times(int number) {
WindowOrder window = new WindowOrder(this.window, this.num);
this.num *= number;
return window;
}
// print text like: 20 4 X 6 window
#Override
public String toString() {
String s = "";
s = num + " " + window.toString();
return s;
}
// Two orders are equal if they contain the same number of windows of the same size.
#Override
public boolean equals(Object that) {
if (that instanceof WindowOrder) {
WindowOrder order = (WindowOrder) that;
return this.num == order.num && this.window == order.window;
}
else { return false; }
}
}
public class Room {
Window window;
int numOfWindows;
Room(Window window, int numOfWindows) {
this.window = window;
this.numOfWindows = numOfWindows;
}
WindowOrder order() {
return new WindowOrder(window, numOfWindows);
}
// Print text like: 5 (6 X 8 window)
#Override
public String toString() {
String s = "";
s = numOfWindows + " (" + window.toString() + ")";
return s;
}
// Two rooms are equal if they contain the same number of windows of the same size
#Override
public boolean equals(Object that) {
if (that instanceof Room) {
Room room = (Room) that;
return this.window == room.window && this.numOfWindows == room.numOfWindows;
}
else { return false; }
}
}
class MasterBedroom extends Room {
MasterBedroom() {
super(new Window(4, 6), 3);
}
// Call parent's toString method
//
// return text like: Master bedroom: 3 (4 X 6 window)
#Override
public String toString() {
String s = "";
s = "Master bedroom: " + numOfWindows + " " + window.toString();
return s;
}
}
class GuestRoom extends Room {
GuestRoom() {
super(new Window(5, 6), 2);
}
// Call parent's toString method
//
// return text like: Guest room: 2 (5 X 6 window)
#Override
public String toString() {
String s = "";
s = "Guest room: " + numOfWindows + " " + window.toString();
return s;
}
}
class LivingRoom extends Room {
LivingRoom() {
super(new Window(6, 8), 5);
}
// Call parent's toString method
//
// return text like: Living room: 5 (6 X 8 window)
#Override
public String toString() {
String s = "";
s = "Living room: " + numOfWindows + " " + window.toString();
return s;
}
}
For Apartment's orderForOneUnit() method, I wrote this, but it seems to simplistic and I feel like I should be using a for loop..
WindowOrder[] orderForOneUnit() {
WindowOrder[] order = new WindowOrder[rooms.length];
return order;
}
Am I even close to correctly understanding this? What should be under the Apartment methods?
Didn't looks at the templates but from what you've provided, you're close. All you've done so far is create a WindowOrder[] array of length rooms. You need to add new WindowOrder(desc, num) to these arrays before return order;
/**
* All apartment rooms have the same number of windows, with the
* same size window for each of those.
*/
public class Apartment
{
private int numRooms_;
private int windowsPerRoom_;
private Window window_;
/**
* Constructor
*/
public Apartment(numRooms, windowsPerRoom, desiredWindowHeight, desiredWindowLength)
{
numRooms_ = numRooms;
windowsPerRoom_ = windowsPerRoom;
window_ = new Window(desiredWindowHeight, desiredWindowLenght);
}
/**
* Orders for one room in apartment
*/
public WindowOrder orderForOneUnit()
{
WindowOrder order = new WindowOrder(window_, 1);
return order;
}
/**
* Orders for all rooms in apartment
*/
public List<WindowOrder> orderForAllUnits()
{
List<WindowOrder> orders = new ArrayList<WindowOrder>();
WindowOrder order;
for(i=0; i<numRooms_; i++)
{
orders.add(new WindowOrder(window_, windowsPerRoom_);
}
return orders;
}
}
Now when you're in your code and you're ready for a new Apartment(x, x, x, x) you can do the following (I'll assume you're just in main())
public class ApartmentComplex
{
public static void main(String[] args)
{
int numWindowsPerRoom = 3;
int desiredWindowHeight = 10;
int desiredWindowWidth = 10;
int numRooms = 5;
Apartment aptWithFiveRooms = new Apartment(numRooms, numWindowsPerRoom, desiredWindowHeight, desiredWindowWidth);
WindowOrder singleSingleOrder = apt.orderForOneUnit();
List<WindowOrder> allRoomsOrder = apt.orderForAllUnits();
numRooms = 3;
Apartment aptWithThreeRooms = new Apartment(numRooms, numWindowsPerRoom, desiredWindowHeight, desiredWindowWidth);
List<WindowOrder> threeRoomsOrder = apt.orderForAllUnits();
}
}
You do need a for loop. At the moment you are returning an Array where each entry in the array is null.
Here is an example of filling an array:
for (int i = 0; i < array.length; i++) { // iterate over an array
array[i] = getValueFor(i); // put value in the array
}

match and delete elements in arraylists

I am making a robot maze where the robot reaches a target automatically without crashing into walls. I want the robot to do the maze once, learn the correct route and then the second time be able to get there straight away without going to any deadends. I thought I could do this by making three arraylists.
One for all the squares the robot visits.
Two for all the squares that lead to a deadend.
Three for all the directions the robot goes.
If the squares that lead to a dead end are found in the first arraylist then i can delete the same indexes in the third arraylist. That way, the second time, i can just iterate the third Arraylist.
My full code is below:
import java.util.ArrayList;
import java.util.*;
import java.util.Iterator;
import java.util.stream.IntStream;
public class Explorer {
private int pollRun = 0; // Incremented after each pass.
private RobotData robotData; // Data store for junctions.
private ArrayList<Integer> nonWallDirections;
private ArrayList<Integer> passageDirections;
private ArrayList<Integer> beenbeforeDirections;
private Random random = new Random();
int [] directions = {IRobot.AHEAD, IRobot.LEFT, IRobot.RIGHT, IRobot.BEHIND};
private ArrayList<Square> correctSquares;
private ArrayList<Square> wrongSquares;
private ArrayList<Integer> correctDirections;
public void controlRobot (IRobot robot) {
// On the first move of the first run of a new maze.
if ((robot.getRuns() == 0) && (pollRun ==0))
robotData = new RobotData();
pollRun++; /* Increment poll run so that the data is not reset
each time the robot moves. */
int exits = nonwallExits(robot);
int direction;
if ((robot.getRuns() != 0))
direction = grandfinale(robot);
nonWallDirections = new ArrayList<Integer>();
passageDirections = new ArrayList<Integer>();
beenbeforeDirections = new ArrayList<Integer>();
correctSquares = new ArrayList<Square>();
correctDirections = new ArrayList<Integer>();
// Adding each direction to the appropriate state ArrayList.
for(int item : directions) {
if(robot.look(item) != IRobot.WALL) {
nonWallDirections.add(item);
}
}
for(int item : directions) {
if(robot.look(item) == IRobot.PASSAGE) {
passageDirections.add(item);
}
}
for(int item : directions) {
if(robot.look(item) == IRobot.BEENBEFORE) {
beenbeforeDirections.add(item);
}
}
// Calling the appropriate method depending on the number of exits.
if (exits < 2) {
direction = deadEnd(robot);
} else if (exits == 2) {
direction = corridor(robot);
} else {
direction = junction(robot);
robotData.addJunction(robot);
robotData.printJunction(robot);
}
robot.face(direction);
addcorrectSquares(robot);
correctDirections.add(direction);
}
/* The specification advised to have to seperate controls: Explorer and Backtrack
and a variable explorerMode to switch between them.
Instead, whenever needed I shall call this backtrack method.
If at a junction, the robot will head back the junction as to when it first approached it.
When at a deadend or corridor, it will follow the beenbefore squares until it
reaches an unexplored path. */
public int backtrack (IRobot robot) {
if (nonwallExits(robot) > 2) {
addwrongSquares(robot);
return robotData.reverseHeading(robot);
} else {
do {
addwrongSquares(robot);
return nonWallDirections.get(0);
} while (nonwallExits(robot) == 1);
}
}
// Deadend method makes the robot follow the only nonwall exit.
public int deadEnd (IRobot robot) {
return backtrack(robot);
}
/* Corridor method will make the robot follow the one and only passage.
The exception is at the start. Sometimes, the robot will start with
two passages available to it in which case it will choose one randomly.
If there is no passage, it will follow the beenbefore squares
until it reaches an unexplored path.*/
public int corridor (IRobot robot) {
if (passageExits(robot) == 1) {
return passageDirections.get(0);
} else if (passageExits(robot) == 2) {
int randomPassage = random.nextInt(passageDirections.size());
return passageDirections.get(randomPassage);
} else {
return backtrack(robot);
}
}
/* Junction method states if there is more than one passage, it will randomly select one.
This applies to crossroads as well as essentially they are the same.
If there is no passage, it will follow the beenbefore squares until it reaches an unexplored
path. */
public int junction(IRobot robot) {
if (passageExits(robot) == 1) {
return passageDirections.get(0);
} else if (passageExits(robot) > 1) {
int randomPassage = random.nextInt(passageDirections.size());
return passageDirections.get(randomPassage);
} else {
return backtrack(robot);
}
}
// Calculates number of exits.
private int nonwallExits (IRobot robot) {
int nonwallExits = 0;
for(int item : directions) {
if(robot.look(item) != IRobot.WALL) {
nonwallExits++;
}
}
return nonwallExits;
}
// Calculates number of passages.
private int passageExits (IRobot robot) {
int passageExits = 0;
for(int item : directions) {
if(robot.look(item) == IRobot.PASSAGE) {
passageExits++;
}
}
return passageExits;
}
// Calculates number of beenbefores.
private int beenbeforeExits (IRobot robot) {
int beenbeforeExits = 0;
for(int item : directions) {
if(robot.look(item) == IRobot.PASSAGE) {
beenbeforeExits++;
}
}
return beenbeforeExits;
}
// Resets Junction Counter in RobotData class.
public int reset() {
return robotData.resetJunctionCounter();
}
public void addcorrectSquares(IRobot robot) {
Square newSquare = new Square(robot.getLocation().x, robot.getLocation().y);
correctSquares.add(newSquare);
}
public void addwrongSquares(IRobot robot) {
Square badSquare = new Square(robot.getLocation().x, robot.getLocation().y);
wrongSquares.add(badSquare);
}
public int grandfinale (IRobot robot) {
IntStream.range(0, correctSquares.size())
.map(index -> correctSquares.size() - index - 1)
.filter(index -> (((wrongSquares.x).contains(correctSquares.x)) && ((wrongSquares.y).contains(correctSquares.y))).get(index))
.forEach(index -> correctDirections.remove(index));
Iterator<Integer> routeIterator = correctDirections.iterator();
while (routeIterator.hasNext()) {
break;
}
return (routeIterator.next());
}
}
class RobotData {
/* It was advised in the specification to include the variable:
private static int maxJunctions = 10000;
However, as I am not using arrays, but ArrayLists, I do not
need this. */
private static int junctionCounter = 0;
private ArrayList<Junction> junctionList = new ArrayList<Junction>();
// Resets the Junction counter.
public int resetJunctionCounter() {
return junctionCounter = 0;
}
// Adds the current junction to the list of arrays.
public void addJunction(IRobot robot) {
Junction newJunction = new Junction(robot.getLocation().x, robot.getLocation().y, robot.getHeading());
junctionList.add(newJunction);
junctionCounter++;
}
// Gets the junction counter for Junction info method in Junction class.
public int getJunctionCounter (IRobot robot) {
return junctionCounter;
}
// Prints Junction info.
public void printJunction(IRobot robot) {
String course = "";
switch (robot.getHeading()) {
case IRobot.NORTH:
course = "NORTH";
break;
case IRobot.EAST:
course = "EAST";
break;
case IRobot.SOUTH:
course = "SOUTH";
break;
case IRobot.WEST:
course = "WEST";
break;
}
System.out.println("Junction " + junctionCounter + " (x=" + robot.getLocation().x + ", y=" + robot.getLocation().y +") heading " + course);
}
/* Iterates through the junction arrayList to find the
heading of the robot when it first approached the junction.
It does this by finding the first junction in the ArrayList
that has the same x and y coordinates as the robot.*/
public int searchJunction(IRobot robot) {
Junction currentJunction = null;
Iterator<Junction> junctionIterator = junctionList.iterator();
while (junctionIterator.hasNext()) {
currentJunction = junctionIterator.next();
if ((((currentJunction.x)==(robot.getLocation().x))) && ((currentJunction.y)==(robot.getLocation().y)))
break;
}
return currentJunction.arrived;
}
// Returns the reverse of the heading the robot had when first approaching the junction.
public int reverseHeading(IRobot robot) {
int firstHeading = searchJunction(robot);
int reverseHeading = 1; // Random integer to Iniitalise variable.
switch (firstHeading) {
case IRobot.NORTH:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.BEHIND;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.RIGHT;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.AHEAD;
else
reverseHeading = IRobot.LEFT;
break;
case IRobot.EAST:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.LEFT;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.BEHIND;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.RIGHT;
else
reverseHeading = IRobot.AHEAD;
break;
case IRobot.SOUTH:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.AHEAD;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.LEFT;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.BEHIND;
else
reverseHeading = IRobot.RIGHT;
break;
case IRobot.WEST:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.RIGHT;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.AHEAD;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.LEFT;
else
reverseHeading = IRobot.BEHIND;
break;
}
return reverseHeading;
}
}
class Junction {
int x;
int y;
int arrived;
public Junction(int xcoord, int ycoord, int course) {
x = xcoord;
y = ycoord;
arrived = course;
}
}
class Square {
int x;
int y;
public Square(int cordx, int cordy){
x = cordx;
y = cordy;
}
}
IntStream.range(0, al1.length)
.filter(index -> al2.contains(al1.get(index)))
.forEach(index -> al3.remove(index));
Slightly more complex than this if removing elements from al3 shifts them left but in that case just reverse the stream before the .filter- then it will delete from the end. The easiest way to do that is:
.map(index -> al1.length - index - 1)
Without Streams the equivalent would be
for (int i = 0; i < al1.length; i++) {
if (al2.contains(al1.get(i))) {
al3.remove(i);
}
}
Similarly, if you need to delete from the right then the for loop would need to count down rather than up.
Without further details on arraylist structure it's hard to give any more hints.

Java help! implementing a 2d array of a certain object, the object has multiple private data types and objects

I'm trying to make a 2d array of an object in java. This object in java has several private variables and methods in it, but won't work. Can someone tell me why and is there a way I can fix this?
This is the exeception I keep getting for each line of code where I try to initialize and iterate through my 2d object.
"Exception in thread "main" java.lang.NullPointerException
at wumpusworld.WumpusWorldGame.main(WumpusWorldGame.java:50)
Java Result: 1"
Here is my main class:
public class WumpusWorldGame {
class Agent {
private boolean safe;
private boolean stench;
private boolean breeze;
public Agent() {
safe = false;
stench = false;
breeze = false;
}
}
/**
* #param args
* the command line arguments
* #throws java.lang.Exception
*/
public static void main(String [] args) {
// WumpusFrame blah =new WumpusFrame();
// blah.setVisible(true);
Scanner input = new Scanner(System.in);
int agentpts = 0;
System.out.println("Welcome to Wumpus World!\n ******************************************** \n");
//ArrayList<ArrayList<WumpusWorld>> woah = new ArrayList<ArrayList<WumpusWorld>>();
for (int i = 0 ; i < 5 ; i++) {
WumpusWorldObject [] [] woah = new WumpusWorldObject [5] [5];
System.out.println( "*********************************\n Please enter the exact coordinates of the wumpus (r and c).");
int wumpusR = input.nextInt();
int wumpusC = input.nextInt();
woah[wumpusR][wumpusC].setPoints(-3000);
woah[wumpusR][wumpusC].setWumpus();
if ((wumpusR <= 5 || wumpusC <= 5) && (wumpusR >= 0 || wumpusC >= 0)) {
woah[wumpusR][wumpusC].setStench();
}
if (wumpusC != 0) {
woah[wumpusR][wumpusC - 1].getStench();
}
if (wumpusR != 0) {
woah[wumpusR - 1][wumpusC].setStench();
}
if (wumpusC != 4) {
woah[wumpusR][wumpusC + 1].setStench();
}
if (wumpusR != 4) {
woah[wumpusR + 1][wumpusC].setStench();
}
System.out.println( "**************************************\n Please enter the exact coordinates of the Gold(r and c).");
int goldR = input.nextInt();
int goldC = input.nextInt();
woah[goldR][goldC].setGold();
System.out.println("***************************************\n How many pits would you like in your wumpus world?");
int numPits = input.nextInt();
for (int k = 0 ; k < numPits ; k++) {
System.out.println("Enter the row location of the pit");
int r = input.nextInt();
System.out.println("Enter the column location of the pit");
int c = input.nextInt();
woah[r][c].setPit();
if ((r <= 4 || c <= 4) && (r >= 0 || c >= 0)) {
woah[r][c].setBreeze();
}
if (c != 0) {
woah[r][c - 1].setBreeze();
}
if (r != 0) {
woah[r - 1][c].setBreeze();
}
if (c != 4) {
woah[r][c + 1].setBreeze();
}
if (r != 4) {
woah[r + 1][c].setBreeze();
}
}
for (int x = 0 ; x < 4 ; x++) {
int j = 0;
while (j < 4) {
agentpts = agentpts + woah[x][j].getPoints();
Agent [] [] k = new Agent [4] [4];
if (woah[x][j].getWumpus() == true) {
agentpts = agentpts + woah[x][j].getPoints();
System.out.println("You just got ate by the wumpus!!! THE HORROR!! Your score is " + agentpts);
}
if (woah[x][j].getStench() == true) {
k[x][j].stench = true;
System.out.println("You smell something funny... smells like old person.");
}
if (woah[x][j].getBreeze() == true) {
k[x][j].breeze = true;
System.out.println("You hear a breeze. yeah");
}
if (woah[x][j].getPit() == true) {
agentpts = agentpts + woah[x][j].getPoints();
System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH! you dumb bith, your dead now.");
}
// if breeze or stench, if breeze and stench, if nothing, etc then move.
k[x][j].safe = true;
// if(k[i][j].isSafe()!=true){
// } else { }
}
}
}
}
}
Here is my class object that I'm trying to implement:
package wumpusworld;
/**
*
* #author Jacob
*/
public class WumpusWorldObject {
private boolean stench;
private boolean breeze;
private boolean pit;
private boolean wumpus;
private boolean gold;
private int points;
private boolean safe;
public WumpusWorldObject(){
}
public boolean getPit() {
return pit;
}
public void setPit() {
this.pit = true;
}
public boolean getWumpus() {
return wumpus;
}
public void setWumpus() {
this.wumpus = true;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public boolean getStench() {
return stench;
}
public void setStench() {
this.stench = true;
}
public boolean getBreeze() {
return breeze;
}
public void setBreeze() {
this.breeze = true;
}
public boolean getSafe() {
return safe;
}
public void setSafe() {
this.safe = true;
}
public void setGold(){
this.gold=true;
}
}
Creating array doesn't mean it will be automatically filled with new instances of your class. There are many reasons for that, like
which constructor should be used
what data should be passed to this constructor.
This kind of decisions shouldn't be made by compiler, but by programmer, so you need to invoke constructor explicitly.
After creating array iterate over it and fill it with new instances of your class.
for (int i=0; i<yourArray.length; i++)
for (int j=0; j<yourArray[i].length; j++)
yourArray[i][j] = new ...//here you should use constructor
AClass[][] obj = new AClass[50][50];
is not enough, you have to create instances of them like
obj[i][j] = new AClass(...);
In your code the line
woah[wumpusR][wumpusC].setPoints(-3000);
must be after
woah[wumpusR][wumpusC] = new WumpusWorldObject();
.

Categories