Question

I am trying to make a TicTacToe game for android . But i have the following problems. First and foremost i would like to implement threads to my app but i have not been succesfull ( have tried almost anything ) . Secondly i would like to know how to cope with these two errors ( i dont know if they are called errors) : Grow heap (frag case) to 65.24 MB for 2567824 byte-allocation , Skipped 118 frames ! The applcation may be doing too much work on its main thread ( though i think this would be solved with thread implementation )

public class DrawClass extends View {

int index;
int x, y, RectX, RectY;
// it will hold the rectangles dimensions depending on the screen dimensions
public Rect[] rectangles = new Rect[9];
// it will be our reference array as to what does each rectangle hold
char[] isFilledWith = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
// bitmaps
Bitmap empty, cross, circle;

// constructor
public DrawClass(Context context) {

    super(context);
    // setting bitmaps and calculating screen dimensions
    setBitmaps();
    Calculations(context);

}

public void setBitmaps() {// set the 3 bitmaps empty , circle , cross
    cross = BitmapFactory.decodeResource(getResources(), R.drawable.cross1);
    circle = BitmapFactory.decodeResource(getResources(),
            R.drawable.circle1);
    empty = BitmapFactory.decodeResource(getResources(), R.drawable.empty1);
}

@Override
public void onDraw(Canvas canvas) {

    super.onDraw(canvas);

    Paint paint = new Paint();
    // this for updates the canvas with the appropriate bitmaps cross , circle or empty 
    // depending on tyhe char array isFilledWith
    for (int i = 0; i < 9; i++) {
        if (isFilledWith[i] == ' ') {
            canvas.drawBitmap(empty, null, rectangles[i], null);
        } else if (isFilledWith[i] == 'X') {
            canvas.drawBitmap(cross, null, rectangles[i], null);
        } else if (isFilledWith[i] == 'O') {
            canvas.drawBitmap(circle, null, rectangles[i], null);
        }
        paint.setColor(Color.WHITE);
        canvas.drawLine(x, 0, x, 3 * y, paint);// 1h
        canvas.drawLine(2 * x, 0, 2 * x, 3 * y, paint);// 2h
        canvas.drawLine(0, y, 3 * x, y, paint);// 3h
        canvas.drawLine(0, 2 * y, 3 * x, 2 * y, paint);// 4h
    }
}

protected void Calculations(Context context) {
    /*
     * We calculate screen dimensions and fill the rectangles array with the
     * appropriate dimensions
     */
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    int width = metrics.widthPixels;
    int height = metrics.heightPixels;

    x = (width / 3);
    y = (height / 3);

    int rectanglescounter = 0;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            rectangles[rectanglescounter] = new Rect((x * j), (y * i),
                    ((x * j) + x), ((y * i) + y));
            if (rectanglescounter < 8)
                rectanglescounter++;
            else
                break;
        }
    }
    Log.d("Checks", "rectangles calculated");
}
// setter for the array 
public void setArray(int index, char character) {
    this.isFilledWith[index] = character;
}
// getter for the array
public char getArray(int index) {
    return isFilledWith[index];
}
// This method searches for tictactoe winning patterns .
public char checkForWinner() {
    if (isFilledWith[0] == isFilledWith[1]
            && isFilledWith[1] == isFilledWith[2]) {// 1st horizontal

        if (isFilledWith[0] == 'X') {
            Log.d("WINNING CHECK", "1st row win detected");
            return 'X';
        }
        if (isFilledWith[0] == 'O') {
            Log.d("WINNING CHECK", "1st row win detected");
            return 'O';
        }
    } else if (isFilledWith[3] == isFilledWith[4]
            && isFilledWith[4] == isFilledWith[5]) {// 2nd horizontal

        if (isFilledWith[3] == 'X') {
            ;
            Log.d("WINNING CHECK", "2st row win detected");
            return 'X';
        }
        if (isFilledWith[3] == 'O') {
            Log.d("WINNING CHECK", "2st row win detected");
            return 'O';
        }
    } else if (isFilledWith[6] == isFilledWith[7]
            && isFilledWith[7] == isFilledWith[8]) {// 3rd horizontal

        if (isFilledWith[6] == 'X') {
            Log.d("WINNING CHECK", "3st row win detected");
            return 'X';
        }
        if (isFilledWith[6] == 'O') {
            Log.d("WINNING CHECK", "3st row win detected");
            return 'O';
        }
    } else if (isFilledWith[0] == isFilledWith[3]
            && isFilledWith[3] == isFilledWith[6]) {// 1st vertical

        if (isFilledWith[0] == 'X') {
            Log.d("WINNING CHECK", "1st column win detected");
            return 'X';
        }
        if (isFilledWith[0] == 'O') {
            Log.d("WINNING CHECK", "1st column win detected");
            return 'O';
        }
    } else if (isFilledWith[1] == isFilledWith[4]
            && isFilledWith[4] == isFilledWith[7]) {// 2st vertical

        if (isFilledWith[1] == 'X') {

            Log.d("WINNING CHECK", "2st column win detected");
            return 'X';
        }
        if (isFilledWith[1] == 'O') {
            Log.d("WINNING CHECK", "2st column win detected");
            return 'O';
        }
    } else if (isFilledWith[2] == isFilledWith[5]
            && isFilledWith[5] == isFilledWith[8]) {// 3rd vertical

        if (isFilledWith[2] == 'X') {
            Log.d("WINNING CHECK", "3st column win detected");
            return 'X';
        }
        if (isFilledWith[2] == 'O') {
            Log.d("WINNING CHECK", "3st column win detected");
            return 'O';
        }
    } else if (isFilledWith[0] == isFilledWith[4]
            && isFilledWith[4] == isFilledWith[8]) {// diagonal
        if (isFilledWith[0] == 'X') {
            Log.d("WINNING CHECK", "1st diagonal win detected");
            return 'X';
        }
        if (isFilledWith[0] == 'O') {
            Log.d("WINNING CHECK", "1st diagonal win detected");
            return 'O';
        }
    } else if ((isFilledWith[2] == isFilledWith[4] && isFilledWith[4] == isFilledWith[6])) {// diagonal

        if (isFilledWith[2] == 'X') {
            Log.d("WINNING CHECK", "2nd diagonal win detected");
            return 'X';
        }
        if (isFilledWith[2] == 'O') {
            Log.d("WINNING CHECK", "2nd diagonal win detected");
            return 'O';
        }
    } else
        return ' ';
    return ' ';
}

}

