Question: Run ``Main'' as a Java Application found in the default package and grab the following things in the exact order A gem A ring A

Run ``Main'' as a Java Application found in the default package and grab the following things in the exact order

A gem

A ring

A key

A gem

A coin

Then write down the contents of the collector:

Collector has

Now what if we grab another key? Write down what you expect the contents of the collector to be and draw what you would expect the linked list to look like. (Drawings for linked list should be in a similar format as the above pictures).

Collector has

Expected:

Now actually grab another key. Then write the contents of the collector and circle the unexpected result due to the bug in grabSome .Print the linked list to show what it actually looks like.

As you can see there is an extra ``key'' node in the list; there should instead just be one ``key'' node with the number collected being ``2.'' (As it happens, the first node is the extraneous one.)

Collector has

Actual:

Understanding the Code

Take a look at the code for grabSome and concentrate on the section where a bug of omission is marked by comments in the code.This section executes if the current item being grabbed is not the head item. Note that pre always points to the node before the node which cur is pointing. Using the example in the last section, during the last step of grabbing another key. Draw pointers for pre and cur for both before and after the insert of the last item ``key''.

During this key grab, before the Bug Section (ie, after the while loop):

During this same key grab, but after the Bug Section (indicate which node is the one newly added):

Looking at the section again, are you able to point out what is missing for the case of grabbing another key?

Fixing the Code

So sometimes we want to insert a new node and sometimes not. We don't want to insert a node if we are pointing to a node that is already collecting this kind of item. Add the following (buggy!) code before the code which creates a new node:

 if (cur.thing == new_thing) { cur.count += count; return; } 

Run ``Main'' again, but this time first grab a gem and then grab a ring. The program will give an error. Draw what the collection looks like at the time the program crashed by evaluating the operation of the grabSome method with the provided input. Put in the small pointers for pre and cur :

The (buggy) code you inserted didn't handle the case that cur was null. What should happen in this case?

import java.awt.EventQueue;

import java.awt.FontMetrics;

import java.awt.Graphics;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JOptionPane;

import javax.swing.JScrollPane;

import javax.swing.JSeparator;

import javax.swing.JPanel;

import javax.swing.border.TitledBorder;

import javax.swing.JButton;

import javax.swing.JTextPane;

import java.awt.Color;

import javax.swing.border.BevelBorder;

import edu.uwm.cs351.Collector;

import edu.uwm.cs351.Collector.ThingType;

import java.awt.event.ActionListener;

import java.awt.event.ActionEvent;

import javax.swing.UIManager;

import javax.swing.JEditorPane;

import javax.swing.JTextArea;

import javax.swing.ScrollPaneConstants;

public class Main {

private JFrame frame;

private Collector collector = new Collector();

private JTextArea txtContent;

private LinkedListCanvas paneLinked;

/**

* Launch the application.

*/

public static void main(String[] args) {

EventQueue.invokeLater(new Runnable() {

public void run() {

try {

Main window = new Main();

window.frame.setVisible(true);

} catch (Exception e) {

e.printStackTrace();

}

}

});

}

/**

* Create the application.

*/

public Main() {

initialize();

}

/**

* Initialize the contents of the frame.

*/

private void initialize() {

frame = new JFrame();

frame.setBounds(100, 100, 450, 347);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.getContentPane().setLayout(null);

JPanel grabPanel = new JPanel();

grabPanel.setBorder(new TitledBorder(null, "Grab Something", TitledBorder.LEADING, TitledBorder.TOP, null, null));

grabPanel.setBounds(10, 11, 414, 91);

frame.getContentPane().add(grabPanel);

grabPanel.setLayout(null);

JButton btnCoin = new JButton("Grab a Coin");

btnCoin.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent arg0) {

addCollector(ThingType.COIN);

}

});

btnCoin.setBounds(10, 22, 117, 23);

grabPanel.add(btnCoin);

JButton btnGem = new JButton("Grab a Gem");

btnGem.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent arg0) {

addCollector(ThingType.GEM);

}

});

btnGem.setBounds(10, 56, 117, 23);

grabPanel.add(btnGem);

JButton btnKey = new JButton("Grab a Key");

btnKey.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent arg0) {

addCollector(ThingType.KEY);

}

});

btnKey.setBounds(137, 22, 117, 23);

grabPanel.add(btnKey);

JButton btnRing = new JButton("Grab a Ring");

btnRing.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent arg0) {

addCollector(ThingType.RING);

}

});

btnRing.setBounds(137, 56, 117, 23);

grabPanel.add(btnRing);

JButton btnStone = new JButton("Grab a Stone");

btnStone.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent arg0) {

addCollector(ThingType.STONE);

}

});

btnStone.setBounds(264, 22, 140, 23);

grabPanel.add(btnStone);

JButton btnLeaveAll = new JButton("Leave Everything");

btnLeaveAll.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

addCollector(null);

}

});

btnLeaveAll.setBounds(264, 56, 140, 23);

grabPanel.add(btnLeaveAll);

JPanel contentPanel = new JPanel();

contentPanel.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Collector Contents", TitledBorder.LEADING, TitledBorder.TOP, null, null));

contentPanel.setBounds(10, 113, 414, 65);

frame.getContentPane().add(contentPanel);

contentPanel.setLayout(null);

txtContent = new JTextArea();

txtContent.setLineWrap(true);

txtContent.setBounds(10, 16, 394, 40);

contentPanel.add(txtContent);

txtContent.setText(collector.show());

txtContent.setEditable(false);

JButton btnPrintLinkedList = new JButton("Print Linked List");

btnPrintLinkedList.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

paneLinked.repaint();

}

});

btnPrintLinkedList.setBounds(20, 183, 151, 23);

frame.getContentPane().add(btnPrintLinkedList);

paneLinked = new LinkedListCanvas();

paneLinked.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));

paneLinked.setBounds(10, 217, 414, 81);

paneLinked.setBackground(Color.WHITE);

frame.getContentPane().add(paneLinked);

}

private void addCollector(ThingType thing) {

try {

if (thing == null) collector.leaveEverything();

else collector.grab(thing);

txtContent.setText(collector.show());

} catch (Exception e) {

e.printStackTrace();

JOptionPane.showMessageDialog(frame, "There was an exception thrown, view Console for more details", "Exception Error", JOptionPane.ERROR_MESSAGE);

}

}

private class LinkedListCanvas extends JPanel {

private static final int BOX_WIDTH = 40, BOX_HEIGHT = 60, SECTION_HEIGHT = 20;

private static final int X_SPACE = 10;

private static final int Y = 10;

private static final int ARROWSIZE = 5;

@Override

public void paintComponent(Graphics g) {

super.paintComponent(g);

if (!collector.hasNoThings()) {

int x = 10;

int how_many = collector.howManyThings();

for (int j = 0; j < how_many; j++) {

ThingType t = collector.whatIs(j);

paintBox(g,x, ThingType.describe(t), collector.howManyOf(t));

if (j < how_many - 1) {

paintPointer(g,x);

}

x += BOX_WIDTH + X_SPACE;

}

}

}

private void paintBox(Graphics g, int x, String description, int count) {

g.drawRect(x, Y, BOX_WIDTH, BOX_HEIGHT);

g.drawLine(x, Y + SECTION_HEIGHT, x + BOX_WIDTH, Y + SECTION_HEIGHT);

g.drawLine(x, Y + SECTION_HEIGHT * 2, x + BOX_WIDTH, Y + SECTION_HEIGHT * 2);

FontMetrics fm = getFontMetrics( getFont() );

int textWidth = fm.stringWidth(description);

int textX = x + (BOX_WIDTH - textWidth) / 2;

g.drawString(description, textX, Y+ SECTION_HEIGHT - 5);

textWidth = fm.stringWidth(Integer.toString(count));

textX = x + (BOX_WIDTH - textWidth) / 2;

g.drawString(Integer.toString(count), textX, Y + SECTION_HEIGHT * 2 - 5);

}

private void paintPointer(Graphics g, int x) {

int startX = x+BOX_WIDTH/2;

int startY = Y+BOX_HEIGHT-SECTION_HEIGHT/2;

int endX = x+BOX_WIDTH+X_SPACE;

int [] pointx = { endX, endX - ARROWSIZE, endX -ARROWSIZE};

int [] pointy = { startY, startY + ARROWSIZE, startY - ARROWSIZE};

g.drawLine(startX, startY, endX, startY);

g.fillPolygon(pointx, pointy, pointx.length);

}

}

}

--------------------------------------------------------------------------------------------

