Computer Science 15-111 (Sections A & B), Spring 2007

Quiz 3  /  Thu 15-Feb-2007

SOLUTIONS

 

·         All work is by hand.  No computers or calculators or other devices allowed.

·         Show your work!  Correct answers without supporting calculations receive NO points.

·         When writing Java code during a quiz, style does not count!  Only correctness!

·         Time:  25 minutes.

1.   Draw by hand, in the provided square, what paintFoo() paints:
  public void paintFoo(Graphics page) {
  int bar = 3, foo = getWidth()/(bar+1);
   page.setColor(Color.black);
   for (int row=0; row<=bar; row++)
        for (int col=0; col<bar; col++)
             if ((row % 2) == (col % 2))
                   page.fillRect(col*foo,row*foo,foo,foo);
  }


Notice that there are 3 cols, 4 rows, and the rows fit exactly whereas there is one empty col at the right.

2.   Assuming this component has a timer started with startTimer(250), draw by hand, in the provided square, what paintComponent paints after the timer has run for one second.
  private int foo = 5;
  private ArrayList<Integer> foos = new ArrayList<Integer>();
 
  public void paintComponent(Graphics page) {
  int x = this.getWidth()/10, y = x/2;
  page.setColor(Color.black);
  for (int foo : foos)
        page.fillRect(x*foo, 0, y, y*foo);
  }
 
  public void onTimer() {
  foos.add(foo--);
  }


Notice there are 4 bars, not 5.  Each is separated by a space.

3.      Very briefly (in 10 words or less!), explain why Tetris’s 2d board of Colors should be initialized in the Tetris component’s constructor.

Many of you answered why it needs to be initialized at all, not why it had to be done in the constructor.  We can also initialize instance variables outside the constructor when we declare them, as in:
   private int x = 5;
However, in this case, we cannot do that because we needed nested for loops in order to set all the values of the 2d array to the emptyColor.


4.      Assuming the given component has a timer started with startTimer(250), the following code will move a black rectangle across the screen.  Very briefly (in 10 words or less!) explain why it is impossible to state with certainty the precise x location after, say, 20 seconds have elapsed.
  private int x = 0;
  public void paintComponent(Graphics page) {
  page.setColor(Color.black);
  page.fillRect(x++,10,20,30);
  }
  public void onTimer() { x++; }

There are two valid answers:  timers in Java are imprecise, and (more important) we have no way of knowing how many times paintComponent will be called, so its side-effect of incrementing x is not at all predictable (and this is why you should not have side-effects in your paint methods!).  The answer has nothing to do with how quickly the updates occur, nor whether or not the object moves off the visible portion of the screen.



5.      Write this method:
public void paintCenteredRectangle(Graphics page, int left, int top,
                                   int width, int height, int margin)

The parameters left, top, width, and height describe an outer rectangle.  You should paint an inner rectangle, centered within the outer rectangle, with a distance of margin
between each side of the inner rectangle and the enclosing side of the outer rectangle.  Note that if the resulting inner rectangle would not be visible, then you must not paint it!

   public void paintCenteredRectangle(Graphics page, int left, int top,
                                   int width, int height, int margin) {
      if ((width > 2*margin) && (height > 2*margin))
         page.fillRect(left+margin,top+margin,width-2*margin,height-2*margin);
    }




6.      In Tetris, we defined our pieceTypes to be a 3d array of int’s (where this is an array of rectangular 2d arrays each describing a piece type as rows of 1’s and 0’s).  Say we want to score each falling piece according to the number of 1’s in its type.  To assist with that, write a method:
    
public int maxPieceScore(int[][][] pieceTypes)
that takes a 3d array of piece types returns the maximum number of 1’s in any piece.

Here are two different ways to do it.  The first way seems much cleaner to me.

   public int maxPieceScore(int[][][] pieceTypes) {
         int max = 0;
         for (int[][] piece : pieceTypes) {
               int score =0;
               for (int[] row : piece)
                     for (int cell : row)
                           if (cell == 1) score++;
               if (score > max) max = score;
         }
         return max;
   }

   public int maxPieceScore2(int[][][] pieceTypes) {
         int max = 0;
         int pieces = pieceTypes.length;
         for (int piece=0; piece<pieces; piece++) {
               int score =0;
               int rows = pieceTypes[piece].length;
               for (int row=0; row<rows; row++) {
                     int cols = pieceTypes[piece][row].length;
                     for (int col=0; col<cols; col++)
                           if (pieceTypes[piece][row][col] == 1) score++;
               }
               max = Math.max(max,score);
         }
         return max;
   }