Answered step by step
Verified Expert Solution
Link Copied!

Question

00
1 Approved Answer

Need some coding help with refactoring some of my code. Refactor GameEngine Declare an instance variable of type Map that maps Items to GameObjects. Initialize

Need some coding help with refactoring some of my code.

Refactor GameEngine

  • Declare an instance variable of type Map that maps Items to GameObjects. Initialize the map in the constructor using a HashMap or an EnumMap (your choice) and put the four game-objects in it. Use your map to simplify the methods getName, getLocation, getItem, and any other methods that can be simplified.
  • Once you have created the map and simplified the code, you should no longer need the fields wolf, goose, beans, and farmer (since you can easily access them using the map). Make sure there are no references to them and then delete them. Note that you will still have to create appropriate game objects in the constructor so that you can add them to the map, but fix things so that you won't need the fields anymore.
  • Change the method names getName, getLocation, and getSound to getItemName, getItemLocation, and getItemSound. This will make it clear that these metods just call through to the game object getters.
  • The"current location" is basically just the boat location. Rename the field and the getter to use boat-location rather than current-location.
  • Clean up the class. Make sure all fields and helper methods have private access. And make sure all fields that can be declared final are declared final.
package river; public class GameEngine { private GameObject wolf; private GameObject goose; private GameObject beans; private GameObject farmer; private Location boatLocation; public GameEngine() { wolf = new Wolf(); goose = new Goose(); beans = new Beans(); farmer = new Farmer(); boatLocation = Location.START; } public String getName(Item id) { switch (id) { case WOLF: return wolf.getName(); case GOOSE: return goose.getName(); case BEANS: return beans.getName(); default: return farmer.getName(); } } public Location getLocation(Item id) { switch (id) { case WOLF: return wolf.getLocation(); case GOOSE: return goose.getLocation(); case BEANS: return beans.getLocation(); default: return farmer.getLocation(); } } public String getSound(Item id) { switch (id) { case WOLF: return wolf.getSound(); case GOOSE: return goose.getSound(); case BEANS: return beans.getSound(); default: return farmer.getSound(); } } public Location getCurrentLocation() { return boatLocation; } public void loadBoat(Item id) { switch (id) { case WOLF: if (wolf.getLocation() == boatLocation && goose.getLocation() != Location.BOAT && beans.getLocation() != Location.BOAT) { wolf.setLocation(Location.BOAT); } break; case GOOSE: if (goose.getLocation() == boatLocation && wolf.getLocation() != Location.BOAT && beans.getLocation() != Location.BOAT) { goose.setLocation(Location.BOAT); } break; case BEANS: if (beans.getLocation() == boatLocation && wolf.getLocation() != Location.BOAT && goose.getLocation() != Location.BOAT) { beans.setLocation(Location.BOAT); } break; case FARMER: if (farmer.getLocation() == boatLocation) { farmer.setLocation(Location.BOAT); } default: // do nothing } } public void unloadBoat(Item id) { switch (id) { case WOLF: if (wolf.getLocation() == Location.BOAT) { wolf.setLocation(boatLocation); } break; case GOOSE: if (goose.getLocation() == Location.BOAT) { goose.setLocation(boatLocation); } break; case BEANS: if (beans.getLocation() == Location.BOAT) { beans.setLocation(boatLocation); } break; case FARMER: if (farmer.getLocation() == Location.BOAT) { farmer.setLocation(boatLocation); } default: // do nothing } } public void rowBoat() { assert (boatLocation != Location.BOAT); if (boatLocation == Location.START) { boatLocation = Location.FINISH; } else { boatLocation = Location.START; } } public boolean gameIsWon() { return wolf.getLocation() == Location.FINISH && goose.getLocation() == Location.FINISH && beans.getLocation() == Location.FINISH && farmer.getLocation() == Location.FINISH; } public boolean gameIsLost() { if (goose.getLocation() == Location.BOAT) { return false; } if (goose.getLocation() == farmer.getLocation()) { return false; } if (goose.getLocation() == boatLocation) { return false; } if (goose.getLocation() == wolf.getLocation()) { return true; } if (goose.getLocation() == beans.getLocation()) { return true; } return false; } public void resetGame() { wolf.setLocation(Location.START); goose.setLocation(Location.START); beans.setLocation(Location.START); farmer.setLocation(Location.START); boatLocation = Location.START; } } 

Refactor GameEngineTest

  • The class under test is GameEngine, so declare a private field "engine" of type GameEngine and initialize it in the @Before method (setUp). Use it to replace the local instances of the game engine.
  • Rename the testObject method to testObjectCallThroughs. Instead of creating game-objects, test the call through methods in the game-engine class. For example, instead of testing whether farmer.getName is "Farmer", test whether engine.getItemName(Item.FARMER) is "Farmer".
  • Write a helper method called transport that takes an item. The method should transport the item from one side of the river to the other. Use it to simplify some of the test cases in which an item is transported.
  • Write a helper method called goBackAlone that just calls engine.rowBoat, and use it whenever the farmer is going back alone in the test cases.

Remember that through all of the above refactorings, you are only changing the design of the code, not its functionality. Therefore, your test cases should continue to pass after each refactoring and -- if you do them carefully -- during each step of your refactoring.

package river; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class GameEngineTest { @Before public void setUp() throws Exception { } @Test public void testObjects() { GameObject farmer = new Farmer(); GameObject wolf = new Wolf(); GameObject goose = new Goose(); GameObject beans = new Beans(); Assert.assertEquals("Farmer", farmer.getName()); Assert.assertEquals(Location.START, farmer.getLocation()); Assert.assertEquals("", farmer.getSound()); Assert.assertEquals("Wolf", wolf.getName()); Assert.assertEquals(Location.START, wolf.getLocation()); Assert.assertEquals("Howl", wolf.getSound()); Assert.assertEquals("Goose", goose.getName()); Assert.assertEquals(Location.START, goose.getLocation()); Assert.assertEquals("Honk", goose.getSound()); Assert.assertEquals("Beans", beans.getName()); Assert.assertEquals(Location.START, beans.getLocation()); Assert.assertEquals("", beans.getSound()); } @Test public void testMidTransport() { GameEngine engine = new GameEngine(); Assert.assertEquals(Location.START, engine.getLocation(Item.GOOSE)); engine.loadBoat(Item.GOOSE); Assert.assertEquals(Location.BOAT, engine.getLocation(Item.GOOSE)); engine.rowBoat(); Assert.assertEquals(Location.BOAT, engine.getLocation(Item.GOOSE)); engine.unloadBoat(Item.GOOSE); Assert.assertEquals(Location.FINISH, engine.getLocation(Item.GOOSE)); } @Test public void testWinningGame() { GameEngine engine = new GameEngine(); // transport the goose engine.loadBoat(Item.GOOSE); engine.loadBoat(Item.FARMER); engine.rowBoat(); engine.unloadBoat(Item.GOOSE); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); // go back alone engine.rowBoat(); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); //transport the wolf engine.loadBoat(Item.WOLF); engine.loadBoat(Item.FARMER); engine.rowBoat(); engine.unloadBoat(Item.GOOSE); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); // transport the goose engine.loadBoat(Item.GOOSE); engine.loadBoat(Item.FARMER); engine.rowBoat(); engine.unloadBoat(Item.GOOSE); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); // transport the beans engine.loadBoat(Item.GOOSE); engine.loadBoat(Item.FARMER); engine.rowBoat(); engine.unloadBoat(Item.GOOSE); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); // go back alone engine.rowBoat(); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); // transport the goose engine.loadBoat(Item.GOOSE); engine.loadBoat(Item.FARMER); engine.rowBoat(); engine.unloadBoat(Item.GOOSE); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); } @Test public void testLosingGame() { GameEngine engine = new GameEngine(); // transport the goose engine.loadBoat(Item.GOOSE); engine.rowBoat(); engine.unloadBoat(Item.GOOSE); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); // go back alone engine.rowBoat(); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); //transport the wolf engine.loadBoat(Item.WOLF); engine.loadBoat(Item.FARMER); engine.rowBoat(); engine.unloadBoat(Item.GOOSE); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); // go back alone engine.rowBoat(); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); } @Test public void testError() { GameEngine engine = new GameEngine(); // transport the goose engine.loadBoat(Item.GOOSE); engine.rowBoat(); engine.unloadBoat(Item.GOOSE); Assert.assertFalse(engine.gameIsLost()); Assert.assertFalse(engine.gameIsWon()); // save the state Location topLoc = engine.getLocation(Item.WOLF); Location midLoc = engine.getLocation(Item.GOOSE); Location bottomLoc = engine.getLocation(Item.GOOSE); Location playerLoc = engine.getLocation(Item.FARMER); // This action should do nothing since the wolf is not on the same shore as the // boat engine.loadBoat(Item.WOLF); // check that the state has not changed Assert.assertEquals(topLoc, engine.getLocation(Item.WOLF)); Assert.assertEquals(midLoc, engine.getLocation(Item.GOOSE)); Assert.assertEquals(bottomLoc, engine.getLocation(Item.GOOSE)); Assert.assertEquals(playerLoc, engine.getLocation(Item.FARMER)); } }

Refactor GameObject

  • Get rid of the GameObject subclasses we don't want to limit ourselves to the farmer-oriented river-crossing game. Therefore, it doesn't make much sense to have specific subclasses devoted to these objects. Furthermore, the subclasses don't serve a lot of purpose - they are essentially just there to initialize fields in the game-object.
  • Change the getter method "getSound" in GameObject so that it is based on a field, just like the "getName" and "getLocation" getter methods.
  • We are not going to modify the name field of a game object after it is created. Therefore, get rid of the setter method for it. Remember to check that there are no references to a method (or field or constructor) before deleting it.
  • Clean up the class. Get rid of any unused constructors. Make all fields private. Make the fields that are never assigned to final.

--GameObject.java

package river;

public class GameObject {

protected String name; protected Location location; protected String sound = ""; public GameObject (){ name = ""; sound = ""; location = Location.START; };

public String getName() { return name; }

public Location getLocation() { return location; }

public void setLocation(Location loc) { this.location = loc; }

public String getSound() { return sound; }

}

other java files associated with this code

--Item.java

package river;

public enum Item { WOLF, GOOSE, BEANS, FARMER; }

Location.java

package river;

public enum Location { START, FINISH, BOAT; }

Wolf.java

package river;

public class Wolf extends GameObject {

public Wolf() { name = "Wolf"; sound = "Howl"; location = Location.START; }

}

Goose.java

package river;

public class Goose extends GameObject {

public Goose() { name = "Goose"; sound = "Honk"; location = Location.START; }

}

Beans.java

package river;

public class Beans extends GameObject {

public Beans() { name = "Beans"; location = Location.START; } }

Farmer.java

package river;

public class Farmer extends GameObject {

public Farmer() { name = "Farmer"; location = Location.START; }

}

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access with AI-Powered Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions