Chris Pollett >
Old Classes >
CS146

   ( Print View )

Grades: |Sec6|Sec8|

Course Info: Homework Assignments: Practice Exams:
                           












HW #2 Page

HW#2 --- last modified January 16 2019 00:35:12..

A solution set is posted here.

Due date: Oct. 1, 2001 start of class
========= 

Files to be submitted: cs146sec6hw2file1.java (sec 8 if you're in sec 8)
====================== This as usual should be submitted via e-mail.
                       Book problem 4.9 should be turned in on paper
                       start of class.

Purpose: To gain experience with stacks and binary search trees.
======== 

Specification:
==============
In addition to problem 4.9, you will write a Java application to display
pictures written in ShML (Shape Mark-up Language). ShML is a language I
invented for this homework similar to HTML. Your application will be tested 
from the command prompt with a line like:

java cs146sec6hw2file1 shmlfile

Your program should then read in the file in its args[0] and try to parse
the ShML file in it. If the file is parsable your application should then 
open a JFrame and draw the ShML picture in it on a black background. 
Make sure you have a WindowListener so this window can be clicked closed.

ShML has three pairs of tags:

<square>
</square>

<circle>
</circle>

<triangle>
</triangle>

The meaning of a pair of tags is to draw that kind of shape in the current
enclosing shape. Triangles should be drawn in red; circles should be drawn
in green; and squares should be drawn in blue.  If there is no enclosing
shape the shape should be drawn directly on the frame's background.
For example, if the ShML file was the following:


<square>
<circle>
</circle>
<triangle>
</triangle>
</square>
<square>
</square>


then two non-overlapping squares would be drawn centered on the JFrame.
In the interior of the first square, would be drawn in a non-overlapping 
manner a circle and triangle. Obviously, shapes drawn interior to other 
shapes must be scaled appropriately to make them fit inside. The details of 
the scaling and insuring the shapes interior to a given shape do not overlap
are left up to you. You are required to use java.util.Stack to handle 
the parsing of the file. You may also find the StringTokenizer class useful
in writing your application. You can use the Graphics class' method 
fillPolygon to draw triangles. If the file involves any non-space symbols
other than those in tags or if the open and close tags mismatch then
your application should output:

The provided file was not a valid ShML file.

If args[0] was empty a message saying so should be given as well. 
An example of a file with mismatched tags is:


<square>
<circle>
</circle>
</triangle>
</square>


As another example of what an ShML image might look like the
file:

<triangle>
  <circle>
    <square>
      <circle>
      </circle>
    </square>
  </circle>
  <square>
  </square>
  <circle>
  </circle>
</triangle>

in my version produces the output:
shml browser
Useful Hints:
=============
(0) Make sure to take advantage of the Java 2 Platform Class Library
    link off of the class homepage.

(1) JFrame extends Component so has a paint(Graphics g) method.
    You should override this method to do your drawing of shapes.

(2) You may want to make classes for ShMLCircle, ShMLSquare, and 
    ShMLTriangle. Each of which extend a common class ShMLShape.
    An ShMLShape could contain a LinkedList object (in java.util)
    to which you could add other ShMLShape's. ShMLShape's could
    have a draw method which given a Graphics object g can draw
    itself and any object on it to g. An ShMLShape can store
    information on what its bounding rectangle is. When it is drawn
    it knows to draw itself in this rectangle. It can have
    a method setRectangle to set this Rectangle. Finally, an ShMLShape 
    obj can have an organize() method which can be called if need be
    during the draw phase. This method calculates a bounding rectangle
    for each the ShMLShapes on obj so that these ShMLShapes do not
    overlap. It does a setRectangle on each of these ShMLShapes then
    calls their organize() methods.

(3) You can read in files using the FileReader and BufferedReader
    classes. To open a file you can use something like:

    BufferedReader buf = new BufferedReader( new FileReader(fileName));

    Here fileName is a String. To close this file do buf.close(); 
    To read a line, you can do buf.readLine(). This will be null
    when the end of a file is reached. You should catch
    FileNotFoundException's and IOException's.
 
(4) You can check if an object is an object of a given class
    using instanceof. For instance, 

    (obj instanceof ShMLCircle)

    would return true if obj is an object of class ShMLCircle.

(5) When using Stack or LinkedList remember you have to recast
    the Object back to a subtype (for instance, ShMLShape) if you want
    the functionality of that subtype. 

(6) Remember a String variable is a reference. To actually check if two
    String's are equal use to s1.equals(s2) where s1 and s2 are String's.

Below is a short example application  (from class) that extends JFrame:


/*
	LineDrawer - a simple application to draw a line in a window.
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

import java.util.*;
import java.io.*;

/** 
	Run from the command line with a command like:

   java LineDrawer filename

   This LineDrawer reads in two point from the file filename
   and then opens a JFrame where the line given by these points
   is drawn.

   @author			cpollett
   @version			1.0
*/
public class LineDrawer extends JFrame
{
   public static final int DEFAULT_X_SZ = 400; //dimensions of window
   public static final int DEFAULT_Y_SZ = 400;
   Polygon line = new Polygon(); // will be used to contain our line

   /**
      This constructor takes opens the file named name and tries to
      read in a line. Background and size of window are also set.
   */
   public LineDrawer( String name) 
   {
      super("LineDrawer");

      readLine(name);
      setSize(DEFAULT_X_SZ, DEFAULT_Y_SZ);
      setBackground(Color.black);								

   }

   /**
      This method will be called by the run-time system when it wants
      to draw the interior of the JFrame.

      Since we aren't doing any animation this program directly
      overrides paint to draw the line. For animations, a better
      way is to add a JPanel to the JFrame and override the
      JPanel's paintComponent(Graphics g) method. This avoid flicker.
   */
   public void paint(Graphics g)
   {
      g.setColor(Color.blue);
 
      g.drawPolygon(line);
   }

   /*
      This functions open the file fileName and tries to read
      two Points from it. These Point's are added to the
      Polygon line.
   */
   private void readLine(String fileName)
   {
		
      String mesg = "File did not contain enough points";

      Point point = new Point(-1,-1); //we give some dummy values
      Point point2 = new Point(-1,-1);//so defined on all syntactic paths


      try
      {
         BufferedReader buf= new BufferedReader(
                                         new FileReader(fileName)
                                               );
					//open a Reader for the file fileName
			
         String pt = buf.readLine(); //read in first Point as String
         point = parsePoint(pt); //convert String to Point
         String pt2 = buf.readLine(); //now do the same for second point
         point2 = parsePoint(pt2);
         buf.close();
      }
      catch(FileNotFoundException fe)
      {
         System.err.println("File not found");
         System.exit(1);
      }
      catch(IOException ie)
      {
         System.err.println("An I/O Exception occurred:"+ie.toString());
         System.exit(1);
      }
      catch(Exception ee)
      {
         System.err.println(mesg);
         System.exit(1);
      } 		
		
      line.addPoint(point.x, point.y);
      line.addPoint(point2.x, point2.y);
   }

   /*
      This function takes a String and tries to determins a Point
      object from it. 

      The idea is a String like:
      10,20
      is supposed to represent the point (10,20).
   */
   private Point parsePoint(String pt)
      throws Exception /* we have learned how to define our
                          own exceptions yet so I just throw an Exception
                       */
   {
      int x=-1; //dummy values so defined on all syntactic paths.
      int y=-1;

      StringTokenizer tokens = new StringTokenizer(pt,",");

      if(tokens.hasMoreTokens()) //get first coordinate
      {
         x = Integer.parseInt(tokens.nextToken());
      }
      else
         throw new Exception();

      if(tokens.hasMoreTokens()) //get second coordinate
      {
         y = Integer.parseInt(tokens.nextToken());
      }
      else
         throw new Exception();

      return new Point(x,y);
   }

	// Main entry point
   public static void main(String[] args) 
   {
      if( args.length == 0 )
      {
         System.err.println("You need to give as a comand line "+
                                      "argument an point file.");
         System.exit(1);
      }
		
      LineDrawer app= new LineDrawer(args[0]);

      app.show(); //show the JFrame on the screen
		
		app.addWindowListener( /* handle close window events with
                                this anonymous inner class
                             */
         new WindowAdapter() 
         {
            public void windowClosing( WindowEvent e)
            {
               System.exit(0);
            }
         }
                           );	
   }
	
}


Point Breakdown
===============
Coding guidelines followed............1pt
WindowListener used...................1pt
Stacks used in a constructive way.....1pt
Program reads in ShML file............1pt
Draws shapes correctly................1pt
Bad or no input file case handled.....1pt
Problem 4.9a..........................1pt
Problem 4.9b..........................1pt
=========================================
Total.................................8pts                          

A solution set is posted here.