public class NewGame extends Activity implements OnTouchListener {

DrawClass drawing;
int movecounter = 0;
int playercounter = 0;
static {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
            .permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    drawing = new DrawClass(this);
    //setting on touch events to correspond to this class ontouchlistener
    drawing.setOnTouchListener(this);

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
    setContentView(drawing);

}

@Override
public boolean onTouch(View v, MotionEvent event) {
    // TODO Auto-generated method stub

    int tempx = (int) event.getX();
    int tempy = (int) event.getY();

    // calculating where the user touched the screen so as to fill the char
    // array with the appropriate char 'x'or 'o' and then invalidate the
    // drawing
    for (int i = 0; i < 9; i++) {
        if (drawing.rectangles[i].contains(tempx, tempy)) {
            if (drawing.getArray(i) == ' ') {
                if (playercounter % 2 == 0)
                    drawing.setArray(i, 'X');
                else
                    drawing.setArray(i, 'O');
                playercounter++;
            } else if (drawing.getArray(i) != ' ')
                Toast.makeText(getApplicationContext(), "DONT CHEAT",
                        Toast.LENGTH_SHORT).show();

            // CHECKINK FOR WINNER or DRAW

            movecounter++;
            if (movecounter >= 5) {
                if (drawing.checkForWinner() == 'X') {
                    Toast.makeText(getApplicationContext(), "X WIN",
                            Toast.LENGTH_SHORT).show();
                    finish();
                }
                if (drawing.checkForWinner() == 'O') {
                    Toast.makeText(getApplicationContext(), "O WIN",
                            Toast.LENGTH_SHORT).show();
                    finish();
                }
                if (movecounter >= 9) {
                    Log.d("Entered Draw ", " ok ");
                    Toast.makeText(getApplicationContext(),
                            "IT'S A DRAW  ", Toast.LENGTH_SHORT).show();
                    finish();
                }
            }
            drawing.invalidate();
        } else
            continue;
    }
    return false;
}

}

Thank you in advance !

Was it helpful?

Solution

Skipped 118 frames ! The applcation may be doing too much work on its main thread you are doing to much work on the UI thread. Creating a thread or using asynctask to do the heavy work will solve this error. Take a look at this http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html, it is well explained.

OTHER TIPS

To help you with your struggles with threads and asynctasks you have to be more specific, but to find where the performance problem is you can use the profiling tools of Android.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top