public class Collector {

private final static int THINGS = 5;

private final static String things[] = { "coin", "gem", "key", "ring", "stone" };

public enum ThingType {

NOTHING(-1), COIN(0), GEM(1), KEY(2), RING(3), STONE(4);

private int value;

private ThingType(int value) {

this.value = value;

}

public int getValue() {

return value;

}

public final static String describe(ThingType t) {

if (t == ThingType.NOTHING) {

return "nothing, check input!!";

}

else {

return things[t.getValue()];

}

}

}

private static class CollectorNode

{

ThingType thing;

int count;

CollectorNode next;

public CollectorNode (ThingType thing, int count, CollectorNode next) {

this.thing = thing;

this.count = count;

this.next = next;

}

}

private CollectorNode head;

public Collector() {

head = null;

}

public Boolean hasNoThings() {

return head == null;

}

public int howManyThings() {

int count = 0;

for (CollectorNode cur = head; cur != null; cur=cur.next) {

++count;

}

return count;

}

public int howManyOf(ThingType count_thing) {

for (CollectorNode cur = head; cur != null; cur=cur.next) {

if (cur.thing == count_thing) return cur.count;

}

return 0;

}

public void grab(ThingType new_thing) {

// Being lazy is good. Never write two functions that are almost

// the same if one can be written to use the other, with

// change in function or in big-Oh efficiency.

grabSome(new_thing,1);

}

/**

* Grab something, if the item already exists in the collector increment the existing count

* by the new count

*

* @param new_thing, new_thing of ThingType to add

* @param count, number of

*/

public void grabSome(ThingType new_thing, int count) {

// if head is null construct a new node for head

if (head==null) {

head = new CollectorNode(new_thing,count,head);

}

// if the head is the item we are adding then add here

// reduces iterating through the linked list

else if (head.thing == new_thing) {

head.count += count;

}

else

{

CollectorNode pre = null, cur = null;

// start at the 2nd element

// (because we already checked the head)

pre = head;

cur = head.next;

// iterate through the elements in our list

// and stop if we find it or hit the end

while (cur != null && (new_thing != cur.thing))

{

pre = cur;

cur = cur.next;

}

//! --- Bug Section --- //

// create the new node, hitching the current after it

CollectorNode n = new CollectorNode(new_thing,count,cur);

// insert by hitching it after previous

pre.next = n;

//! ---End of section--- //

}

}

public void leave(ThingType lv_thing) {

CollectorNode pre = head, cur;

if (head == null) {

throw new IllegalStateException("No things to leave!");

}

else if (head.thing == lv_thing) {

if (head.count > 1) {

head.count--;

}

else {

head = head.next;

}

}

else {

cur = head.next;

while (cur != null && (lv_thing.getValue() > cur.thing.getValue())) {

pre = cur;

cur = cur.next;

}

if (cur != null && cur.thing == lv_thing) {

if (cur.count > 1) {

cur.count--;

}

else {

pre.next = cur.next;

}

}

else {

throw new IllegalStateException("No matching thing to leave!");

}

}

}

public void leaveAll(ThingType lv_thing) {

CollectorNode pre = head, cur;

if (head == null) {

throw new IllegalStateException("No things to leave!");

}

else if (head.thing == lv_thing) {

head = head.next;

}

else {

cur = head.next;

while (cur != null && (lv_thing.getValue() > cur.thing.getValue())) {

pre = cur;

cur = cur.next;

}

if (cur != null && cur.thing == lv_thing) {

pre.next = cur.next;

}

else {

throw new IllegalStateException("No matching thing to leave!");

}

}

}

public void leaveEverything() {

// while we have anything, drop all of what the first thing is.

while (!hasNoThings()) {

leaveAll(whatIs(0));

}

}

public ThingType whatIs(int pos) {

if (pos < 0) {

throw new IllegalStateException("list what_is position negative");

}

CollectorNode cur = head;

for (int i = 0; i < pos; i++) {

if (cur == null) {

throw new IllegalStateException("list what_is position too large");

}

else {

cur = cur.next;

}

}

return cur.thing;

}

public int whereIs(ThingType loc_thing) {

int i = 0;

CollectorNode cur = head;

while (cur != null && loc_thing != cur.thing) {

cur = cur.next;

i++;

}

if (cur == null) {

throw new IllegalStateException("Thing not found");

}

else return i;

}

public String show() {

String s = "";

if (!this.hasNoThings()) {

s += "Collector has ";

int how_many = howManyThings();

for (int j = 0; j < how_many; j++) {

ThingType t = this.whatIs(j);

int how_many_of_this = this.howManyOf(t);

s += how_many_of_this + " " + ThingType.describe(t);

if (how_many_of_this > 1) {

s += "s";

}

if (j < how_many - 1) {

s += ", ";

}

if (j == (how_many -2)) {

s += "and ";

}

}

}

else {

s = "Collector has nothing.";

}

return s;

}

}

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!