diff --git a/critters/Bear.java b/critters/Bear.java new file mode 100644 index 0000000..7412ef7 --- /dev/null +++ b/critters/Bear.java @@ -0,0 +1,54 @@ +/* +* +* Matt Jensen +* CS145 +* Lab 2 - Critters +* 4/23/19 +* Partners: Melissa, Devante +* +*/ +import java.awt.*; +import java.util.*; + +public class Bear extends Critter { + private Color color = Color.BLACK; + private String symbol = "/"; + // white if polar + public Bear(boolean polar) { + if(polar) { + this.color = Color.WHITE; + } + if( Math.random() > 0.5) { + this.changeSymbol(); + } + } + //getter + public Color getColor() { + return this.color; + } + //getter + public String toString() { + return this.symbol; + } + public Action getMove(CritterInfo info) { + this.changeSymbol(); + Neighbor front = info.getFront(); + if( front == Neighbor.OTHER ) { // check for enemy in front. + return Action.INFECT; + } + if ( front == Neighbor.EMPTY ) { // check for obstacle. + return Action.HOP; + } + return Action.LEFT; + } + // toggles between / and \ + public void changeSymbol() { + if(this.symbol.equals("/")) { + this.symbol = "\\"; + } + else { + this.symbol = "/"; + } + } + +} diff --git a/critters/Critter.java b/critters/Critter.java new file mode 100644 index 0000000..6fc8b51 --- /dev/null +++ b/critters/Critter.java @@ -0,0 +1,62 @@ +// This is the superclass of all of the Critter classes. Your class should +// extend this class. The class provides several kinds of constants: +// +// type Neighbor : WALL, EMPTY, SAME, OTHER +// type Action : HOP, LEFT, RIGHT, INFECT +// type Direction : NORTH, SOUTH, EAST, WEST +// +// Override the following methods to change the behavior of your Critter: +// +// public Action getMove(CritterInfo info) +// public Color getColor() +// public String toString() +// +// The CritterInfo object passed to the getMove method has the following +// available methods: +// +// public Neighbor getFront(); neighbor in front of you +// public Neighbor getBack(); neighbor in back of you +// public Neighbor getLeft(); neighbor to your left +// public Neighbor getRight(); neighbor to your right +// public Direction getDirection(); direction you are facing +// public Direction getFrontDirection(); direction of front neighbor +// public Direction getBackDirection(); direction of back neighbor +// public Direction getLeftDirection(); direction of left neighbor +// public Direction getRightDirection(); direction of right neighbor + +import java.awt.*; + +public class Critter { + public static enum Neighbor { + WALL, EMPTY, SAME, OTHER + }; + + public static enum Action { + HOP, LEFT, RIGHT, INFECT + }; + + public static enum Direction { + NORTH, SOUTH, EAST, WEST + }; + + // This method should be overriden (default action is turning left) + public Action getMove(CritterInfo info) { + return Action.LEFT; + } + + // This method should be overriden (default color is black) + public Color getColor() { + return Color.BLACK; + } + + // This method should be overriden (default display is "?") + public String toString() { + return "?"; + } + + // This prevents critters from trying to redefine the definition of + // object equality, which is important for the simulator to work properly. + public final boolean equals(Object other) { + return this == other; + } +} diff --git a/critters/CritterFrame.java b/critters/CritterFrame.java new file mode 100644 index 0000000..57290ac --- /dev/null +++ b/critters/CritterFrame.java @@ -0,0 +1,203 @@ +// Class CritterFrame provides the user interface for a simple simulation +// program. + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.event.*; +import java.util.*; + +public class CritterFrame extends JFrame { + private CritterModel myModel; + private CritterPanel myPicture; + private javax.swing.Timer myTimer; + private JButton[] counts; + private JButton countButton; + private boolean started; + private static boolean created; + + public CritterFrame(int width, int height) { + // this prevents someone from trying to create their own copy of + // the GUI components + if (created) + throw new RuntimeException("Only one world allowed"); + created = true; + + // create frame and model + setTitle("CSE142 critter simulation"); + setDefaultCloseOperation(EXIT_ON_CLOSE); + myModel = new CritterModel(width, height); + + // set up critter picture panel + myPicture = new CritterPanel(myModel); + add(myPicture, BorderLayout.CENTER); + + addTimer(); + + constructSouth(); + + // initially it has not started + started = false; + } + + // construct the controls and label for the southern panel + private void constructSouth() { + // add timer controls to the south + JPanel p = new JPanel(); + + final JSlider slider = new JSlider(); + slider.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + double ratio = 1000.0 / (1 + Math.pow(slider.getValue(), 0.3)); + myTimer.setDelay((int) (ratio - 180)); + } + }); + slider.setValue(20); + p.add(new JLabel("slow")); + p.add(slider); + p.add(new JLabel("fast")); + + JButton b1 = new JButton("start"); + b1.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + myTimer.start(); + } + }); + p.add(b1); + JButton b2 = new JButton("stop"); + b2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + myTimer.stop(); + } + }); + p.add(b2); + JButton b3 = new JButton("step"); + b3.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + doOneStep(); + } + }); + p.add(b3); + + // add debug button + JButton b4 = new JButton("debug"); + b4.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + myModel.toggleDebug(); + myPicture.repaint(); + } + }); + p.add(b4); + + // add 100 button + JButton b5 = new JButton("next 100"); + b5.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + multistep(100); + } + }); + p.add(b5); + + add(p, BorderLayout.SOUTH); + } + + // starts the simulation...assumes all critters have already been added + public void start() { + // don't let anyone start a second time and remember if we have started + if (started) { + return; + } + // if they didn't add any critters, then nothing to do + if (myModel.getCounts().isEmpty()) { + System.out.println("nothing to simulate--no critters"); + return; + } + started = true; + addClassCounts(); + myModel.updateColorString(); + pack(); + setVisible(true); + } + + // add right-hand column showing how many of each critter are alive + private void addClassCounts() { + Set> entries = myModel.getCounts(); + JPanel p = new JPanel(new GridLayout(entries.size() + 1, 1)); + counts = new JButton[entries.size()]; + for (int i = 0; i < counts.length; i++) { + counts[i] = new JButton(); + p.add(counts[i]); + } + + // add simulation count + countButton = new JButton(); + countButton.setForeground(Color.BLUE); + p.add(countButton); + + add(p, BorderLayout.EAST); + setCounts(); + } + + private void setCounts() { + Set> entries = myModel.getCounts(); + int i = 0; + int max = 0; + int maxI = 0; + for (Map.Entry entry: myModel.getCounts()) { + String s = String.format("%s =%4d", entry.getKey(), + (int) entry.getValue()); + counts[i].setText(s); + counts[i].setForeground(Color.BLACK); + if (entry.getValue() > max) { + max = entry.getValue(); + maxI = i; + } + i++; + } + counts[maxI].setForeground(Color.RED); + String s = String.format("step =%5d", myModel.getSimulationCount()); + countButton.setText(s); + } + + // add a certain number of critters of a particular class to the simulation + public void add(int number, Class c) { + // don't let anyone add critters after simulation starts + if (started) { + return; + } + // temporarily turning on started flag prevents critter constructors + // from calling add + started = true; + myModel.add(number, c); + started = false; + } + + // post: creates a timer that calls the model's update + // method and repaints the display + private void addTimer() { + ActionListener updater = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doOneStep(); + } + }; + myTimer = new javax.swing.Timer(0, updater); + myTimer.setCoalesce(true); + } + + // one step of the simulation + private void doOneStep() { + myModel.update(); + setCounts(); + myPicture.repaint(); + } + + // advance the simulation until step % n is 0 + private void multistep(int n) { + myTimer.stop(); + do { + myModel.update(); + } while (myModel.getSimulationCount() % n != 0); + setCounts(); + myPicture.repaint(); + } +} diff --git a/critters/CritterInfo.java b/critters/CritterInfo.java new file mode 100644 index 0000000..803b561 --- /dev/null +++ b/critters/CritterInfo.java @@ -0,0 +1,15 @@ +// The CritterInfo interface defines a set of methods for querying the +// state of a critter simulation. You should not alter this file. See +// the documentation in the Critter class for a more detailed explanation. + +public interface CritterInfo { + public Critter.Neighbor getFront(); + public Critter.Neighbor getBack(); + public Critter.Neighbor getLeft(); + public Critter.Neighbor getRight(); + public Critter.Direction getDirection(); + public Critter.Direction getFrontDirection(); + public Critter.Direction getBackDirection(); + public Critter.Direction getLeftDirection(); + public Critter.Direction getRightDirection(); +} diff --git a/critters/CritterMain.java b/critters/CritterMain.java new file mode 100644 index 0000000..94f71b2 --- /dev/null +++ b/critters/CritterMain.java @@ -0,0 +1,25 @@ +// CSE 142 Homework 9 (Critters) +// Authors: Stuart Reges and Marty Stepp +// modified by Kyle Thayer +// +// CritterMain provides the main method for a simple simulation program. Alter +// the number of each critter added to the simulation if you want to experiment +// with different scenarios. You can also alter the width and height passed to +// the CritterFrame constructor. + +public class CritterMain { + public static void main(String[] args) { + CritterFrame frame = new CritterFrame(60, 40); + + // uncomment each of these lines as you complete these classes + frame.add(30, Bear.class); + frame.add(30, Lion.class); + frame.add(30, Giant.class); + frame.add(30, Orca.class); + + frame.add(30, FlyTrap.class); + frame.add(30, Food.class); + + frame.start(); + } +} diff --git a/critters/CritterModel.java b/critters/CritterModel.java new file mode 100644 index 0000000..4b1ff08 --- /dev/null +++ b/critters/CritterModel.java @@ -0,0 +1,327 @@ +// Class CritterModel keeps track of the state of the critter simulation. + +import java.util.*; +import java.awt.Point; +import java.awt.Color; +import java.lang.reflect.*; + +public class CritterModel { + private int height; + private int width; + private Critter[][] grid; + private Map info; + private SortedMapcritterCount; + private boolean debugView; + private int simulationCount; + private static boolean created; + + public CritterModel(int width, int height) { + // this prevents someone from trying to create their own copy of + // the GUI components + if (created) + throw new RuntimeException("Only one world allowed"); + created = true; + + this.width = width; + this.height = height; + grid = new Critter[width][height]; + info = new HashMap(); + critterCount = new TreeMap(); + this.debugView = false; + } + + public Iterator iterator() { + return info.keySet().iterator(); + } + + public Point getPoint(Critter c) { + return info.get(c).p; + } + + public Color getColor(Critter c) { + return info.get(c).color; + } + + public String getString(Critter c) { + return info.get(c).string; + } + + public void add(int number, Class critter) { + Random r = new Random(); + Critter.Direction[] directions = Critter.Direction.values(); + if (info.size() + number > width * height) + throw new RuntimeException("adding too many critters"); + for (int i = 0; i < number; i++) { + Critter next; + try { + next = makeCritter(critter); + } catch (IllegalArgumentException e) { + System.out.println("ERROR: " + critter + " does not have" + + " the appropriate constructor."); + System.exit(1); + return; + } catch (Exception e) { + System.out.println("ERROR: " + critter + " threw an " + + " exception in its constructor."); + System.exit(1); + return; + } + int x, y; + do { + x = r.nextInt(width); + y = r.nextInt(height); + } while (grid[x][y] != null); + grid[x][y] = next; + + Critter.Direction d = directions[r.nextInt(directions.length)]; + info.put(next, new PrivateData(new Point(x, y), d)); + } + String name = critter.getName(); + if (!critterCount.containsKey(name)) + critterCount.put(name, number); + else + critterCount.put(name, critterCount.get(name) + number); + } + + @SuppressWarnings("unchecked") + private Critter makeCritter(Class critter) throws Exception { + Constructor c = critter.getConstructors()[0]; + if (critter.toString().equals("class Bear")) { + // flip a coin + boolean b = Math.random() < 0.5; + return (Critter) c.newInstance(new Object[] {b}); + } else { + return (Critter) c.newInstance(); + } + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public String getAppearance(Critter c) { + // Override specified toString if debug flag is true + if (!debugView) + return info.get(c).string; + else { + PrivateData data = info.get(c); + if (data.direction == Critter.Direction.NORTH) return "^"; + else if (data.direction == Critter.Direction.SOUTH) return "v"; + else if (data.direction == Critter.Direction.EAST) return ">"; + else return "<"; + } + } + + public void toggleDebug() { + this.debugView = !this.debugView; + } + + private boolean inBounds(int x, int y) { + return (x >= 0 && x < width && y >= 0 && y < height); + } + + private boolean inBounds(Point p) { + return inBounds(p.x, p.y); + } + + // returns the result of rotating the given direction clockwise + private Critter.Direction rotate(Critter.Direction d) { + if (d == Critter.Direction.NORTH) return Critter.Direction.EAST; + else if (d == Critter.Direction.SOUTH) return Critter.Direction.WEST; + else if (d == Critter.Direction.EAST) return Critter.Direction.SOUTH; + else return Critter.Direction.NORTH; + } + + private Point pointAt(Point p, Critter.Direction d) { + if (d == Critter.Direction.NORTH) return new Point(p.x, p.y - 1); + else if (d == Critter.Direction.SOUTH) return new Point(p.x, p.y + 1); + else if (d == Critter.Direction.EAST) return new Point(p.x + 1, p.y); + else return new Point(p.x - 1, p.y); + } + + private Info getInfo(PrivateData data, Class original) { + Critter.Neighbor[] neighbors = new Critter.Neighbor[4]; + Critter.Direction d = data.direction; + Critter.Direction[] neighborDirections = new Critter.Direction[4]; + for (int i = 0; i < 4; i++) { + neighbors[i] = getStatus(pointAt(data.p, d), original); + if (neighbors[i] == Critter.Neighbor.OTHER || + neighbors[i] == Critter.Neighbor.SAME){ + Point p = pointAt(data.p, d); + PrivateData oldData = info.get(grid[p.x][p.y]); + neighborDirections[i] = oldData.direction; + } else { + neighborDirections[i] = Critter.Direction.NORTH; + } + d = rotate(d); + } + return new Info(neighbors, data.direction, neighborDirections); + } + + private Critter.Neighbor getStatus(Point p, Class original) { + if (!inBounds(p)) + return Critter.Neighbor.WALL; + else if (grid[p.x][p.y] == null) + return Critter.Neighbor.EMPTY; + else if (grid[p.x][p.y].getClass() == original) + return Critter.Neighbor.SAME; + else + return Critter.Neighbor.OTHER; + } + + @SuppressWarnings("unchecked") + public void update() { + simulationCount++; + Object[] list = info.keySet().toArray(); + Collections.shuffle(Arrays.asList(list)); + + // This keeps track of critters that are locked and cannot be + // infected this turn. The happens when: + // * a Critter is infected + // * a Critter hops + Set locked = new HashSet(); + + for (int i = 0; i < list.length; i++) { + Critter next = (Critter)list[i]; + PrivateData data = info.get(next); + if (data == null) { + // happens when creature was infected earlier in this round + continue; + } + Point p = data.p; + Point p2 = pointAt(p, data.direction); + + + // try to perform the critter's action + Critter.Action move = next.getMove(getInfo(data, next.getClass())); + if (move == Critter.Action.LEFT) + data.direction = rotate(rotate(rotate(data.direction))); + else if (move == Critter.Action.RIGHT) + data.direction = rotate(data.direction); + else if (move == Critter.Action.HOP) { + if (inBounds(p2) && grid[p2.x][p2.y] == null) { + grid[p2.x][p2.y] = grid[p.x][p.y]; + grid[p.x][p.y] = null; + data.p = p2; + locked.add(next); //successful hop locks a critter from + // being infected for the rest of the + // turn + } + } else if (move == Critter.Action.INFECT) { + if (inBounds(p2) && grid[p2.x][p2.y] != null + && grid[p2.x][p2.y].getClass() != next.getClass() + && !locked.contains(grid[p2.x][p2.y])) { + Critter other = grid[p2.x][p2.y]; + // remember the old critter's private data + PrivateData oldData = info.get(other); + // then remove that old critter + String c1 = other.getClass().getName(); + critterCount.put(c1, critterCount.get(c1) - 1); + String c2 = next.getClass().getName(); + critterCount.put(c2, critterCount.get(c2) + 1); + info.remove(other); + // and add a new one to the grid + try { + grid[p2.x][p2.y] = makeCritter(next.getClass()); + // This critter has been infected and is now locked + // for the rest of this turn + locked.add(grid[p2.x][p2.y]); + } catch (Exception e) { + throw new RuntimeException("" + e); + } + // and add to the map + info.put(grid[p2.x][p2.y], oldData); + } + } + } + updateColorString(); + } + + // calling this method causes each critter to update the stored color and + // text for toString; should be called each time update is performed and + // once before the simulation begins + public void updateColorString() { + for (Critter next : info.keySet()) { + info.get(next).color = next.getColor(); + info.get(next).string = next.toString(); + } + } + + public Set> getCounts() { + return Collections.unmodifiableSet(critterCount.entrySet()); + } + + public int getSimulationCount() { + return simulationCount; + } + + private class PrivateData { + public Point p; + public Critter.Direction direction; + public Color color; + public String string; + + public PrivateData(Point p, Critter.Direction d) { + this.p = p; + this.direction = d; + } + + public String toString() { + return p + " " + direction; + } + } + + // an object used to query a critter's state (neighbors, direction) + private static class Info implements CritterInfo { + private Critter.Neighbor[] neighbors; + private Critter.Direction direction; + private Critter.Direction[] neighborDirections; + + public Info(Critter.Neighbor[] neighbors, Critter.Direction d, + Critter.Direction[] neighborDirections) { + this.neighbors = neighbors; + this.direction = d; + this.neighborDirections = neighborDirections; + } + + public Critter.Neighbor getFront() { + return neighbors[0]; + } + + public Critter.Neighbor getBack() { + return neighbors[2]; + } + + public Critter.Neighbor getLeft() { + return neighbors[3]; + } + + public Critter.Neighbor getRight() { + return neighbors[1]; + } + + public Critter.Direction getDirection() { + return direction; + } + + public Critter.Direction getFrontDirection() { + return neighborDirections[0]; + } + + public Critter.Direction getBackDirection() { + return neighborDirections[2]; + } + + public Critter.Direction getLeftDirection() { + return neighborDirections[3]; + } + + public Critter.Direction getRightDirection() { + return neighborDirections[1]; + } + } +} diff --git a/critters/CritterPanel.java b/critters/CritterPanel.java new file mode 100644 index 0000000..a395267 --- /dev/null +++ b/critters/CritterPanel.java @@ -0,0 +1,48 @@ +// Class CritterPanel displays a grid of critters + +import javax.swing.*; +import java.awt.Point; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +public class CritterPanel extends JPanel { + private CritterModel myModel; + private Font myFont; + private static boolean created; + + public static final int FONT_SIZE = 12; + + public CritterPanel(CritterModel model) { + // this prevents someone from trying to create their own copy of + // the GUI components + if (created) + throw new RuntimeException("Only one world allowed"); + created = true; + + myModel = model; + // construct font and compute char width once in constructor + // for efficiency + myFont = new Font("Monospaced", Font.BOLD, FONT_SIZE + 4); + setBackground(Color.CYAN); + setPreferredSize(new Dimension(FONT_SIZE * model.getWidth() + 20, + FONT_SIZE * model.getHeight() + 20)); + } + + public void paintComponent(Graphics g) { + super.paintComponent(g); + g.setFont(myFont); + Iterator i = myModel.iterator(); + while (i.hasNext()) { + Critter next = i.next(); + Point p = myModel.getPoint(next); + String appearance = myModel.getAppearance(next); + g.setColor(Color.BLACK); + g.drawString("" + appearance, p.x * FONT_SIZE + 11, + p.y * FONT_SIZE + 21); + g.setColor(myModel.getColor(next)); + g.drawString("" + appearance, p.x * FONT_SIZE + 10, + p.y * FONT_SIZE + 20); + } + } +} diff --git a/critters/FlyTrap.java b/critters/FlyTrap.java new file mode 100644 index 0000000..6677dba --- /dev/null +++ b/critters/FlyTrap.java @@ -0,0 +1,23 @@ +// This defines a simple class of critters that infect whenever they can and +// otherwise just spin around, looking for critters to infect. This simple +// strategy turns out to be surpisingly successful. + +import java.awt.*; + +public class FlyTrap extends Critter { + public Action getMove(CritterInfo info) { + if (info.getFront() == Neighbor.OTHER) { + return Action.INFECT; + } else { + return Action.LEFT; + } + } + + public Color getColor() { + return Color.RED; + } + + public String toString() { + return "T"; + } +} \ No newline at end of file diff --git a/critters/Food.java b/critters/Food.java new file mode 100644 index 0000000..cbd8f34 --- /dev/null +++ b/critters/Food.java @@ -0,0 +1,18 @@ +// This defines a simple class of critters that sit around waiting to be +// taken over by other critters. + +import java.awt.*; + +public class Food extends Critter { + public Action getMove(CritterInfo info) { + return Action.INFECT; + } + + public Color getColor() { + return Color.GREEN; + } + + public String toString() { + return "F"; + } +} diff --git a/critters/Giant.java b/critters/Giant.java new file mode 100644 index 0000000..4c29cdc --- /dev/null +++ b/critters/Giant.java @@ -0,0 +1,63 @@ +/* +* +* Matt Jensen +* CS145 +* Lab 2 - Critters +* 4/23/19 +* Partners: Melissa, Devante +* +*/ +import java.awt.*; +import java.util.*; + +public class Giant extends Critter { + private Color color = Color.GRAY; + + private String symbol; + + public int moveCount; + + + public Giant() { + } + + public Color getColor() { + return this.color; + } + + public String toString() { + this.changeSymbol(); + return this.symbol; + } + + private void changeSymbol() { + if( this.moveCount > 24 ) { + this.moveCount = 0; + } + if( this.moveCount <= 6) { + this.symbol = "FEE"; + } + if( this.moveCount > 6 && this.moveCount <= 12 ) { + this.symbol = "FIE"; + } + if ( this.moveCount > 12 && this.moveCount <= 18) { + this.symbol = "FOO"; + } + if ( this.moveCount > 18 ) { + this.symbol = "FUM"; + } + } + + public Action getMove(CritterInfo info) { + this.moveCount++; + Neighbor front = info.getFront(); + if( front == Neighbor.OTHER) { + return Action.INFECT; + } + if( front == Neighbor.EMPTY) { + return Action.HOP; + } + return Action.RIGHT; + } + +} diff --git a/critters/Lion.java b/critters/Lion.java new file mode 100644 index 0000000..664f703 --- /dev/null +++ b/critters/Lion.java @@ -0,0 +1,72 @@ +/* +* +* Matt Jensen +* CS145 +* Lab 2 - Critters +* 4/23/19 +* Partners: Melissa, Devante +* +*/ +import java.awt.*; +import java.util.*; + +public class Lion extends Critter { + + private Color color = Color.BLUE; + + private int moves = 0; + + public Lion() { + this.changeColor(); + } + + public int getMoveCount() { + return this.moves; + } + + public Color getColor() { + return this.color; + } + + public String toString() { + return "L"; + } + + public void changeColor() { + if(this.getMoveCount() == 0 || this.getMoveCount() % 3 == 0) { + int rand = this.randomWithRange(0, 2); + if(rand == 0 ) { + this.color = Color.RED; + } + if(rand == 1 ) { + this.color = Color.GREEN; + } + if(rand == 2 ) { + this.color = Color.BLUE; + } + } + } + public Action getMove(CritterInfo info) { + this.moves = this.moves++; + this.changeColor(); + + Neighbor front = info.getFront(); + + if( front == Neighbor.OTHER ) { // check for enemy in front. + return Action.INFECT; + } + if ( front == Neighbor.WALL || info.getRight() == Neighbor.WALL ) { // check for obstacle. + return Action.LEFT; + } + if ( front == Neighbor.SAME ) { // check for obstacle. + return Action.RIGHT; + } + return Action.HOP; + } + public int randomWithRange(int min, int max) + { + int range = (max - min) + 1; + return (int)(Math.random() * range) + min; + } + +} diff --git a/critters/Orca.java b/critters/Orca.java new file mode 100644 index 0000000..182e3b7 --- /dev/null +++ b/critters/Orca.java @@ -0,0 +1,54 @@ +/* +* +* Matt Jensen +* CS145 +* Lab 2 - Critters +* 4/23/19 +* Partners: Melissa, Devante +* +*/ +import java.awt.*; +import java.util.*; + +public class Orca extends Critter { + private Color color = Color.BLACK; + + private String symbol = "0-<"; + + public int moveCount; + + + public Orca() { + } + + public Color getColor() { + if( this.color == Color.BLACK) { + this.color = Color.WHITE; + } + else{ + this.color = Color.BLACK; + } + return this.color; + } + + public String toString() { + return this.symbol; + } + + public Action getMove(CritterInfo info) { + this.moveCount++; + Neighbor front = info.getFront(); + + if(front == Neighbor.OTHER) { + return Action.INFECT; + } + if(front == Neighbor.EMPTY) { + return Action.HOP; + } + if(front == Neighbor.WALL) { + return Action.RIGHT; + } + return Action.LEFT; + } + +}