Recently I have finished my first bigger Android project. I made a little Tetris App.
Here is a picture of my app in emulator:
My Tetris has following functions:
- fast drop down
- play tetris music
- start/pause button
- Gameover Screen
- View which shows next Piece
- "Levels" if you reach a particular score, level will be increase and pieces drops faster down
- saving and loading highscore
I post the most important part of my code, if you need more code please see my git repo(https://github.com/Linus1905/Android-Tetris).
Piece.java:
public class Piece {
public int colorCode;
public int x1, y1;
public int x2, y2;
public int x3, y3;
public int x4, y4;
private Piece piece;
/*
creates a copy Instances of Piece
*/
public Piece(Piece piece) {
this.piece = piece;
this.x1= piece.x1; this.x2= piece.x2;
this.x3= piece.x3; this.x4= piece.x4;
this.y1= piece.y1; this.y2= piece.y2;
this.y3= piece.y3; this.y4= piece.y4;
}
/*
creates a Piece depending on colorCode
*/
public Piece(int f) {
switch (f) { // Square
case 1:
x1 = 0; y1 = 7;
x2 = 0; y2 = 8;
x3 = 1; y3 = 7;
x4 = 1; y4 = 8;
colorCode = 1;
break;
case 2: // z Piece
x1 = 0;y1 = 7;
x2 = 0;y2 = 8;
x3 = 1;y3 = 8;
x4 = 1;y4 = 9;
colorCode = 2;
break;
case 3: // I Piece
x1 = 0;y1 = 6;
x2 = 0;y2 = 7;
x3 = 0;y3 = 8;
x4 = 0;y4 = 9;
colorCode = 3;
break;
case 4: // T Piece
x1 = 0;y1 = 8;
x2 = 1;y2 = 7;
x3 = 1;y3 = 8;
x4 = 1;y4 = 9;
colorCode = 4;
break;
case 5: // S Piece
x1 = 0;y1 = 7;
x2 = 0;y2 = 8;
x3 = 1;y3 = 6;
x4 = 1;y4 = 7;
colorCode = 5;
break;
case 6: // J Piece
x1 = 0;y1 = 7;
x2 = 0;y2 = 8;
x3 = 0;y3 = 9;
x4 = 1;y4 = 9;
colorCode = 6;
break;
case 7: // L Piece
x1 = 0;y1 = 7;
x2 = 0;y2 = 8;
x3 = 0;y3 = 9;
x4 = 1;y4 = 7;
colorCode = 7;
break;
}
}
public void move(int x, int y) {
x1 = x1 + x;
y1 = y1 + y;
x2 = x2 + x;
y2 = y2 + y;
x3 = x3 + x;
y3 = y3 + y;
x4 = x4 + x;
y4 = y4 + y;
}
/*
turns piece around x1|y1 coordinates
*/
public void turnPiece() {
int tmp_x1, tmp_y1;
int tmp_x2, tmp_y2;
int tmp_x3, tmp_y3;
tmp_x1 = turn_AroundX1(y2);
tmp_y1 = turn_AroundY1(x2);
x2 = tmp_x1;
y2 = tmp_y1;
tmp_x2 = turn_AroundX1(y3);
tmp_y2 = turn_AroundY1(x3);
x3 = tmp_x2;
y3 = tmp_y2;
tmp_x3 = turn_AroundX1(y4);
tmp_y3 = turn_AroundY1(x4);
x4 = tmp_x3;
y4 = tmp_y3;
}
public int turn_AroundX1(int y) {
return x1 + y - y1;
}
public int turn_AroundY1(int x) {
return y1 - x + x1;
}
public int getMinXCoordinate(int x1, int x2, int x3, int x4) {
return Math.min(Math.min(x1,x2),Math.min(x3,x4));
}
}
GameBoard.java :
import android.graphics.Color;
import android.graphics.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
public class GameBoard {
private final int boardHeight =30;
private final int boardWidth=16;
private int gameBoard[][]=new int[boardHeight][boardWidth];
private final Random random = new Random();
private ArrayList<Piece> pieceList = new ArrayList<Piece>();
private final int number_of_Pieces = 7;
public GameBoard() {
pieceList.add(new Piece(random.nextInt(number_of_Pieces)+1));
pieceList.add(new Piece(random.nextInt(number_of_Pieces)+1));
}
/*
returns Color of x,y gameBoard cell
*/
public int codeToColor(int x, int y) {
if(gameBoard[x][y]==0) return Color.parseColor("#FFFF00"); // Yellow
if(gameBoard[x][y]==1) return Color.parseColor("#00FF00"); ; // Square Green
if(gameBoard[x][y]==2) return Color.parseColor("#FF00FF"); ; // zpiece Magenta
if(gameBoard[x][y]==3) return Color.parseColor("#0000FF"); ; // ipiece Blue
if(gameBoard[x][y]==4) return Color.parseColor("#00FFFF"); ; // tpiece Cyan
if(gameBoard[x][y]==5) return Color.parseColor("#ffbf00"); ; // spiece Orange
if(gameBoard[x][y]==6) return Color.parseColor("#BEBEBE"); ; // jpiece gray
if(gameBoard[x][y]==7) return Color.parseColor("#FF0000"); ; // lpiece Red
return -1;
}
public void clearGameBoard() {
for(int i=0; i<boardHeight; i++) {
for(int j=0; j<boardWidth; j++) {
gameBoard[i][j]= 0;
}
}
}
public ArrayList<Piece> getPieceList(){
return pieceList;
}
public Piece getCurrentPiece() {
return pieceList.get(pieceList.size() - 2);
}
public Piece getNextPiece() {
return pieceList.get(pieceList.size()-1);
}
private void placePiece(Piece currentPiece) {
gameBoard[currentPiece.x1][currentPiece.y1] = currentPiece.colorCode;
gameBoard[currentPiece.x2][currentPiece.y2] = currentPiece.colorCode;
gameBoard[currentPiece.x3][currentPiece.y3] = currentPiece.colorCode;
gameBoard[currentPiece.x4][currentPiece.y4] = currentPiece.colorCode;
}
private void deletePiece(Piece currentPiece) {
gameBoard[currentPiece.x1][currentPiece.y1] = 0;
gameBoard[currentPiece.x2][currentPiece.y2] = 0;
gameBoard[currentPiece.x3][currentPiece.y3] = 0;
gameBoard[currentPiece.x4][currentPiece.y4] = 0;
}
/*
checks if Piece can move in direction x|y
copy Piece and try to move it, return true
if it can move
*/
private boolean piece_Can_Move(Piece currentPiece, int x, int y) {
int tmp =0;
/*
copy piece coordinates
*/
Point p1 = new Point(currentPiece.x1, currentPiece.y1);
Point p2 = new Point(currentPiece.x2, currentPiece.y2);
Point p3 = new Point(currentPiece.x3, currentPiece.y3);
Point p4 = new Point(currentPiece.x4, currentPiece.y4);
Point tmp1 = new Point(currentPiece.x1+x, currentPiece.y1+y);
Point tmp2 = new Point(currentPiece.x2+x, currentPiece.y2+y);
Point tmp3 = new Point(currentPiece.x3+x, currentPiece.y3+y);
Point tmp4 = new Point(currentPiece.x4+x, currentPiece.y4+y);
ArrayList<Point> tmpPieceCoordinates = new ArrayList<Point>();
tmpPieceCoordinates.add(tmp1);
tmpPieceCoordinates.add(tmp2);
tmpPieceCoordinates.add(tmp3);
tmpPieceCoordinates.add(tmp4);
for(Point p : tmpPieceCoordinates ) {
if(p.x< boardHeight && p.y>=0 && p.y< boardWidth && gameBoard[p.x][p.y]==0) {
tmp++;
}
else if(p.equals(p1) || p.equals(p2) || p.equals(p3) || p.equals(p4)) {
tmp++;
}
}
if(tmp==4) {
return true;
}
return false;
}
/*
copy current Piece and check if it can rotate
if true return true
*/
private boolean piece_Can_Rotate(Piece currentPiece) {
int tmp =0;
ArrayList<Point> tmpPieceCoordinates = new ArrayList<Point>();
Piece tmpStein = new Piece(currentPiece);
Point p1 = new Point(currentPiece.x1, currentPiece.y1);
Point p2 = new Point(currentPiece.x2, currentPiece.y2);
Point p3 = new Point(currentPiece.x3, currentPiece.y3);
Point p4 = new Point(currentPiece.x4, currentPiece.y4);
tmpStein.turnPiece();
Point tmp1 = new Point(tmpStein.x1, tmpStein.y1);
Point tmp2 = new Point(tmpStein.x2, tmpStein.y2);
Point tmp3 = new Point(tmpStein.x3, tmpStein.y3);
Point tmp4 = new Point(tmpStein.x4, tmpStein.y4);
tmpPieceCoordinates .add(tmp1);
tmpPieceCoordinates .add(tmp2);
tmpPieceCoordinates .add(tmp3);
tmpPieceCoordinates .add(tmp4);
for(Point p : tmpPieceCoordinates ) {
if(p.x< boardHeight && p.x>=0 && p.y>=0 && p.y< boardWidth && gameBoard[p.x][p.y]==0) {
tmp++;
}
else if(p.equals(p1) || p.equals(p2) || p.equals(p3) || p.equals(p4)) {
tmp++;
}
}
if(tmp==4) { /* all four little squares are correct*/
return true;
}
return false;
}
private boolean can_Move_Left(Piece currentPiece) {
if(piece_Can_Move(currentPiece, 0, -1)==true) {
return true;
}
return false;
}
private boolean can_Move_Right(Piece currentPiece){
if(piece_Can_Move(currentPiece, 0,1) == true) {
return true;
}
return false;
}
public boolean can_Move_Down(Piece currentPiece) {
if(piece_Can_Move(currentPiece, 1,0)==true) {
return true;
}
return false;
}
private void movePiece(Piece currentPiece, int x, int y) {
deletePiece(currentPiece);
currentPiece.move(x, y);
placePiece(currentPiece);
}
public void moveRight(Piece currentPiece){
if(can_Move_Right(currentPiece)==true) {
movePiece(currentPiece, 0, 1);
}
}
public void moveLeft(Piece currentPiece){
if(can_Move_Left(currentPiece)==true) {
movePiece(currentPiece, 0, -1);
}
}
public void moveDown(Piece currentPiece) {
if(can_Move_Down(currentPiece)==true) {
movePiece(currentPiece, 1, 0);
}
}
public void fastDrop(Piece currentPiece) {
deletePiece(currentPiece);
while(can_Move_Down(currentPiece)==true) {
moveDown(currentPiece);
}
placePiece(currentPiece);
}
/*
turn all pieces until square piece
*/
public void rotatePiece(Piece currentPiece) {
if(piece_Can_Rotate(currentPiece)==true && currentPiece.colorCode!=1) {
deletePiece(currentPiece);
currentPiece.turnPiece();
placePiece(currentPiece);
}
placePiece(currentPiece);
}
public int clearRows() {
int deletedRowIndex;
int deletedRows=0;
ArrayList<Integer> arrayList = new ArrayList<Integer>();
for (int i = 0; i < boardHeight; i++) {
for (int j = boardWidth - 1; j >= 0; j--) {
if (gameBoard[i][j]==0) { // Row not full
break;
}
if (j == 0) {
deletedRowIndex = i;
arrayList.add(deletedRowIndex);
deletedRows++;
deleteRow(deletedRowIndex);
}
}
}
if (deletedRows >= 1) {
int highestRow = Collections.min(arrayList); // highest Row which can be cleared
int[][] gameBoardCopy = new int[highestRow][boardWidth];
for (int i = 0; i < gameBoardCopy.length; i++) {
for (int j = 0; j < gameBoardCopy[1].length; j++) {
gameBoardCopy[i][j] = gameBoard[i][j];
}
}
for (int i = 0; i < gameBoardCopy.length; i++) {
for (int j = 0; j < gameBoardCopy[1].length; j++) {
gameBoard[i+deletedRows][j] = gameBoardCopy[i][j];
}
}
}
return deletedRows;
}
public void deleteRow(int r){
for (int i = 0; i < boardWidth; i++) {
gameBoard[r][i] =0;
}
}
public boolean checkGameOver(Piece spielStein) {
if(can_Move_Down(spielStein) == false && spielStein.getMinXCoordinate(
spielStein.x1, spielStein.x2, spielStein.x3, spielStein.x4)<=1) {
return true;
}
return false;
}
public int getBoardHeight() {
return this.boardHeight;
}
public int getBoardWidth() {
return this.boardWidth;
}
}
Tetris.java:
public class Tetris extends View implements View.OnClickListener{
private MediaPlayer mediaPlayer;
private GameBoard gameBoard;
private MainActivity mainActivity;
private ImageButton rotateButton;
private ImageButton rightButton;
private ImageButton downButton;
private ImageButton leftButton;
private Timer timer = new Timer();
private Random random = new Random();
private ArrayList<Piece> pieceList;
private NextPieceView nextPieceView;
private TextView currentLevelTextView;
private TextView highscoreLevelTextView;
private TextView currentPunkteTextView;
private Points points;
private final int score=10;
private int timerPeriod =250;
private int level=0;
private boolean pause;
public Tetris(Context context, NextPieceView nextPieceView, GameBoard
gameBoard) {
super(context);
this.mainActivity = (MainActivity) context;
this.nextPieceView=nextPieceView;
this.gameBoard = gameBoard;
pause = mainActivity.getPause();
pieceList = gameBoard.getPieceList();
mediaPlayer = mainActivity.getMediaPlayer();
points = new Points(context);
currentLevelTextView = mainActivity.getCurrentLevelTextView();
highscoreLevelTextView = mainActivity.getHighscoreLevelTextView();
currentPunkteTextView = mainActivity.getPointTextView();
currentLevelTextView.append("0");
currentPunkteTextView.append("0");
highscoreLevelTextView.append(""+points.loadHighscore());
rotateButton = mainActivity.getRotateButton();
rightButton = mainActivity.getRightButton();
downButton = mainActivity.getDownButton();
leftButton = mainActivity.getLeftButton();
rotateButton .setOnClickListener(this);
rightButton.setOnClickListener(this);
downButton.setOnClickListener(this);
leftButton.setOnClickListener(this);
gameLoop();
}
public void gameLoop() {
timer.schedule(new TimerTask() {
@Override
public void run() {
mainActivity.runOnUiThread(new TimerTask() {
@Override
public void run() {
if(gameOver()==false && mainActivity.getPause()==false ) {
gameBoard.moveDown(gameBoard.getCurrentPiece());
if (gameBoard.can_Move_Down(gameBoard.getCurrentPiece()) == false) {
int deletedRows = gameBoard.clearRows();
gameBoard.clearRows();
pieceList.remove(gameBoard.getCurrentPiece());
pieceList.add(new Piece(random.nextInt(7) + 1));
nextPieceView.invalidate();
if (deletedRows> 0) {
points.setCurrentPoints(points.getCurrentPoints() + deletedRows * score);
int p = points.getCurrentPoints();
points.setLevel();
currentPunkteTextView.setText("Points:" +" "+ p);
currentLevelTextView.setText("Level" +" "+ points.getLevel());
if (points.getLevel() > points.loadHighscore()) {
points.writeHighscore();
highscoreLevelTextView.setText("Highscore:" +" "+ points.getLevel());
}
}
if(points.getLevel()>level) {
level++;
timerPeriod = timerPeriod - (points.getLevel()*20);
timer.cancel();
timer = new Timer();
gameLoop();
}
}
invalidate();
}
}
});
}
}, 0, timerPeriod);
}
public boolean gameOver() {
if( gameBoard.checkGameOver(gameBoard.getCurrentPiece())==true ) {
timer.cancel();
pieceList.clear();
gameBoard.clearGameBoard();
mainActivity.setPause(true);
mediaPlayer.stop();
showGameOverScreen();
return true;
}
return false;
}
public void showGameOverScreen() {
Intent intent = new Intent(this.getContext(), GameOverScreen.class);
getContext().startActivity(intent);
}
/*
change colorCode to spezific Color and paint on Gameboard
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint p = new Paint();
for (int x = 0; x < gameBoard.getBoardHeight(); x++) {
for (int y = 0; y < gameBoard.getBoardWidth(); y++) {
int color = gameBoard.codeToColor(x,y);
p.setColor(color);
canvas.drawRect(y*30, x*30, y*30+30, x*30+30,p);
}
}
}
/*
control falling pieces with buttons
*/
@Override
public void onClick(View v) {
if(mainActivity.getPause()==false) {
switch(v.getId()) {
case R.id.rightButton:
gameBoard.moveRight(gameBoard.getCurrentPiece());
invalidate();
break;
case R.id.downButton:
gameBoard.fastDrop(gameBoard.getCurrentPiece());
invalidate();
break;
case R.id.leftButton:
gameBoard.moveLeft(gameBoard.getCurrentPiece());
invalidate();
break;
case R.id.rotateButton:
gameBoard.rotatePiece(gameBoard.getCurrentPiece());
invalidate();
break;
}
}
}
}
MainActivity:
import android.graphics.Color;
import android.media.MediaPlayer;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Button buttonStart;
private ImageButton rotateButton;
private ImageButton rightButton;
private ImageButton downButton;
private ImageButton leftButton;
private TextView pointTextView;
private TextView highscoreLevelTextView;
private TextView currentLevelTextView;
private Tetris tetris;
private NextPieceView nextPieceView;
private boolean pause = true;
private MediaPlayer mediaPlayer;
private int stopMediaplayer;
private GameBoard gameBoard = new GameBoard();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource( this, Uri.parse("android.resource://com.example.admin.tetris/raw/tetrismusik"));
mediaPlayer.prepare();
} catch (Exception e) {e.printStackTrace();}
buttonStart = (Button) findViewById(R.id.buttonstart);
rotateButton = (ImageButton) findViewById(R.id.rotateButton);
rightButton = (ImageButton) findViewById(R.id.rightButton);
downButton = (ImageButton) findViewById(R.id.downButton);
leftButton = (ImageButton) findViewById(R.id.leftButton);
pointTextView = (TextView) findViewById(R.id.textViewPunkte);
highscoreLevelTextView= (TextView) findViewById(R.id.textViewHighscore);
currentLevelTextView = (TextView) findViewById(R.id.levelText);
nextPieceView = new NextPieceView(this, gameBoard);
RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(300,300);
nextPieceView.setLayoutParams(params1);
RelativeLayout relativeSteinAnzeige = (RelativeLayout) findViewById(R.id.relativelayout1);
nextPieceView.setBackgroundColor(Color.YELLOW);
relativeSteinAnzeige.addView(nextPieceView);
tetris = new Tetris(this,nextPieceView, gameBoard);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(480, 900);
tetris.setLayoutParams(params);
RelativeLayout relativeTetris = (RelativeLayout) findViewById(R.id.relativelayout);
tetris.setBackgroundColor(Color.YELLOW);
relativeTetris.addView(tetris);
buttonStart.setOnClickListener(new View.OnClickListener() {
int tmp=0;
@Override
public void onClick(View v) {
stopMediaplayer = mediaPlayer.getCurrentPosition();
tmp++;
if(buttonStart.getText().equals("Start")) {
buttonStart.setText("Pause");
pause = false;
if(tmp==1) {
mediaPlayer.start();
mediaPlayer.setLooping(true);
} else if(tmp>1) {
mediaPlayer.seekTo(stopMediaplayer);
mediaPlayer.start();
}
}
else if(buttonStart.getText().equals("Pause")) {
buttonStart.setText("Start");
pause = true;
mediaPlayer.pause();
}
}
});
}
@Override
public void onRestart() {
super.onRestart();
pause = false;
mediaPlayer.seekTo(stopMediaplayer);
mediaPlayer.start();
}
@Override
public void onPause() {
super.onPause();
pause = true;
mediaPlayer.stop();
mediaPlayer.pause();
stopMediaplayer = mediaPlayer.getCurrentPosition();
}
@Override
public void onDestroy() {
super.onDestroy();
finish();
}
public ImageButton getRightButton() { return rightButton;}
public ImageButton getDownButton() { return downButton;}
public ImageButton getLeftButton() { return leftButton;}
public ImageButton getRotateButton() { return rotateButton; }
public boolean getPause() { return pause;}
public void setPause(boolean pause) { this.pause=pause;}
public TextView getHighscoreLevelTextView() { return highscoreLevelTextView;
}
public TextView getPointTextView() { return pointTextView; }
public TextView getCurrentLevelTextView() { return currentLevelTextView;}
public MediaPlayer getMediaPlayer() { return mediaPlayer; }
}
All help and suggestions would be really appreciated
-
\$\begingroup\$ No Suggestions? Should i improve my Post? \$\endgroup\$Marten– Marten2018年06月21日 07:51:29 +00:00Commented Jun 21, 2018 at 7:51
-
3\$\begingroup\$ just give it time. Some reviews take more time to write. Larger questions take longer to read and understand. Although with that much code more explaination of what is happening in the code would facilitate a faster/better response. \$\endgroup\$Summer– Summer2018年06月21日 18:17:05 +00:00Commented Jun 21, 2018 at 18:17
-
1\$\begingroup\$ A year is quite some time :) \$\endgroup\$Rob Audenaerde– Rob Audenaerde2019年07月16日 07:47:11 +00:00Commented Jul 16, 2019 at 7:47
2 Answers 2
Good job separating concerns
Your tetris game-board model, piece and UI code is nicely separated in classes, so each one has its own responibility. Well done!
Don't use magic values, use Enum
public Piece(int f)
This switches on a magic value of f
. Piece
is a excellent candidate for Enum
!
public enum Piece { L, J, T, Z, I, ... }
Enum works as class as well, so you can add a constructor:
public Piece ( int x1, int y1, int x2, .... )
Then the enum becomes:
public enum Piece {
L (0,7,0,8....);
J (....)
}
Your gameBoard
can store which type of Piece
it contains:
private Piece gameBoard[][]=new Piece[boardHeight][boardWidth];
The color of a Piece
could also be stored in the Piece
itself, so you don't need magic lookup methods.
Use Java naming conventions
For example, take a look here: https://www.geeksforgeeks.org/java-naming-conventions/
This method turn_AroundX1
should be called turnAroundX1
Don't duplicate boolean
s.
if(tmp==4) {
return true;
}
return false;
If tmp = 4, the code is:
if(true) {
return true;
}
return false;
Better to rewrite to:
return (tmp == 4);
Use proper variable names & simplest interface as possible.
I saw this:
ArrayList<Integer> arrayList = new ArrayList<Integer>();
What does this 'arrayList' contain? That would be a better variable name.
Also, the rest of the code doesn't care how the List
is implemented, as long as it behaves like a list. It is best practice to write:
List<Integer> listOfAwesomeThings = new ArrayList<Integer>();
-
\$\begingroup\$ thx didn't expect to get an answer after over one year \$\endgroup\$Marten– Marten2019年07月22日 11:18:19 +00:00Commented Jul 22, 2019 at 11:18
-
2\$\begingroup\$ Somehow your question ended up in my 'interesting' queue. Thought I might as well answer it a bit ;) \$\endgroup\$Rob Audenaerde– Rob Audenaerde2019年07月22日 11:20:10 +00:00Commented Jul 22, 2019 at 11:20
-
\$\begingroup\$ just a sidehint, the use of enums in android is(or at least used to be) discouraged, for it takes up so much memory \$\endgroup\$A Honey Bustard– A Honey Bustard2020年12月04日 15:01:58 +00:00Commented Dec 4, 2020 at 15:01
-
\$\begingroup\$ @AHoneyBustard do you have a source for this? Enum is just a class, and an instance is just an instance. \$\endgroup\$Rob Audenaerde– Rob Audenaerde2020年12月04日 15:03:42 +00:00Commented Dec 4, 2020 at 15:03
-
\$\begingroup\$ developer.android.com/studio/write/… seems to be the recommended way to avoid enums \$\endgroup\$A Honey Bustard– A Honey Bustard2020年12月04日 15:09:31 +00:00Commented Dec 4, 2020 at 15:09
Do something about the code formatting (intendation) in this question. The code reads really awful.
Review of Piece
Piece
has an instance variable of the same type, which is stored through the copy constructor, but unused in the class.- Many variables belong together
x1, y1
etc.. Consider creating a classEuclidPoint
which groups andx
andy
value. You can offset some arithmic and euclidean operations in this class. For instancemove
,rotate
,reflect
,invert
, and also variants specifically forx
ory
. - Use common names for your operations.
turnAround
is a rotation around a point (I think) so userotate
instead. getMinXCoordinate
could be made more extensible and usable if it would allow a dynamic number of values or an array, instead ofint x1, int x2, int x3, int x4
. It should also be calledgetMinCoordinate
, why specific forx
?- the constructor
Piece(int f)
should be extracted to a class namedPieceFactory
. This to avoid convolution of specific shapes with the general intend of the class.
Explore related questions
See similar questions with these tags.