9
\$\begingroup\$

Recently I have finished my first bigger Android project. I made a little Tetris App.

Here is a picture of my app in emulator:

enter image description here

My Tetris has following functions:

  1. fast drop down
  2. play tetris music
  3. start/pause button
  4. Gameover Screen
  5. View which shows next Piece
  6. "Levels" if you reach a particular score, level will be increase and pieces drops faster down
  7. 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

\$\endgroup\$
3
  • \$\begingroup\$ No Suggestions? Should i improve my Post? \$\endgroup\$
    – Marten
    Commented 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
    Commented Jun 21, 2018 at 18:17
  • 1
    \$\begingroup\$ A year is quite some time :) \$\endgroup\$ Commented Jul 16, 2019 at 7:47

2 Answers 2

4
\$\begingroup\$

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 booleans.

 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>();
\$\endgroup\$
8
  • \$\begingroup\$ thx didn't expect to get an answer after over one year \$\endgroup\$
    – Marten
    Commented 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\$ Commented 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\$ Commented 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\$ Commented Dec 4, 2020 at 15:03
  • \$\begingroup\$ developer.android.com/studio/write/… seems to be the recommended way to avoid enums \$\endgroup\$ Commented Dec 4, 2020 at 15:09
2
\$\begingroup\$

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 class EuclidPoint which groups and x and y value. You can offset some arithmic and euclidean operations in this class. For instance move, rotate, reflect, invert, and also variants specifically for x or y.
  • Use common names for your operations. turnAround is a rotation around a point (I think) so use rotate instead.
  • getMinXCoordinate could be made more extensible and usable if it would allow a dynamic number of values or an array, instead of int x1, int x2, int x3, int x4. It should also be called getMinCoordinate, why specific for x?
  • the constructor Piece(int f) should be extracted to a class named PieceFactory. This to avoid convolution of specific shapes with the general intend of the class.
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.