⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 piece.java

📁 一个java的俄罗斯方块实现
💻 JAVA
字号:
/*  Author: <insert your name here>  ugrad.cs.ubc.ca address: <insert your ugrad.cs.ubc.ca e-mail address here>  Date: <insert date here>      By submitting this file, I acknowledge that the person whose name appears  above is the *only* author of the code required to solve this assignment.*/package cs111.tetris.data;import java.awt.*;import java.util.*;//// This is the "starter code" version of the Piece.java file.//// Most of this code is provided for you but there are a few places// left where you need to fill in some implementations.//// We have conveniently left all of the JavaDoc comments intact// so you wouldn't have to switch back and forth between your// JavaDoc browser and Java editor.//// Hint: Open Eclipse's "Tasks" view. All places in the code where// you need to do work are marked with TO DO comments which Eclipse// automatically finds for you and puts in the Tasks view///// To open Eclipse's task view go to menu Window >> Show View and // select "Tasks". Click some of the buttons in the top of the // toolbar and you'll find they let you filter the task to only // see those in the current file.///** * A Piece instance represents a tetris piece in a particular rotation. Each piece * is defined by a number of blocks known as its "body". The body is represented * by the (x, y) coordinates of its blocks, with the origin in the lower-left * corner. <br> * <img src="doc-files/piece.gif" border="0" height="92" width="102"><br> * So the body of this piece is defined by the (x, y) points :&nbsp; (0, 0), (1, * 0), (1, 1), (2, 1). * <p> * The Piece class and the Board class both measure things in this way -- * block by block with the origin in the lower-left corner. As a design * decision, the Piece and Board classes do not know about pixels -- they * measure everything block by block. Or put another way, all the knowledge of * pixels is isolated in the cs111.tetris.gui package. * <p> * Each piece responds to the methods like getWidth(), getHeight(), and * getBody() that allow the client to see the state of the piece. The getSkirt() * method returns an array that shows the lowest y value for each x value * across the piece ({0, 0, 1} for the piece above). The skirt makes it easier * to compute how a piece will come to land in the board. There are no methods * that change a piece -- it is "immutable". To allow the client to see the * various piece rotations that are available, the Piece class builds an array * of the standard tetris pieces internally -- available through the * Piece.getPieces() method. This array contains the first rotation of each of the * standard pieces. Starting with any piece, the nextRotation() method returns * the "next" piece object that represents the next clockwise rotation. * Enough calls to nextRotation() gets the caller back to the original piece. *  * @author Nick Parlante (revised by Kris De Volder 2007). */public class Piece {	/**	 * This array contains piece objects, one piece object for each of the	 * 7 standard tetris pieces in the first rotation.	 */	static private Piece[] pieces; 	private Point[] body;	private int[] skirt;	private int width;	private int height;	private Piece next; // "next" rotation	/**	 * Defines a new piece given the Points that make up its body. 	 * Does <b>not</b> set up the rotations through the next field.	 * <p>	 * This constructor is PRIVATE so clients can not create pieces themselves. 	 * If a client wants a piece object, they must use the {@link #getPieces()} 	 * method	 */	private Piece(Point[] points) {		body = points;		width = 0;		height = 0;		for (int i = 0; i < points.length; i++) {			//TODO: update width and height if needed.			//Take advantage of this loop to update the width and			//height fields.		}		//TODO: The code that initializes the skirt is missing.		//Implementation notes: 		//  You should create an array of the appropriate length to hold the		//  skirt values. 		//  Then loop through the skirt to initialize it with y values 		//  that are "high enough".		//  Then loop through the body and for each point in it,		//  update the appropriate spot in the skirt array		//  if the point has a smaller y value.	}	/**	 * Returns width of the piece measured in blocks.	 * @return the width of the piece measured in blocks.	 */	public int getWidth() {		return width;	}	/**	 * Returns the height of the piece measured in blocks.	 * @return the height of the piece measured in blocks.	 */	public int getHeight() {		return height;	}	/**	 * Returns a pointer to the piece's body. The caller should not modify this	 * array.	 */	public Point[] getBody() {		return body;	}	/**	 * Returns a pointer to the piece's skirt. For each x value across the	 * piece, the skirt gives the lowest y value in the body. This useful for	 * computing where the piece will land. The caller should not modify this	 * array.	 */	public int[] getSkirt() {		return skirt;	}	/**	 * Returns a piece that is 90 degrees clockwise rotated from the	 * receiver.	 * <p>	 * Implementation: The Piece class pre-computes all the rotations once. This	 * method just hops from one pre-computed rotation to the next in constant	 * time.	 */	public Piece nextRotation() {		return next;	}	/**	 * Returns an array containing the first rotation of each of the 7 standard	 * tetris pieces. The next (clockwise) rotation can be obtained from	 * each piece with the {@link #nextRotation()} method. In this way, the	 * client can iterate through all the rotations until eventually getting	 * back to the first rotation.	 */	public static Piece[] getPieces() {		if (pieces == null) {			// We create the array the first time it is asked for.			// (If pieces is still null it means we haven't created it yet).			pieces = new Piece[] {					pieceRow(new Piece(parsePoints("0 0	0 1	0 2	0 3"))), // 0					pieceRow(new Piece(parsePoints("0 0	0 1	0 2	1 0"))), // 1					pieceRow(new Piece(parsePoints("0 0	1 0	1 1	1 2"))), // 2					pieceRow(new Piece(parsePoints("0 0	1 0	1 1	2 1"))), // 3					pieceRow(new Piece(parsePoints("0 1	1 1	1 0	2 0"))), // 4					pieceRow(new Piece(parsePoints("0 0	0 1	1 0	1 1"))), // 5					pieceRow(new Piece(parsePoints("0 0	1 0	1 1	2 0"))), // 6			};		}		return pieces;	}	/**	 * Returns true if two pieces are the same -- their bodies contain the same	 * points. Interestingly, this is not the same as having exactly the same	 * body arrays, since the points may not be in the same order in the bodies.	 * Used internally to detect if two rotations are effectively the same.	 * 	 * This methods is only for internal use when we are generating the piece	 * rotations (we need to know when to stop).	 * 	 * Client code can use == to compare pieces, since our implementation makes	 * sure if two pieces are equal then they are actually == .	 */	private boolean isSameAs(Piece other) {		//TODO: implement this correctly		return false;		// Notes: You need a nested loop		// One loop goes over the body of this piece.		// For each point of this piece, you should be able to find		// an equal point in the body of the other piece.	}	/**	 * This is a helper method to setup the next field of a piece.	 * It creates all rotation of parameter piece and links all these	 * rotations together by making each of the piece's next field	 * point to the next rotation.	 * <p>	 * The tricky part is that we have to stop creating piece rotations	 * when we detect that rotating the piece gets us back to a piece	 * that has the exact same shape as the starting piece.	 * 	 * @param piece	 * @return piece (now with its next field properly set up and all rotations	 *               of this piece linked through their next fields into a	 *               cirular list).	 */	private static Piece pieceRow(Piece piece) {		final int MAX_ROTATIONS = 6; 		// MAX_ROATIONS is a safeguard against buggy student code.		// even if isSameAs is broken or if rotatePoints is broken, 		// the loop should stop after a fixed number of rotations.		Piece firstPiece = piece;		Piece currentPiece = piece;		Piece nextPiece = new Piece(currentPiece.rotatePoints());		int count = 0;		while (!nextPiece.isSameAs(firstPiece) && count<MAX_ROTATIONS) {			count++;			currentPiece.next = nextPiece;			currentPiece = nextPiece;			nextPiece = new Piece(currentPiece.rotatePoints());		}		// The loop ends when nextPiece is a piece object that		// represents the same piece as firstPiece.		// => nextPiece is discarded (because we shouldn't have two piece objects		// that represent the same piece in the same rotation).		// We will make currentPiece.next to point to the firstPiece		// This creates a kind of linked structure where each piece points		// to the next rotation and the last one points back to the beginning.		currentPiece.next = firstPiece;		return firstPiece;	}	/**	 * A helper to rotate a piece. It computes an array of rotated points from	 * this piece's body. (clockwise!)	 */	private Point[] rotatePoints() {		//TODO: implement this correctly		// 		//  This is tricky. Take piece of paper and a pencil. 		//  draw a piece and its clockwise rotation and try to find		//  a formula that for a given block tells the coordinates		//  where that block will end up in the rotated piece.		//		//  Maybe it helps to think in terms of "mirroring" transforms		//  that reflect a piece along one of its central axis.		//  (From math you may remember that composing two mirroring transforms		//  results in a rotation transform).		// Below is a "dummy" implementation. This is sufficient to avoid the		// tester from crashing but is not correct (it doesn't actually do 		// any rotation).		//		// Be careful, you should not change the body of this piece!		// A correct implementation should make a new array for the 		// rotated points.		return body;	}	/**	 * A helper method use to create the initial pieces:	 * <p>	 * Given a string of x,y pairs ("0 0 0 1 0 2 1 0"), parses the points into a	 * Point[] array. (Provided code)	 */	private static Point[] parsePoints(String string) {		ArrayList<Point> points = new ArrayList<Point>();		StringTokenizer tok = new StringTokenizer(string);		try {			while (tok.hasMoreTokens()) {				int x = Integer.parseInt(tok.nextToken());				int y = Integer.parseInt(tok.nextToken());				points.add(new Point(x, y));			}		} catch (NumberFormatException e) {			throw new RuntimeException("Could not parse x,y string:" + string); 		}		return points.toArray(new Point[points.size()]);	}	/**	 * By implementing the toString method you change the way piece objects	 * get printed out (e.g. with println). This may be convenient if	 * you are debugging because the Eclipse debugger will show whatever toString	 * returns when it displays the contents of a variable that has	 * a Piece object in it.	 */	public String toString() {		try {			boolean[][] pieceMap = new boolean[getHeight()][getWidth()];			for (int i = 0; i < body.length; i++)				pieceMap[body[i].y][body[i].x] = true;			StringBuffer buf = new StringBuffer(getHeight() * (getWidth() + 1));			for (int i = pieceMap.length - 1; i >= 0; i--) {				for (int j = 0; j < pieceMap[i].length; j++) {					buf.append(pieceMap[i][j] ? "#" : ".");				}				buf.append("\n");			}			return buf.toString();		}		catch (Throwable e) {			// If anything goes wrong in the code above this catch clause			// will get executed.			// This really shouldn't happen, but it might, for example,			// if your piece rotations are not correctly implemented.			// In that case we just fall back on Java's             // default toString implementation (inherited from Object).			return super.toString(); 		}	}	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -