0

Hi I'm trying to build a simple game, called SOS. It's a slightly more complicated version of tic tac toe. The goal of the game is to complete the word SOS. Players take turns placing letters on a grid. If one player completes the word SOS they score a point and they get to go again until they don't score any points. I wrote the logic for a computer player and now I'm try to figure out how to update the UI in these steps.
The user is blocked from interacting with the game board ( Table View ) during computers turn. The computer places a letter on the board and the border is high lighted for half a second to show where the computer is placing it's letter. If the computer scores a point it places the next letter on the board half a second later. I'm having trouble keeping the user from interacting with the board (TableView) while the computer is updating the game board. For example I tried to block all the tiles with view.setEnabled method to false, then using the postDelayed method to high light the tile where the computer is making it's move, after which I used post delayed again to reset the tile to a S or O. However the post delayed method is running on a separate thread and the view.setEnabled code is executed to enabled before the postDelayed method finishes. I think if I used AsyncTask I'll have the same problem where onPostExecute method will execute before the postDelayed method finishes. Does anyone have any suggestions on how I can accomplish this, I've been searching on here but haven't found anything. Thanks for your time.

public Object[] computerMove() {
    // remove players ability to change board
    enableDisableView(game_board, false);   

    // used to tell if the move var is null and the
    // game is over
    boolean end = false;

    //declare and initialize the computer player
    AI computer = new AI(game, difficulty);

    // returns null if board is full
    Object[] move = computer.move();

    if (move == null) {         
        end = true;
    }   

    if (!end && move[0] instanceof Integer &&  move[1] instanceof Integer
            && move[2] instanceof Types) {
        final int row = (Integer) move[0];
        final int col = (Integer) move[1];
        Types type = (Types) move[2];           

        // set the tile background image
        tiles[row][col].setTile(type);

        // set occupied
        tiles[row][col].setOccupied(true);                  
        // update the array in the GamePlayClass
        game.placeOnBoard(type, row, col);          

        //add a delay and show where button is placed
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
           @Override
           public void run() {
               tiles[row][col].setTile(tiles[row][col].getType());
           }
         }, 1000);
        handler.postDelayed(new Runnable() {
           @Override
           public void run() {
               tiles[row][col].setBackgroundColor(getResources().getColor(R.color.white));;
           }
         }, 100);

        //find points and then update score
        int points = scorePoints();                                     
        updateScore(points);

    }// end of if statement checking for a null move

    // one less tile remaining,
    --remainingTiles;
    game.decrementRemainingTiles();

    //highlight the correct player
    if (game.getTurn() == 0) {
        // highlight background to indicate turn
        player1Label.setBackgroundColor(getResources().getColor(
                R.color.tomato));
        player1Score.setBackgroundColor(getResources().getColor(
                R.color.tomato));

        player2Label.setBackgroundColor(color.black);
        player2Score.setBackgroundColor(color.black);

    } else {
        player2Label.setBackgroundColor(getResources().getColor(
                R.color.tomato));
        player2Score.setBackgroundColor(getResources().getColor(
                R.color.tomato));

        player1Label.setBackgroundColor(color.black);
        player1Score.setBackgroundColor(color.black);
    }

    // restore players ability to change board
    enableDisableView(game_board, true);    

    return move;

}

//copied from stack overflow 
//http://stackoverflow.com/questions/3818013/is-there-a-way-to-disable-all-the-items-in-a-specific-layout-programmaticaly/5257691#5257691
private void enableDisableView(View view, boolean enabled) {
    view.setEnabled(enabled);

    if ( view instanceof ViewGroup ) {
        ViewGroup group = (ViewGroup)view;

        for ( int idx = 0 ; idx < group.getChildCount() ; idx++ ) {
            enableDisableView(group.getChildAt(idx), enabled);
        }
    }
}
Boo
  • 377
  • 6
  • 18
  • Enable the view after you finish updating its color in the UI thread. – Chris Stratton Jul 30 '14 at 18:31
  • Does that mean run the postDelayed method on the UI thread instead of starting a separate thread? – Boo Jul 30 '14 at 20:48
  • Ok I think I understand, your saying just move the enableDisableView method inside the postDelayed method and after the update. It works, thanks for your suggestion – Boo Jul 31 '14 at 15:20

1 Answers1

0

Ok so I found a solution. First I found all the moves the computer player could make and stored the info in Move objects and added each move to a array list. Second I recursively ( Handler post delay not work in for loop ) iterated through the arraylist, updating the UI with a handler and the postDelayed method.

public void computerPlayerUpdateUI(int index, boolean done, int score) {

    // repeat loop until no more points are found
    while (game.getTurn() == 1 && !done) {

        Object[] moveObj = computerMove();
        int points = 0;
        int player = game.getTurn();

        if (moveObj != null) {
            // calculate points and add to moves arraylist
            points = scorePoints();

            Move move = new Move(moveObj, points, player);
            moves.add(move);
        }

        if (points == 0) {
            // exit loop and update user interface
            done = true;
        }
    }
    if (index < moves.size()) {

            final int x = index;
            final int nextIndex = x+1;
            final int updateScore = moves.get(x).getScore() + score;

            // add a delay and show where button is placed
            final int row = (Integer) moves.get(x).getObject()[0];
            final int col = (Integer) moves.get(x).getObject()[1];
            Types type = (Types) moves.get(x).getObject()[2];

            // set the tile background image
            tiles[row][col].setTile(type);

            // set occupied
            tiles[row][col].setOccupied(true);

            // add a delay and show where button is placed
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    tiles[row][col].setTile(tiles[row][col].getType());
                    player2Score.setText(updateScore + "");
                    // restore players ability to change board
                    enableDisableView(game_board, true);
                    computerPlayerUpdateUI(nextIndex, true, updateScore);
                }
            }, 1000);
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    tiles[row][col].setBackgroundColor(getResources()
                            .getColor(R.color.white));

                }
            }, 100);

            // highlight the correct player
            if (game.getTurn() == 0) {
                // highlight background to indicate turn
                player1Label.setBackgroundColor(getResources().getColor(
                        R.color.tomato));
                player1Score.setBackgroundColor(getResources().getColor(
                        R.color.tomato));

                player2Label.setBackgroundColor(color.black);
                player2Score.setBackgroundColor(color.black);

            } else {
                player2Label.setBackgroundColor(getResources().getColor(
                        R.color.tomato));
                player2Score.setBackgroundColor(getResources().getColor(
                        R.color.tomato));

                player1Label.setBackgroundColor(color.black);
                player1Score.setBackgroundColor(color.black);
        }

    }// end of if
    //check for game over only once at end of recursion
    if (index == (moves.size() - 1)) {
        gameOver();
    }
}// end if



public Object[] computerMove() {
    // remove players ability to change board
    enableDisableView(game_board, false);   

    // used to tell if the move var is null and the
    // game is over
    boolean end = false;

    //initialize the computer player clones the GamePlay object game
    final AI computer = new AI(game, difficulty);               

    // returns null if board is full
    Object[] move = computer.move();

    if (move == null) {         
        end = true;
    }

    if (!end && move[0] instanceof Integer &&  move[1] instanceof Integer
            && move[2] instanceof Types) {
        final int row = (Integer) move[0];
        final int col = (Integer) move[1];
        Types type = (Types) move[2];           


        // update the array in the GamePlayClass
        game.placeOnBoard(type, row, col);                          

    }// end of if statement checking for a null move

    // one less tile remaining,
    --remainingTiles;
    game.decrementRemainingTiles();         

    return move;

}
Community
  • 1
  • 1
Boo
  • 377
  • 6
  • 18