Advertisement
CSenshi

OOP - HW2 Milestone: A (Piece.java)

Apr 13th, 2020
590
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.02 KB | None | 0 0
  1. // Piece.java
  2. package tetris;
  3.  
  4. import java.util.*;
  5.  
  6. /**
  7.  * An immutable representation of a tetris piece in a particular rotation.
  8.  * Each piece is defined by the blocks that make up its body.
  9.  * <p>
  10.  * Typical client code looks like...
  11.  * <pre>
  12.  * Piece pyra = new Piece(PYRAMID_STR);     // Create piece from string
  13.  * int width = pyra.getWidth();         // 3
  14.  * Piece pyra2 = pyramid.computeNextRotation(); // get rotation, slow way
  15.  *
  16.  * Piece[] pieces = Piece.getPieces();  // the array of root pieces
  17.  * Piece stick = pieces[STICK];
  18.  * int width = stick.getWidth();        // get its width
  19.  * Piece stick2 = stick.fastRotation(); // get the next rotation, fast way
  20.  * </pre>
  21.  */
  22. @SuppressWarnings("ALL")
  23. public class Piece {
  24.     // Starter code specs out a few basic things, leaving
  25.     // the algorithms to be done.
  26.     private TPoint[] body;
  27.     private int[] skirt;
  28.     private int width;
  29.     private int height;
  30.     private Piece next; // "next" rotation
  31.  
  32.     static private Piece[] pieces;    // singleton static array of first rotations
  33.  
  34.     /**
  35.      * Defines a new piece given a TPoint[] array of its body.
  36.      * Makes its own copy of the array and the TPoints inside it.
  37.      */
  38.     public Piece(TPoint[] points) {
  39.         // initialize with zero values
  40.         this.width = 0;
  41.         this.height = 0;
  42.         this.body = new TPoint[points.length];
  43.  
  44.         // copy  points into this.body
  45.         System.arraycopy(points, 0, this.body, 0, points.length);
  46.  
  47.         // calculate height and width
  48.         for (TPoint p : this.body) {
  49.             this.height = Math.max(p.y, this.height);
  50.             this.width = Math.max(p.x, this.width);
  51.         }
  52.         // at this point we have coordinates, increase by 1 to get actual size
  53.         this.width++;
  54.         this.height++;
  55.  
  56.         // calculate skirt
  57.         this.skirt = new int[width];
  58.         Arrays.fill(this.skirt, Integer.MAX_VALUE);
  59.         for (TPoint tPoint : body)
  60.             this.skirt[tPoint.x] = Math.min(this.skirt[tPoint.x], tPoint.y);
  61.     }
  62.  
  63.  
  64.     /**
  65.      * Alternate constructor, takes a String with the x,y body points
  66.      * all separated by spaces, such as "0 0  1 0  2 0  1 1".
  67.      * (provided)
  68.      */
  69.     public Piece(String points) {
  70.         this(parsePoints(points));
  71.     }
  72.  
  73.     /**
  74.      * Returns the width of the piece measured in blocks.
  75.      */
  76.     public int getWidth() {
  77.         return width;
  78.     }
  79.  
  80.     /**
  81.      * Returns the height of the piece measured in blocks.
  82.      */
  83.     public int getHeight() {
  84.         return height;
  85.     }
  86.  
  87.     /**
  88.      * Returns a pointer to the piece's body. The caller
  89.      * should not modify this array.
  90.      */
  91.     public TPoint[] getBody() {
  92.         return body;
  93.     }
  94.  
  95.     /**
  96.      * Returns a pointer to the piece's skirt. For each x value
  97.      * across the piece, the skirt gives the lowest y value in the body.
  98.      * This is useful for computing where the piece will land.
  99.      * The caller should not modify this array.
  100.      */
  101.     public int[] getSkirt() {
  102.         return skirt;
  103.     }
  104.  
  105.  
  106.     /**
  107.      * Returns a new piece that is 90 degrees counter-clockwise
  108.      * rotated from the receiver.
  109.      */
  110.     public Piece computeNextRotation() {
  111.         // initialize array that will be body of our new piece
  112.         TPoint[] res = new TPoint[this.body.length];
  113.  
  114.         // integer to keep track of index while filling array
  115.         int i = 0;
  116.         // iterate each point and find its 90 degree rotation
  117.         // 90 degree rotation of (x,y) = (height-y-1, x)
  118.         for (TPoint p : this.body)
  119.             res[i++] = new TPoint(this.height - p.y - 1, p.x);
  120.  
  121.         return new Piece(res);
  122.     }
  123.  
  124.     /**
  125.      * Returns a pre-computed piece that is 90 degrees counter-clockwise
  126.      * rotated from the receiver.    Fast because the piece is pre-computed.
  127.      * This only works on pieces set up by makeFastRotations(), and otherwise
  128.      * just returns null.
  129.      */
  130.     public Piece fastRotation() {
  131.         return next;
  132.     }
  133.  
  134.  
  135.     /**
  136.      * Returns true if two pieces are the same --
  137.      * their bodies contain the same points.
  138.      * Interestingly, this is not the same as having exactly the
  139.      * same body arrays, since the points may not be
  140.      * in the same order in the bodies. Used internally to detect
  141.      * if two rotations are effectively the same.
  142.      */
  143.     public boolean equals(Object obj) {
  144.         // standard equals() technique 1
  145.         if (obj == this) return true;
  146.  
  147.         // standard equals() technique 2
  148.         // (null will be false)
  149.         if (!(obj instanceof Piece)) return false;
  150.         Piece other = (Piece) obj;
  151.  
  152.         // convert both arrays to list (for usage of 'contains' method)
  153.         List<TPoint> thisList = Arrays.asList(this.body);
  154.         List<TPoint> otherList = Arrays.asList(other.getBody());
  155.         // itterate and check if all points of this object occure in other piece
  156.         for (TPoint p : thisList)
  157.             if (!otherList.contains(p))
  158.                 return false;
  159.  
  160.         // at this point we have done checking and everything is correct
  161.         return true;
  162.     }
  163.  
  164.  
  165.     // String constants for the standard 7 tetris pieces
  166.     public static final String STICK_STR = "0 0 0 1  0 2  0 3";
  167.     public static final String L1_STR = "0 0    0 1  0 2  1 0";
  168.     public static final String L2_STR = "0 0    1 0 1 1  1 2";
  169.     public static final String S1_STR = "0 0    1 0  1 1  2 1";
  170.     public static final String S2_STR = "0 1    1 1  1 0  2 0";
  171.     public static final String SQUARE_STR = "0 0  0 1  1 0  1 1";
  172.     public static final String PYRAMID_STR = "0 0  1 0  1 1  2 0";
  173.  
  174.     // Indexes for the standard 7 pieces in the pieces array
  175.     public static final int STICK = 0;
  176.     public static final int L1 = 1;
  177.     public static final int L2 = 2;
  178.     public static final int S1 = 3;
  179.     public static final int S2 = 4;
  180.     public static final int SQUARE = 5;
  181.     public static final int PYRAMID = 6;
  182.  
  183.     /**
  184.      * Returns an array containing the first rotation of
  185.      * each of the 7 standard tetris pieces in the order
  186.      * STICK, L1, L2, S1, S2, SQUARE, PYRAMID.
  187.      * The next (counterclockwise) rotation can be obtained
  188.      * from each piece with the {@link #fastRotation()} message.
  189.      * In this way, the client can iterate through all the rotations
  190.      * until eventually getting back to the first rotation.
  191.      * (provided code)
  192.      */
  193.     public static Piece[] getPieces() {
  194.         // lazy evaluation -- create static array if needed
  195.         if (Piece.pieces == null) {
  196.             // use makeFastRotations() to compute all the rotations for each piece
  197.             Piece.pieces = new Piece[]{
  198.                     makeFastRotations(new Piece(STICK_STR)),
  199.                     makeFastRotations(new Piece(L1_STR)),
  200.                     makeFastRotations(new Piece(L2_STR)),
  201.                     makeFastRotations(new Piece(S1_STR)),
  202.                     makeFastRotations(new Piece(S2_STR)),
  203.                     makeFastRotations(new Piece(SQUARE_STR)),
  204.                     makeFastRotations(new Piece(PYRAMID_STR)),
  205.             };
  206.         }
  207.  
  208.  
  209.         return Piece.pieces;
  210.     }
  211.  
  212.  
  213.     /**
  214.      * Given the "first" root rotation of a piece, computes all
  215.      * the other rotations and links them all together
  216.      * in a circular list. The list loops back to the root as soon
  217.      * as possible. Returns the root piece. fastRotation() relies on the
  218.      * pointer structure setup here.
  219.      */
  220.     /*
  221.      Implementation: uses computeNextRotation()
  222.      and Piece.equals() to detect when the rotations have gotten us back
  223.      to the first piece.
  224.     */
  225.     private static Piece makeFastRotations(Piece root) {
  226.         // make 90 degree rotations for until we reached cycle
  227.         Piece rootRotate90 = root.computeNextRotation();
  228.         Piece rootRotate180 = rootRotate90.computeNextRotation();
  229.         Piece rootRotate270 = rootRotate180.computeNextRotation();
  230.  
  231.         // assign each piece to it's next piece and make cycle
  232.         root.next = rootRotate90;
  233.         rootRotate90.next = rootRotate180;
  234.         rootRotate180.next = rootRotate270;
  235.         rootRotate270.next = root;
  236.  
  237.         // return given piece with changed next piece
  238.         return root;
  239.     }
  240.  
  241.  
  242.     /**
  243.      * Given a string of x,y pairs ("0 0    0 1 0 2 1 0"), parses
  244.      * the points into a TPoint[] array.
  245.      * (Provided code)
  246.      */
  247.     private static TPoint[] parsePoints(String string) {
  248.         List<TPoint> points = new ArrayList<TPoint>();
  249.         StringTokenizer tok = new StringTokenizer(string);
  250.         try {
  251.             while (tok.hasMoreTokens()) {
  252.                 int x = Integer.parseInt(tok.nextToken());
  253.                 int y = Integer.parseInt(tok.nextToken());
  254.  
  255.                 points.add(new TPoint(x, y));
  256.             }
  257.         } catch (NumberFormatException e) {
  258.             throw new RuntimeException("Could not parse x,y string:" + string);
  259.         }
  260.  
  261.         // Make an array out of the collection
  262.         TPoint[] array = points.toArray(new TPoint[0]);
  263.         return array;
  264.     }
  265.  
  266.  
  267. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement