Java tutorial
/* Copyright (C) 2013 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.yaniv.online; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.CountDownTimer; import android.os.Handler; import android.support.v4.content.ContextCompat; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.games.Games; import com.google.android.gms.games.GamesStatusCodes; import com.google.android.gms.games.GamesActivityResultCodes; import com.google.android.gms.games.multiplayer.Invitation; import com.google.android.gms.games.multiplayer.Multiplayer; import com.google.android.gms.games.multiplayer.OnInvitationReceivedListener; import com.google.android.gms.games.multiplayer.Participant; import com.google.android.gms.games.multiplayer.realtime.RealTimeMessage; import com.google.android.gms.games.multiplayer.realtime.RealTimeMessageReceivedListener; import com.google.android.gms.games.multiplayer.realtime.Room; import com.google.android.gms.games.multiplayer.realtime.RoomConfig; import com.google.android.gms.games.multiplayer.realtime.RoomStatusUpdateListener; import com.google.android.gms.games.multiplayer.realtime.RoomUpdateListener; import com.google.example.games.basegameutils.BaseGameUtils; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.Vector; public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, View.OnClickListener, RealTimeMessageReceivedListener, RoomStatusUpdateListener, RoomUpdateListener, OnInvitationReceivedListener { /* * API INTEGRATION SECTION. This section contains the code that integrates * the game with the Google Play game services API. */ final static String TAG = "[Yaniv]"; // Request codes for the UIs that we show with startActivityForResult: final static int RC_SELECT_PLAYERS = 10000; final static int RC_INVITATION_INBOX = 10001; final static int RC_WAITING_ROOM = 10002; long timeToPCSleep = 2000; // Request code used to invoke sign in user interactions. private static final int RC_SIGN_IN = 9001; // Client used to interact with Google APIs. private GoogleApiClient mGoogleApiClient; // Are we currently resolving a connection failure? private boolean mResolvingConnectionFailure = false; // Has the user clicked the sign-in button? private boolean mSignInClicked = false; // Set to true to automatically start the sign in flow when the Activity starts. // Set to false to require the user to click the button in order to sign in. private boolean mAutoStartSignInFlow = true; // Room ID where the currently active game is taking place; null if we're // not playing. String mRoomId = null; // Are we playing in multiplayer mode? boolean mMultiplayer = false; // The participants in the currently active game ArrayList<Participant> mParticipants = null; static ArrayList<PCPlayer> mPCParticipants = null; // My participant ID in the currently active game static String mMyId = null; // If non-null, this is the id of the invitation we received via the // invitation listener String mIncomingInvitationId = null; int cardsID[] = { R.id.my_card_1, R.id.my_card_2, R.id.my_card_3, R.id.my_card_4, R.id.my_card_5 }; int cardsTopID[] = { R.id.player_top_card_1, R.id.player_top_card_2, R.id.player_top_card_3, R.id.player_top_card_4, R.id.player_top_card_5 }; int cardsRightID[] = { R.id.player_right_card_1, R.id.player_right_card_2, R.id.player_right_card_3, R.id.player_right_card_4, R.id.player_right_card_5 }; int cardsLeftID[] = { R.id.player_left_card_1, R.id.player_left_card_2, R.id.player_left_card_3, R.id.player_left_card_4, R.id.player_left_card_5 }; int droppedID[] = { R.id.dropped_1, R.id.dropped_2, R.id.dropped_3, R.id.dropped_4, R.id.dropped_5 }; private int myCardWidthParam; private int topCardWidthParam; private boolean readyToStartGame; private int[] highscores; int mStatusCode; Room mRoom; Vector<Integer> myCardsDrop = new Vector<>(); Vector<String> myCardsDropToString = new Vector<>(); boolean yaniv = false; // cell[0] cell[X] WHAT AND WHO EXPLAIN // TYPE // 0 1 Owner in the initial of the game. Anybody on the game when cards over. Shuffle the cards and resend them on cell 1. Evreybody needs to load the new cards! // 1 1 owner only in start Sending the self cards to the other players // 2 1 participant when finish playing - is Cards sending the drop cards and update on each participant // 3 1 participant when finish playing - take from 0-primary 1-deck take from the primary or deck (and update in each screen). // 3 2 participant when finish playing - Cards he take (only if 0) remove the cards from the screen // 4 1 Anybody message indicates whether it's a final score or not // 4 2 Anybody The score // 4 3 Anybody Whos turn // 4 4 Anybody CANCEL FOR NOW last turn (taking from the deck or the primary pot). // 4 4 Anybody last Drop Type // 5 1 Owner in the initial of the game. Anybody on the game when cards over. Sending the last drop cards to the primary deck. // 6 1 Anybody when finished is turn send his new cards Sending the new myCards Vector to all participants. // 7 1 Anybody when declare yaniv Sending a declare message to other participants. byte[] mMsgBuf = new byte[5]; //*/*/*/*/*/* Yaniv */*/*/*/*/*/ private static byte turn; //True if the participant is the owner of the game private boolean owner = false; private static final Type DATA_TYPE_M_PARTICIPANT_CARDS = new TypeToken<Map<String, Vector<Card>>>() { }.getType(); private static final Type DATA_TYPE_CARD_DECK = new TypeToken<Cards>() { }.getType(); private static final Type DATA_TYPE_PRIMARY_DECK = new TypeToken<Stack<ArrayList<Card>>>() { }.getType(); private static final Type DATA_TYPE_MY_CARDS = new TypeToken<Vector<Card>>() { }.getType(); private static final Type DATA_TYPE_CARDS = new TypeToken<ArrayList<Card>>() { }.getType(); private static final Type DATA_TYPE_STRING = new TypeToken<String>() { }.getType(); //Participants common objects private static Stack<ArrayList<Card>> primaryDeck; private static Cards cardDeck; // Score of other participants. We update this as we receive their scores // from the network. static Map<String, Vector<Card>> mParticipantCards = new HashMap<>(); Map<String, String> mParticipantPlayerPosition = new HashMap<>(); Map<String, Boolean> readyToPlayPlayers = new HashMap<>(); // Participants who sent us their final score. Set<String> mFinishedParticipants = new HashSet<>(); private int yanivMinScore = 5; //Participant objects private Vector<Card> myCards; private int mySum; private static int lastDropType = 1; private int myLastDropType; private int[] invalidDrop = { 999 }; EditText takeCardEditText; Map<String, Integer> cardsDrawable = new HashMap<>(); CountDownTimer cdt; public static Context baseContext; static MainActivity instance; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); instance = this; setContentView(R.layout.activity_main); baseContext = getBaseContext(); updateLayoutParams(); // Create the Google Api Client with access to Games mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this) .addOnConnectionFailedListener(this).addApi(Games.API).addScope(Games.SCOPE_GAMES).build(); // set up a click listener for everything we care about for (int id : CLICKABLES) { findViewById(id).setOnClickListener(this); } initialCardsDrawable(); } private void updateLayoutParams() { // Save my layout size LinearLayout layout = (LinearLayout) findViewById(R.id.myCardsLayout); // Gets the layout params that will allow you to resize the layout ViewGroup.LayoutParams params = layout.getLayoutParams(); myCardWidthParam = params.width / 5; // Save top player layout size layout = (LinearLayout) findViewById(R.id.player_top); // Gets the layout params that will allow you to resize the layout params = layout.getLayoutParams(); topCardWidthParam = params.width / 5; } @Override public void onClick(View v) { Intent intent; switch (v.getId()) { case R.id.button_single_player: case R.id.button_single_player_2: // play a single-player game resetGameVars(); startGame(false); break; case R.id.button_sign_in: // user wants to sign in // Check to see the developer who's running this sample code read the instructions :-) // NOTE: this check is here only because this is a sample! Don't include this // check in your actual production app. if (!BaseGameUtils.verifySampleSetup(this, R.string.app_id)) { Log.w(TAG, "*** Warning: setup problems detected. Sign in may not work!"); } // start the sign-in flow Log.d(TAG, "Sign-in button clicked"); mSignInClicked = true; mGoogleApiClient.connect(); mMultiplayer = true; break; case R.id.button_sign_out: // user wants to sign out // sign out. Log.d(TAG, "Sign-out button clicked"); mSignInClicked = false; Games.signOut(mGoogleApiClient); mGoogleApiClient.disconnect(); switchToScreen(R.id.screen_sign_in); mMultiplayer = true; break; case R.id.button_invite_players: // show list of invitable players intent = Games.RealTimeMultiplayer.getSelectOpponentsIntent(mGoogleApiClient, 1, 3); switchToScreen(R.id.screen_wait); startActivityForResult(intent, RC_SELECT_PLAYERS); mMultiplayer = true; break; case R.id.button_see_invitations: // show list of pending invitations intent = Games.Invitations.getInvitationInboxIntent(mGoogleApiClient); switchToScreen(R.id.screen_wait); startActivityForResult(intent, RC_INVITATION_INBOX); mMultiplayer = true; break; case R.id.button_accept_popup_invitation: // user wants to accept the invitation shown on the invitation popup // (the one we got through the OnInvitationReceivedListener). acceptInviteToRoom(mIncomingInvitationId); mIncomingInvitationId = null; mMultiplayer = true; break; case R.id.button_quick_game: // user wants to play against a random opponent right now startQuickGame(); mMultiplayer = true; break; } } void startQuickGame() { mMultiplayer = true; // quick-start a game with 1 randomly selected opponent final int MIN_OPPONENTS = 1, MAX_OPPONENTS = 1; Bundle autoMatchCriteria = RoomConfig.createAutoMatchCriteria(MIN_OPPONENTS, MAX_OPPONENTS, 0); RoomConfig.Builder rtmConfigBuilder = RoomConfig.builder(this); rtmConfigBuilder.setMessageReceivedListener(this); rtmConfigBuilder.setRoomStatusUpdateListener(this); rtmConfigBuilder.setAutoMatchCriteria(autoMatchCriteria); switchToScreen(R.id.screen_wait); keepScreenOn(); resetGameVars(); Games.RealTimeMultiplayer.create(mGoogleApiClient, rtmConfigBuilder.build()); } @Override public void onActivityResult(int requestCode, int responseCode, Intent intent) { super.onActivityResult(requestCode, responseCode, intent); switch (requestCode) { case RC_SELECT_PLAYERS: // we got the result from the "select players" UI -- ready to create the room handleSelectPlayersResult(responseCode, intent); break; case RC_INVITATION_INBOX: // we got the result from the "select invitation" UI (invitation inbox). We're // ready to accept the selected invitation: handleInvitationInboxResult(responseCode, intent); break; case RC_WAITING_ROOM: // we got the result from the "waiting room" UI. if (responseCode == Activity.RESULT_OK) { // ready to start playing Log.d(TAG, "Starting game (waiting room returned OK)."); startGame(true); } else if (responseCode == GamesActivityResultCodes.RESULT_LEFT_ROOM) { // player indicated that they want to leave the room leaveRoom(); } else if (responseCode == Activity.RESULT_CANCELED) { // Dialog was cancelled (user pressed back key, for instance). In our game, // this means leaving the room too. In more elaborate games, this could mean // something else (like minimizing the waiting room UI). leaveRoom(); } break; case RC_SIGN_IN: Log.d(TAG, "onActivityResult with requestCode == RC_SIGN_IN, responseCode=" + responseCode + ", intent=" + intent); mSignInClicked = false; mResolvingConnectionFailure = false; if (responseCode == RESULT_OK) { mGoogleApiClient.connect(); } else { BaseGameUtils.showActivityResultError(this, requestCode, responseCode, R.string.signin_other_error); } break; } super.onActivityResult(requestCode, responseCode, intent); } // Handle the result of the "Select players UI" we launched when the user clicked the // "Invite friends" button. We react by creating a room with those players. private void handleSelectPlayersResult(int response, Intent data) { if (response != Activity.RESULT_OK) { Log.w(TAG, "*** select players UI cancelled, " + response); switchToMainScreen(); return; } Log.d(TAG, "Select players UI succeeded."); // get the invitee list final ArrayList<String> invitees = data.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS); Log.d(TAG, "Invitee count: " + invitees.size()); // get the automatch criteria Bundle autoMatchCriteria = null; int minAutoMatchPlayers = data.getIntExtra(Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0); int maxAutoMatchPlayers = data.getIntExtra(Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0); if (minAutoMatchPlayers > 0 || maxAutoMatchPlayers > 0) { autoMatchCriteria = RoomConfig.createAutoMatchCriteria(minAutoMatchPlayers, maxAutoMatchPlayers, 0); Log.d(TAG, "Automatch criteria: " + autoMatchCriteria); } // create the room Log.d(TAG, "Creating room..."); RoomConfig.Builder rtmConfigBuilder = RoomConfig.builder(this); rtmConfigBuilder.addPlayersToInvite(invitees); rtmConfigBuilder.setMessageReceivedListener(this); rtmConfigBuilder.setRoomStatusUpdateListener(this); if (autoMatchCriteria != null) { rtmConfigBuilder.setAutoMatchCriteria(autoMatchCriteria); } switchToScreen(R.id.screen_wait); keepScreenOn(); resetGameVars(); Games.RealTimeMultiplayer.create(mGoogleApiClient, rtmConfigBuilder.build()); Log.d(TAG, "Room created, waiting for it to be ready..."); } // Handle the result of the invitation inbox UI, where the player can pick an invitation // to accept. We react by accepting the selected invitation, if any. private void handleInvitationInboxResult(int response, Intent data) { if (response != Activity.RESULT_OK) { Log.w(TAG, "*** invitation inbox UI cancelled, " + response); switchToMainScreen(); return; } Log.d(TAG, "Invitation inbox UI succeeded."); Invitation inv = data.getExtras().getParcelable(Multiplayer.EXTRA_INVITATION); // accept invitation acceptInviteToRoom(inv.getInvitationId()); } // Accept the given invitation. void acceptInviteToRoom(String invId) { // accept the invitation Log.d(TAG, "Accepting invitation: " + invId); RoomConfig.Builder roomConfigBuilder = RoomConfig.builder(this); roomConfigBuilder.setInvitationIdToAccept(invId).setMessageReceivedListener(this) .setRoomStatusUpdateListener(this); switchToScreen(R.id.screen_wait); keepScreenOn(); resetGameVars(); Games.RealTimeMultiplayer.join(mGoogleApiClient, roomConfigBuilder.build()); } // Activity is going to the background. We have to leave the current room. @Override public void onStop() { Log.d(TAG, "**** got onStop"); // if we're in a room, leave it. // leaveRoom(); // stop trying to keep the screen on // stopKeepingScreenOn(); // if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) { // switchToMainScreen(); // } else { // switchToScreen(R.id.screen_sign_in); // } super.onStop(); } // Activity just got to the foreground. We switch to the wait screen because we will now // go through the sign-in flow (remember that, yes, every time the Activity comes back to the // foreground we go through the sign-in flow -- but if the user is already authenticated, // this flow simply succeeds and is imperceptible). @Override public void onStart() { if (mGoogleApiClient == null) { switchToScreen(R.id.screen_sign_in); } else if (!mGoogleApiClient.isConnected()) { Log.d(TAG, "Connecting client."); switchToScreen(R.id.screen_wait); mGoogleApiClient.connect(); } else { Log.w(TAG, "GameHelper: client was already connected on onStart()"); } super.onStart(); (findViewById(R.id.button_score)).setClickable(false); } // Handle back key to make sure we cleanly leave a game if we are in the middle of one @Override public boolean onKeyDown(int keyCode, KeyEvent e) { if (keyCode == KeyEvent.KEYCODE_BACK && mCurScreen == R.id.screen_game) { new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle("Leaving the game") .setMessage("Are you sure you want to leave the game?") .setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { leaveRoom(); } }).setNegativeButton("No", null).show(); return true; } return super.onKeyDown(keyCode, e); } // Leave the room. void leaveRoom() { Log.d(TAG, "Leaving room."); mSecondsLeft = 0; stopKeepingScreenOn(); if (mRoomId != null) { Games.RealTimeMultiplayer.leave(mGoogleApiClient, this, mRoomId); mRoomId = null; switchToScreen(R.id.screen_wait); } else { switchToMainScreen(); } } // Show the waiting room UI to track the progress of other players as they enter the // room and get connected. void showWaitingRoom(Room room) { // minimum number of players required for our game // For simplicity, we require everyone to join the game before we start it // (this is signaled by Integer.MAX_VALUE). final int MIN_PLAYERS = Integer.MAX_VALUE; Intent i = Games.RealTimeMultiplayer.getWaitingRoomIntent(mGoogleApiClient, room, MIN_PLAYERS); // show waiting room UI startActivityForResult(i, RC_WAITING_ROOM); } // Called when we get an invitation to play a game. We react by showing that to the user. @Override public void onInvitationReceived(Invitation invitation) { // We got an invitation to play a game! So, store it in // mIncomingInvitationId // and show the popup on the screen. mIncomingInvitationId = invitation.getInvitationId(); ((TextView) findViewById(R.id.incoming_invitation_text)) .setText(invitation.getInviter().getDisplayName() + " " + getString(R.string.is_inviting_you)); switchToScreen(mCurScreen); // This will show the invitation popup } @Override public void onInvitationRemoved(String invitationId) { if (mIncomingInvitationId.equals(invitationId) && mIncomingInvitationId != null) { mIncomingInvitationId = null; switchToScreen(mCurScreen); // This will hide the invitation popup } } /* * CALLBACKS SECTION. This section shows how we implement the several games * API callbacks. */ @Override public void onConnected(Bundle connectionHint) { Log.d(TAG, "onConnected() called. Sign in successful!"); Log.d(TAG, "Sign-in succeeded."); // register listener so we are notified if we receive an invitation to play // while we are in the game Games.Invitations.registerInvitationListener(mGoogleApiClient, this); if (connectionHint != null) { Log.d(TAG, "onConnected: connection hint provided. Checking for invite."); Invitation inv = connectionHint.getParcelable(Multiplayer.EXTRA_INVITATION); if (inv != null && inv.getInvitationId() != null) { // retrieve and cache the invitation ID Log.d(TAG, "onConnected: connection hint has a room invite!"); acceptInviteToRoom(inv.getInvitationId()); return; } } switchToMainScreen(); } @Override public void onConnectionSuspended(int i) { Log.d(TAG, "onConnectionSuspended() called. Trying to reconnect."); mGoogleApiClient.connect(); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { Log.d(TAG, "onConnectionFailed() called, result: " + connectionResult); if (mResolvingConnectionFailure) { Log.d(TAG, "onConnectionFailed() ignoring connection failure; already resolving."); return; } if (mSignInClicked || mAutoStartSignInFlow) { mAutoStartSignInFlow = false; mSignInClicked = false; mResolvingConnectionFailure = BaseGameUtils.resolveConnectionFailure(this, mGoogleApiClient, connectionResult, RC_SIGN_IN, R.string.signin_other_error); } switchToScreen(R.id.screen_sign_in); } // Called when we are connected to the room. We're not ready to play yet! (maybe not everybody // is connected yet). @Override public void onConnectedToRoom(Room room) { Log.d(TAG, "onConnectedToRoom."); highscores = null; initialAllVal(); //get participants and my ID: mParticipants = room.getParticipants(); mMyId = room.getParticipantId(Games.Players.getCurrentPlayerId(mGoogleApiClient)); // save room ID if its not initialized in onRoomCreated() so we can leave cleanly before the game starts. if (mRoomId == null) mRoomId = room.getRoomId(); // print out the list of participants (for debug purposes) Log.d(TAG, "Room ID: " + mRoomId); Log.d(TAG, "My ID " + mMyId); Log.d(TAG, "<< CONNECTED TO ROOM>>"); } // Called when we've successfully left the room (this happens a result of voluntarily leaving // via a call to leaveRoom(). If we get disconnected, we get onDisconnectedFromRoom()). @Override public void onLeftRoom(int statusCode, String roomId) { // we have left the room; return to main screen. Log.d(TAG, "onLeftRoom, code " + statusCode); switchToMainScreen(); } // Called when we get disconnected from the room. We return to the main screen. @Override public void onDisconnectedFromRoom(Room room) { mRoomId = null; showGameError(); } // Show error message about game being cancelled and return to main screen. void showGameError() { BaseGameUtils.makeSimpleDialog(this, getString(R.string.game_problem)); switchToMainScreen(); } // Called when room has been created @Override public void onRoomCreated(int statusCode, Room room) { Log.d(TAG, "onRoomCreated(" + statusCode + ", " + room + ")"); if (statusCode != GamesStatusCodes.STATUS_OK) { Log.e(TAG, "*** Error: onRoomCreated, status " + statusCode); showGameError(); return; } // save room ID so we can leave cleanly before the game starts. mRoomId = room.getRoomId(); // show the waiting room UI showWaitingRoom(room); } // Called when room is fully connected. @Override public void onRoomConnected(int statusCode, Room room) { Log.d(TAG, "onRoomConnected(" + statusCode + ", " + room + ")"); mStatusCode = statusCode; mRoom = room; readyToStartGame = false; turn = 0; for (Participant p : mParticipants) { readyToPlayPlayers.put(p.getParticipantId(), false); } myCards = new Vector<>(); initialAllVal(); if (getOwnerId().equals(mMyId)) { owner = true; ownerInitial(); updateTurnUi(); } else { owner = false; } if (statusCode != GamesStatusCodes.STATUS_OK) { Log.e(TAG, "*** Error: onRoomConnected, status " + statusCode); showGameError(); return; } mySum = 0; lastDropType = 1; updateRoom(room); //Create new shuffle deck. if (owner) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Log.d(TAG, "cards(: " + cardDeck.jp); //Sending the participants cards. sendParticipantsCardsToAllParticipants(); drawMyCards(); //Sending the card deck to all participant sendCardDeckToAllParticipants(false); sendPrimaryDeckToAllParticipants(); //update all participant cards ui updateParticipantsNamesAndUI(); } } private void sendPrimaryDeckToAllParticipants() { Log.d(TAG, "sendPrimaryDeckToAllParticipants() " + primaryDeck); byte[] b = new byte[0]; try { b = toGson(primaryDeck, DATA_TYPE_PRIMARY_DECK); } catch (IOException e) { e.printStackTrace(); } byte[] sendMsg = new byte[5 + b.length]; sendMsg[0] = (int) 5; for (int i = 0; i < b.length; i++) { sendMsg[5 + i] = b[i]; } messageToAllParticipants(sendMsg, true); updatePrimaryDeckUI(); } private void sendMyCardsToAllParticipants() { Log.d(TAG, "sendMyCardsToAllParticipants() " + myCards); byte[] b = new byte[0]; try { b = toGson(myCards, DATA_TYPE_MY_CARDS); } catch (IOException e) { e.printStackTrace(); } byte[] sendMsg = new byte[5 + b.length]; sendMsg[0] = (int) 2; for (int i = 0; i < b.length; i++) { sendMsg[5 + i] = b[i]; } messageToAllParticipants(sendMsg, true); } private void sendParticipantsCardsToAllParticipants() { Log.d(TAG, "sendParticipantsCardsToAllParticipants() "); byte[] b = new byte[0]; try { b = toGson(mParticipantCards, DATA_TYPE_M_PARTICIPANT_CARDS); } catch (IOException e) { e.printStackTrace(); } byte[] sendMsg = new byte[5 + b.length]; sendMsg[0] = 1; for (int i = 0; i < b.length; i++) { sendMsg[5 + i] = b[i]; } messageToAllParticipants(sendMsg, true); } private void sendCardDeckToAllParticipants(boolean shuffle) { Log.d(TAG, "sendCardDeckToAllParticipants() "); byte[] b = new byte[0]; try { b = toGson(cardDeck, DATA_TYPE_CARD_DECK); } catch (IOException e) { e.printStackTrace(); } byte[] sendMsg = new byte[5 + b.length]; sendMsg[0] = (int) 0; if (shuffle) { sendMsg[1] = (int) 1; displayToastForLimitTime("Shuffling Card Deck...", 3000); } for (int i = 0; i < b.length; i++) { sendMsg[5 + i] = b[i]; } messageToAllParticipants(sendMsg, true); } private void createParticipantsCards() { Log.d(TAG, "createParticipantsCards() "); for (int j = 0; j < 5; j++) { myCards.add(cardDeck.jp.remove(0)); } calculateSum(); mParticipantCards.put(mMyId, myCards); if (mMultiplayer) { for (Participant p : mParticipants) { if (p.getParticipantId().equals(mMyId)) continue; if (p.getStatus() != Participant.STATUS_JOINED) continue; else { Vector<Card> v = new Vector<>(); for (int j = 0; j < 5; j++) { v.add(cardDeck.jp.remove(0)); } mParticipantCards.put(p.getParticipantId(), v); } } } else { for (PCPlayer p : mPCParticipants) { Vector<Card> v = new Vector<>(); for (int j = 0; j < 5; j++) { v.add(cardDeck.jp.remove(0)); } mParticipantCards.put(p.getParticipantId(), v); p.setCards(v); } } } @Override public void onJoinedRoom(int statusCode, Room room) { Log.d(TAG, "onJoinedRoom(" + statusCode + ", " + room + ")"); if (statusCode != GamesStatusCodes.STATUS_OK) { Log.e(TAG, "*** Error: onRoomConnected, status " + statusCode); showGameError(); return; } // show the waiting room UI showWaitingRoom(room); } // We treat most of the room update callbacks in the same way: we update our list of // participants and update the display. In a real game we would also have to check if that // change requires some action like removing the corresponding player avatar from the screen, // etc. @Override public void onPeerDeclined(Room room, List<String> arg1) { updateRoom(room); } @Override public void onPeerInvitedToRoom(Room room, List<String> arg1) { updateRoom(room); } @Override public void onP2PDisconnected(String participant) { } @Override public void onP2PConnected(String participant) { } @Override public void onPeerJoined(Room room, List<String> arg1) { updateRoom(room); } @Override public void onPeerLeft(Room room, List<String> peersWhoLeft) { // updateRoom(room); Toast toast = Toast.makeText(getApplicationContext(), "A player has left the room", Toast.LENGTH_SHORT); toast.show(); leaveRoom(); } @Override public void onRoomAutoMatching(Room room) { updateRoom(room); } @Override public void onRoomConnecting(Room room) { updateRoom(room); } @Override public void onPeersConnected(Room room, List<String> peers) { updateRoom(room); } @Override public void onPeersDisconnected(Room room, List<String> peers) { updateRoom(room); } void updateRoom(Room room) { if (room != null) { mParticipants = room.getParticipants(); } if (mParticipants != null) { // updatePeerScoresDisplay(); } if (cardDeck != null) { // ((TextView) findViewById(R.id.card_deck)).setText("" + cardDeck.jp); } if (primaryDeck != null) { // ((TextView) findViewById(R.id.primary_deck)).setText("" + primaryDeck.peek()); } } /* * GAME LOGIC SECTION. Methods that implement the game's rules. */ // Current state of the game: int mSecondsLeft = -1; // how long until the game ends (seconds) final static int GAME_DURATION = 1000; // game duration, seconds. int mScore = 0; // user's current score // Reset game variables in preparation for a new game. void resetGameVars() { mSecondsLeft = GAME_DURATION; mFinishedParticipants.clear(); } // Start the gameplay phase of the game. void startGame(boolean multiplayer) { mMultiplayer = multiplayer; drawMyCards(); switchToScreen(R.id.screen_game); if (!mMultiplayer) { cleanUI(); Log.d(TAG, "singlePlayer()"); mMyId = "ID"; getNumOfPC(); } // run the gameTick() method every second to update the game. final Handler h = new Handler(); h.postDelayed(new Runnable() { @Override public void run() { if (mSecondsLeft <= 0) return; gameTick(); h.postDelayed(this, 1000); } }, 1000); } private void cleanUI() { //update old participant ui; ImageView myCard; ((TextView) findViewById(R.id.leftName)).setText(""); (findViewById(R.id.leftName)).setVisibility(View.GONE); (findViewById(R.id.leftPlayIcon)).setVisibility(View.GONE); ((TextView) findViewById(R.id.rightName)).setText(""); (findViewById(R.id.rightName)).setVisibility(View.GONE); (findViewById(R.id.rightPlayIcon)).setVisibility(View.GONE); ((TextView) findViewById(R.id.topName)).setText(""); (findViewById(R.id.topName)).setVisibility(View.GONE); (findViewById(R.id.topPlayIcon)).setVisibility(View.GONE); for (int j = 0; j < 5; j++) { myCard = (ImageView) findViewById(cardsRightID[j]); myCard.setVisibility(View.GONE); myCard = (ImageView) findViewById(cardsLeftID[j]); myCard.setVisibility(View.GONE); myCard = (ImageView) findViewById(cardsTopID[j]); myCard.setVisibility(View.GONE); myCard = (ImageView) findViewById(cardsID[j]); myCard.setVisibility(View.GONE); myCard = (ImageView) findViewById(droppedID[j]); myCard.setVisibility(View.GONE); } } // Game tick -- update countdown, check if game ended. void gameTick() { if (mSecondsLeft > 0) --mSecondsLeft; // update countdown if (mSecondsLeft <= 0) { // finish game // findViewById(R.id.button_click_me).setVisibility(View.GONE); broadcastScore(true); } } // indicates the player scored one point void onTurnFinished(byte pickedCardIndex, ArrayList<Card> myDrop) { if (!updateTurnUi()) { return; } // if (mSecondsLeft <= 0) // return; // too late! // ++mScore; calculateSum(); drawMyCards(); updatePrimaryDeckUI(); // broadcast our new score to our peers if (mMultiplayer) { updatePlayersOnTurnFinish(pickedCardIndex, myDrop); } else { Log.d(TAG, "onTurnFinished() - turn1: " + turn); turn = (byte) (++turn % (mPCParticipants.size() + 1)); Log.d(TAG, "onTurnFinished() - turn2: " + turn); updateTurnGUI(); } ((findViewById(R.id.yaniv_declare))).setVisibility(View.GONE); ((Button) (findViewById(R.id.button_score))).setText("Current: " + mySum); } public void updatePlayersOnTurnFinishSingle(String ID, int LDT) { Log.d(TAG, "updatePlayersOnTurnFinishSingle() - turn2= " + turn); turn = (byte) (++turn % (mPCParticipants.size() + 1)); Log.d(TAG, "updatePlayersOnTurnFinishSingle() - turn2= " + turn); lastDropType = LDT; updateParticipantUI(ID); updatePrimaryDeckUI(); updateTurnGUI(); } // indicates the player scored one point void onTurnFinishedSingle(byte pickedCardIndex, ArrayList<Card> myDrop) { if (!updateTurnUi()) { return; } // if (mSecondsLeft <= 0) // return; // too late! // ++mScore; calculateSum(); drawMyCards(); updatePrimaryDeckUI(); // broadcast our new score to our peers if (mMultiplayer) { updatePlayersOnTurnFinish(pickedCardIndex, myDrop); } else { Log.d(TAG, "onTurnFinished() - turn1: " + turn); turn = (byte) (++turn % (mPCParticipants.size() + 1)); Log.d(TAG, "onTurnFinished() - turn2: " + turn); updateTurnGUI(); } ((findViewById(R.id.yaniv_declare))).setVisibility(View.GONE); ((Button) (findViewById(R.id.button_score))).setText("Current: " + mySum); } /* * COMMUNICATIONS SECTION. Methods that implement the game's network * protocol. */ // Called when we receive a real-time message from the network. // Messages in our game are made up of 2 bytes: the first one is 'F' or 'U' // indicating // whether it's a final or interim score. The second byte is the score. // There is also the // 'S' message, which indicates that the game should start. @Override public void onRealTimeMessageReceived(RealTimeMessage rtm) { byte[] buf = rtm.getMessageData(); String sender = rtm.getSenderParticipantId(); Log.d(TAG, "[onRealTimeMessageReceived] - Got message from Participant " + sender + ",msg: " + Arrays.toString(buf)); // Another player finished his turn if (buf[0] == 20) { turn = buf[1]; Card newCard; TextView lastPlayerPick = (TextView) (findViewById(R.id.lastPlayerPick)); if (buf[2] == 5) { // if the last player took from the deck, remove the first card lastPlayerPick.setText("Last player picked from the deck"); newCard = cardDeck.jp.remove(0); } else { lastPlayerPick.setText("Last player picked: " + primaryDeck.peek().get(buf[2]).toString()); ArrayList<Card> lastDrop = primaryDeck.peek(); newCard = lastDrop.get(buf[2]); } lastDropType = buf[3]; ArrayList<Card> droppedCards = fromGson(buf, 5, buf.length, DATA_TYPE_CARDS); Log.d(TAG, "Player dropped cards: " + droppedCards.toString()); primaryDeck.push(droppedCards); Log.d(TAG, "Player cards before: " + mParticipantCards.get(sender)); Vector<Card> playerCards = mParticipantCards.get(sender); for (Card c : droppedCards) { Log.d(TAG, "Deleting card: " + c.toString()); boolean contains = playerCards.contains(c); boolean b = playerCards.remove(c); Log.d(TAG, "Delete worked: " + b + " card exist? " + contains); } playerCards.add(newCard); Log.d(TAG, "Player cards changed: " + playerCards); mParticipantCards.put(sender, playerCards); Log.d(TAG, "Player cards after: " + mParticipantCards.get(sender)); updateParticipantUI(sender); updatePrimaryDeckUI(); } //Game is started, owner send the cardsDeck, any participant needs to reload the cards into cardDeck or shuffle cards. else if ((int) buf[0] == 0) { // Checking shuffle if ((int) buf[1] == 1) { displayToastForLimitTime("Shuffling Card Deck...", 3000); } cardDeck = fromGson(buf, 5, buf.length, DATA_TYPE_CARD_DECK); Log.d(TAG, "[onRealTimeMessageReceived] - cardDeck " + cardDeck.jp); if (cardDeck != null) { } } // Owner create the cards for all participant. needs to save it on Mycards. else if ((int) buf[0] == 1) { // starting highscores array if null if (highscores == null) { highscores = new int[mParticipants.size()]; } mParticipantCards = fromGson(buf, 5, buf.length, DATA_TYPE_M_PARTICIPANT_CARDS); myCards = mParticipantCards.containsKey(mMyId) ? mParticipantCards.get(mMyId) : null; calculateSum(); setPlayerPositonUI(); Log.d(TAG, "[onRealTimeMessageReceived] -mycards after" + myCards); updateTurnUi(); updateParticipantsNamesAndUI(); } // When participant played a turn else if ((int) buf[0] == 2) { mParticipantCards.put(sender, (Vector<Card>) fromGson(buf, 5, buf.length, DATA_TYPE_MY_CARDS)); Log.d(TAG, "[onRealTimeMessageReceived] -participant " + sender + " finished his turn, his new cards: " + mParticipantCards.get(sender)); updateParticipantUI(sender); } // take from 0-primary 1-deck take from the primary or deck (and update in each screen) // Cards he take (only if 0) else if ((int) buf[0] == 5) { primaryDeck = fromGson(buf, 5, buf.length, DATA_TYPE_PRIMARY_DECK); Log.d(TAG, "[onRealTimeMessageReceived] - primaryDeck " + primaryDeck); if (primaryDeck != null) { updatePrimaryDeckUI(); } } //when player declare yaniv else if ((int) buf[0] == 7) { yanivCalled(buf); } else if ((int) buf[0] == 8) { readyToPlayPlayers.put(sender, true); checkReadyList(); } else if ((int) buf[0] == 10) { } // Regular messages to change the turn. else { turn = buf[3]; updateTurnUi(); Log.d(TAG, "[onRealTimeMessageReceived] - regular message "); if (buf[1] == 'F' || buf[1] == 'U') { turn = buf[3]; lastDropType = (int) buf[4]; } } } private void displayToastForLimitTime(String message, long time) { Log.d(TAG, "displayToastForLimitTime() mes:" + message + " time:" + time); final Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT); toast.show(); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { toast.cancel(); } }, time); } private void checkReadyList() { boolean isAllReady = true; Log.d(TAG, "[checkReadyList]" + readyToPlayPlayers.toString()); for (Participant p : mParticipants) { if (!readyToPlayPlayers.get(p.getParticipantId())) { isAllReady = false; break; } } readyToStartGame = isAllReady; } // After a player called Yaniv, and the msg was received // Update the scores for all the players. private void yanivCalled(byte[] buf) { boolean isGameFinished = false; String loser = ""; // if a yaniv was called if (buf[2] == 0) { for (int i = 0; i < mParticipants.size(); i++) { if (i != buf[1]) { highscores[i] += getPlayerScore(mParticipants.get(i)); if (highscores[i] == 100) { highscores[i] = 50; } else if (highscores[i] > 100) { isGameFinished = true; loser += mParticipants.get(i).getDisplayName() + " lost with " + highscores[i] + " points." + System.getProperty("line.separator"); } } } } // if an asaf was called else { ArrayList<Integer> asafArray = new ArrayList<>(); for (int i = 0; i < buf[2]; i++) { asafArray.add((int) buf[2 + i + 1]); } for (int i = 0; i < mParticipants.size(); i++) { if (i == buf[1]) { highscores[i] += getPlayerScore(mParticipants.get(i)) + 30; if (highscores[i] == 100) { highscores[i] = 50; } else if (highscores[i] > 100) { isGameFinished = true; loser += mParticipants.get(i).getDisplayName() + " lost with " + highscores[i] + " points." + System.getProperty("line.separator"); } } else if (!asafArray.contains(i)) { highscores[i] += getPlayerScore(mParticipants.get(i)); if (highscores[i] == 100) { highscores[i] = 50; } else if (highscores[i] > 100) { isGameFinished = true; loser += mParticipants.get(i).getDisplayName() + " lost with " + highscores[i] + " points." + System.getProperty("line.separator"); } } } } updateParticipantsCardsOnGameOverUI(); String winner = ""; switch (buf[2]) { case 0: winner = "The winner is: " + mParticipants.get(buf[3]).getDisplayName() + "!"; break; case 1: winner = "ASAF!!! the winner is: " + mParticipants.get(buf[3]).getDisplayName() + "!"; break; case 2: winner = "ASAF!!! the winners are: " + mParticipants.get(buf[3]).getDisplayName() + "," + System.getProperty("line.separator") + mParticipants.get(buf[4]).getDisplayName() + "!"; break; case 3: winner = "ASAF!!! the winners are: " + mParticipants.get(buf[3]).getDisplayName() + "," + System.getProperty("line.separator") + mParticipants.get(buf[4]).getDisplayName() + "," + System.getProperty("line.separator") + mParticipants.get(buf[5]).getDisplayName() + "!"; break; } if (isGameFinished) { winner += System.getProperty("line.separator") + loser; } new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle("Game Over") .setMessage(winner).show(); final TextView timer = (TextView) (findViewById(R.id.countDownTimer)); final Button readyButton = (Button) (findViewById(R.id.Ready)); if (isGameFinished) { timer.setText("The game is finished."); timer.setVisibility(View.VISIBLE); } else { timer.setText("New game starts in: 30 seconds"); timer.setVisibility(View.VISIBLE); readyButton.setVisibility(View.VISIBLE); cdt = new CountDownTimer(30000, 1000) { public void onTick(long millisUntilFinished) { timer.setText("New game starts in: " + millisUntilFinished / 1000 + " seconds" + System.getProperty("line.separator") + "or when everyone is ready."); if (readyToStartGame) { onFinish(); cdt.cancel(); } } public void onFinish() { cancelTimer(); timer.setVisibility(View.GONE); readyButton.setVisibility(View.GONE); onRoomConnected(mStatusCode, mRoom); } }.start(); } } private void cancelTimer() { cdt.cancel(); } private void setPlayerPositonUI() { Log.d(TAG, "setPlayerPositonUI()"); boolean top = false; boolean left = false; if (mMultiplayer) { for (Participant p : mParticipants) { if (!p.getParticipantId().equals(mMyId)) { if (!top) { mParticipantPlayerPosition.put("top", p.getParticipantId()); Log.d(TAG, "setPlayerPositonUI() - top - " + p.getParticipantId() + " - " + p.getDisplayName()); top = true; } else if (!left) { mParticipantPlayerPosition.put("left", p.getParticipantId()); Log.d(TAG, "setPlayerPositonUI() - left - " + p.getParticipantId() + " - " + p.getDisplayName()); left = true; } else { mParticipantPlayerPosition.put("right", p.getParticipantId()); } } } } else { for (PCPlayer p : mPCParticipants) { if (!p.getParticipantId().equals(mMyId)) { if (!top) { mParticipantPlayerPosition.put("top", p.getParticipantId()); Log.d(TAG, "setPlayerPositonUI() - top - " + p.getParticipantId() + " - " + p.getDisplayName()); top = true; } else if (!left) { mParticipantPlayerPosition.put("left", p.getParticipantId()); Log.d(TAG, "setPlayerPositonUI() - left - " + p.getParticipantId() + " - " + p.getDisplayName()); left = true; } else { mParticipantPlayerPosition.put("right", p.getParticipantId()); } } } } } private void updatePrimaryDeckUI() { Log.d(TAG, "updatePrimaryDeckUI()"); int i; ImageView myCard; ArrayList<Card> peek = primaryDeck.peek(); for (i = 0; i < peek.size(); i++) { int drawable = cardsDrawable.get("" + peek.get(i).getKey()); myCard = (ImageView) findViewById(droppedID[i]); myCard.setImageResource(drawable); myCard.setVisibility(View.VISIBLE); } for (; i < 5; i++) { myCard = (ImageView) findViewById(droppedID[i]); myCard.setVisibility(View.GONE); } updateTurnGUI(); } void messageToAllParticipants(byte[] msg, boolean reliable) { Log.d(TAG, "[messageToAllParticipants] Participant " + mMyId + " Send msg to all participants: " + Arrays.toString(msg)); for (Participant p : mParticipants) { if (p.getParticipantId().equals(mMyId)) continue; if (p.getStatus() != Participant.STATUS_JOINED) continue; if (reliable) { // final score notification must be sent via reliable message Games.RealTimeMultiplayer.sendReliableMessage(mGoogleApiClient, null, msg, mRoomId, p.getParticipantId()); } else { // it's an interim score notification, so we can use unreliable Games.RealTimeMultiplayer.sendUnreliableMessage(mGoogleApiClient, msg, mRoomId, p.getParticipantId()); } } } private void updatePlayersOnTurnFinish(byte pickedCardIndex, ArrayList<Card> myDrop) { byte[] droppedCards = new byte[0]; try { droppedCards = toGson(myDrop, DATA_TYPE_CARDS); Log.d(TAG, "Dropped cards message length: " + droppedCards.length); } catch (IOException e) { e.printStackTrace(); } byte[] sendMsg = new byte[5 + droppedCards.length]; sendMsg[0] = 20; turn = (byte) (++turn % mParticipants.size()); updateTurnGUI(); sendMsg[1] = turn; // 0-4 indicating card index from thrown pile // 5 if taken from the deck sendMsg[2] = pickedCardIndex; TextView lastPlayerPick = (TextView) (findViewById(R.id.lastPlayerPick)); if (pickedCardIndex == 5) { lastPlayerPick.setText("You picked a random card"); } else { lastPlayerPick.setText("You picked from dropped pile"); } sendMsg[3] = (byte) myLastDropType; for (int i = 0; i < droppedCards.length; i++) { sendMsg[5 + i] = droppedCards[i]; } // Send to every other participant. for (Participant p : mParticipants) { if (p.getParticipantId().equals(mMyId)) continue; if (p.getStatus() != Participant.STATUS_JOINED) continue; Log.d(TAG, "[broadcastScore] Participant " + mMyId + " Send Reliable msg to " + p.getParticipantId() + ",msg: " + Arrays.toString(sendMsg)); Games.RealTimeMultiplayer.sendReliableMessage(mGoogleApiClient, null, sendMsg, mRoomId, p.getParticipantId()); } } // Broadcast my score to everybody else. void broadcastScore(boolean finalScore) { if (!mMultiplayer) return; // playing single-player mode mMsgBuf[0] = (byte) 4; // First byte in message indicates whether it's a final score or not mMsgBuf[1] = (byte) (finalScore ? 'F' : 'U'); // Second byte is the score. mMsgBuf[2] = (byte) mScore; turn = (byte) (++turn % mParticipants.size()); mMsgBuf[3] = (turn); Log.d(TAG, "turn= " + turn + " mMsgBuf[3]=" + mMsgBuf[3]); mMsgBuf[4] = (byte) (myLastDropType); // Send to every other participant. for (Participant p : mParticipants) { if (p.getParticipantId().equals(mMyId)) continue; if (p.getStatus() != Participant.STATUS_JOINED) continue; if (finalScore) { Log.d(TAG, "[broadcastScore] Participant " + mMyId + " Send Reliable msg to " + p.getParticipantId() + ",msg: " + Arrays.toString(mMsgBuf)); // final score notification must be sent via reliable message Games.RealTimeMultiplayer.sendReliableMessage(mGoogleApiClient, null, mMsgBuf, mRoomId, p.getParticipantId()); } else { // it's an interim score notification, so we can use unreliable Log.d(TAG, "[broadcastScore] Participant " + mMyId + " Send Unreliable msg to " + p.getParticipantId() + ",msg: " + Arrays.toString(mMsgBuf)); Games.RealTimeMultiplayer.sendUnreliableMessage(mGoogleApiClient, mMsgBuf, mRoomId, p.getParticipantId()); } } updateTurnUi(); } /* * UI SECTION. Methods that implement the game's UI. */ // This array lists everything that's clickable, so we can install click // event handlers. final static int[] CLICKABLES = { R.id.button_accept_popup_invitation, R.id.button_invite_players, R.id.button_quick_game, R.id.button_see_invitations, R.id.button_sign_in, R.id.button_sign_out, R.id.button_single_player, R.id.button_single_player_2 }; // This array lists all the individual screens our game has. final static int[] SCREENS = { R.id.screen_game, R.id.screen_main, R.id.screen_sign_in, R.id.screen_wait }; int mCurScreen = -1; void switchToScreen(int screenId) { // make the requested screen visible; hide all others. for (int id : SCREENS) { findViewById(id).setVisibility(screenId == id ? View.VISIBLE : View.GONE); } mCurScreen = screenId; // should we show the invitation popup? boolean showInvPopup; if (mIncomingInvitationId == null) { // no invitation, so no popup showInvPopup = false; } else if (mMultiplayer) { // if in multiplayer, only show invitation on main screen showInvPopup = (mCurScreen == R.id.screen_main); } else { // single-player: show on main screen and gameplay screen showInvPopup = (mCurScreen == R.id.screen_main || mCurScreen == R.id.screen_game); } findViewById(R.id.invitation_popup).setVisibility(showInvPopup ? View.VISIBLE : View.GONE); } void switchToMainScreen() { if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) { switchToScreen(R.id.screen_main); } else { switchToScreen(R.id.screen_sign_in); } } /* Needs to thread sleep with that: Handler handler = new Handler(); Runnable r = new Runnable() { public void run() { p.play(); } }; handler.postDelayed(r, timeToPCSleep);*/ // updates the screen - who's turn is it void updateTurnGUI() { Log.d(TAG, "updateTurnGUI() "); Drawable imgOnline = ContextCompat.getDrawable(baseContext, android.R.drawable.presence_online); Drawable imgInvisible = ContextCompat.getDrawable(baseContext, android.R.drawable.presence_invisible); if (isTurn(mMyId)) { (findViewById(R.id.my_card_1)).setSelected(false); (findViewById(R.id.my_card_1)).setClickable(true); (findViewById(R.id.my_card_2)).setSelected(false); (findViewById(R.id.my_card_2)).setClickable(true); (findViewById(R.id.my_card_3)).setSelected(false); (findViewById(R.id.my_card_3)).setClickable(true); (findViewById(R.id.my_card_4)).setSelected(false); (findViewById(R.id.my_card_4)).setClickable(true); (findViewById(R.id.my_card_5)).setSelected(false); (findViewById(R.id.my_card_5)).setClickable(true); (findViewById(R.id.dropped_1)).setClickable(true); (findViewById(R.id.dropped_3)).setClickable(true); (findViewById(R.id.dropped_2)).setClickable(true); (findViewById(R.id.dropped_4)).setClickable(true); (findViewById(R.id.dropped_5)).setClickable(true); (findViewById(R.id.deck_cards)).setClickable(true); // (findViewById(R.id.my_drop)).setVisibility(View.VISIBLE); checkYanivOpportunity(); (findViewById(R.id.topPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.leftPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.rightPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.myPlayIcon)).setVisibility(View.VISIBLE); } else { (findViewById(R.id.my_card_1)).setClickable(false); (findViewById(R.id.my_card_2)).setClickable(false); (findViewById(R.id.my_card_3)).setClickable(false); (findViewById(R.id.my_card_4)).setClickable(false); (findViewById(R.id.my_card_5)).setClickable(false); (findViewById(R.id.dropped_1)).setClickable(false); (findViewById(R.id.dropped_3)).setClickable(false); (findViewById(R.id.dropped_2)).setClickable(false); (findViewById(R.id.dropped_4)).setClickable(false); (findViewById(R.id.dropped_5)).setClickable(false); (findViewById(R.id.deck_cards)).setClickable(false); // (findViewById(R.id.my_drop)).setVisibility(View.GONE); if (mMultiplayer) { (findViewById(R.id.my_card_1)).setClickable(false); (findViewById(R.id.my_card_2)).setClickable(false); (findViewById(R.id.my_card_3)).setClickable(false); (findViewById(R.id.my_card_4)).setClickable(false); (findViewById(R.id.my_card_5)).setClickable(false); (findViewById(R.id.dropped_1)).setClickable(false); (findViewById(R.id.dropped_3)).setClickable(false); (findViewById(R.id.dropped_2)).setClickable(false); (findViewById(R.id.dropped_4)).setClickable(false); (findViewById(R.id.dropped_5)).setClickable(false); (findViewById(R.id.deck_cards)).setClickable(false); // (findViewById(R.id.my_drop)).setVisibility(View.GONE); if (isTurn(mParticipantPlayerPosition.get("top"))) { (findViewById(R.id.topPlayIcon)).setBackground(imgOnline); (findViewById(R.id.leftPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.rightPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.myPlayIcon)).setVisibility(View.GONE); } else if (isTurn(mParticipantPlayerPosition.get("left"))) { (findViewById(R.id.topPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.leftPlayIcon)).setBackground(imgOnline); (findViewById(R.id.rightPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.myPlayIcon)).setVisibility(View.GONE); } else { (findViewById(R.id.topPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.leftPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.rightPlayIcon)).setBackground(imgOnline); (findViewById(R.id.myPlayIcon)).setVisibility(View.GONE); } } else { if (isTurn(mParticipantPlayerPosition.get("top"))) { Log.d(TAG, "updateTurnGUI() turn=top name=" + mParticipantPlayerPosition.get("top")); (findViewById(R.id.topPlayIcon)).setBackground(imgOnline); (findViewById(R.id.leftPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.rightPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.myPlayIcon)).setVisibility(View.GONE); for (final PCPlayer p : mPCParticipants) { Log.d(TAG, "updateTurnGUI() p.getParticipantId()=" + p.getParticipantId() + " ParticipantPlayerPosition.get(\"top\")" + mParticipantPlayerPosition.get("top")); if (p.getParticipantId().equals(mParticipantPlayerPosition.get("top"))) { Log.d(TAG, "updateTurnGUI()- Playing!"); p.play(); break; } } } else if (isTurn(mParticipantPlayerPosition.get("left"))) { Log.d(TAG, "updateTurnGUI() turn=left name=" + mParticipantPlayerPosition.get("left")); (findViewById(R.id.topPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.leftPlayIcon)).setBackground(imgOnline); (findViewById(R.id.rightPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.myPlayIcon)).setVisibility(View.GONE); for (final PCPlayer p : mPCParticipants) { if (p.getParticipantId().equals(mParticipantPlayerPosition.get("left"))) { p.play(); break; } } } else { Log.d(TAG, "updateTurnGUI() turn=right name=" + mParticipantPlayerPosition.get("right")); (findViewById(R.id.topPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.leftPlayIcon)).setBackground(imgInvisible); (findViewById(R.id.rightPlayIcon)).setBackground(imgOnline); (findViewById(R.id.myPlayIcon)).setVisibility(View.GONE); for (PCPlayer p : mPCParticipants) { if (p.getParticipantId().equals(mParticipantPlayerPosition.get("right"))) { p.play(); } break; } } } } } /* * MISC SECTION. Miscellaneous methods. */ // Sets the flag to keep this screen on. It's recommended to do that during // the // handshake when setting up a game, because if the screen turns off, the // game will be // cancelled. void keepScreenOn() { getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } // Clears the flag that keeps the screen on. void stopKeepingScreenOn() { getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } String getOwnerId() { return mParticipants.get(0).getParticipantId(); } boolean updateTurnUi() { if (mMultiplayer) { Log.d(TAG, "updateTurnUi: mparti0: " + mParticipants.get(0).getParticipantId()); Log.d(TAG, "updateTurnUi: mpart1i: " + mParticipants.get(1).getParticipantId()); Log.d(TAG, "updateTurnUi: mpart0icards: " + mParticipantCards.get(mParticipants.get(0).getParticipantId())); Log.d(TAG, "updateTurnUi: mpart1icards: " + mParticipantCards.get(mParticipants.get(1).getParticipantId())); Log.d(TAG, "updateTurnUi: myid: " + mMyId); Log.d(TAG, "updateTurnUi: turn: " + turn); } drawMyCards(); return true; } boolean isTurn(String participant) { if (mMultiplayer) { if (!mParticipants.get(turn).getParticipantId().equals(participant)) { Log.d(TAG, "myTurn=false"); return false; } Log.d(TAG, "myTurn=true"); return true; } else { Log.d(TAG, "isTurn() - participant=" + participant + " mMyId=" + mMyId + " mPCParticipants=" + mPCParticipants.toString() + " turn=" + turn); if (participant.equals(mMyId)) { Log.d(TAG, "myTurn=true"); if (turn == 0) { return true; } else { return false; } } else if (!mPCParticipants.get(turn - 1).getParticipantId().equals(participant)) { Log.d(TAG, "myTurn=false"); return false; } Log.d(TAG, "myTurn=true"); return true; } } public static byte[] toByte(Object obj) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream os = new ObjectOutputStream(out); os.writeObject(obj); return out.toByteArray(); } public static Object fromByte(byte[] data) throws IOException, ClassNotFoundException { ByteArrayInputStream in = new ByteArrayInputStream(data); ObjectInputStream is = new ObjectInputStream(in); return is.readObject(); } //*/*/*/*/*/*/*/* Yaniv Game Functions */*/*/*/*/*/*/*// public void initialAllVal() { myCards = new Vector<>(); mySum = 0; lastDropType = 0; mParticipantCards = new HashMap<>(); primaryDeck = new Stack<>(); cardDeck = new Cards(); mParticipantPlayerPosition = new HashMap<>(); myCardsDrop = new Vector<>(); myCardsDropToString = new Vector<>(); yaniv = false; } //Owner Functions //First Initial void ownerInitial() { Log.d(TAG, "ownerInitial()"); if (highscores == null) if (mMultiplayer) { highscores = new int[mParticipants.size()]; } else { highscores = new int[mPCParticipants.size()]; } this.cardDeck = new Cards(); this.primaryDeck = new Stack<>(); // Add the first card to primary deck. ArrayList<Card> list = new ArrayList<Card>() { { add(cardDeck.jp.remove(0)); } }; primaryDeck.add(list); // Division card to participants. createParticipantsCards(); setPlayerPositonUI(); if (!mMultiplayer) { drawMyCards(); updateParticipantsNamesAndUI(); } } public void drawMyCards() { if (myCards == null) { Log.d(TAG, "Call on null object - myCards"); return; } int i; ImageView myCard; // Gets linearlayout LinearLayout layout = (LinearLayout) findViewById(R.id.myCardsLayout); // Gets the layout params that will allow you to resize the layout ViewGroup.LayoutParams params = layout.getLayoutParams(); // Changes the height and width to the specified *pixels* params.width = myCards.size() * myCardWidthParam; layout.setLayoutParams(params); for (i = 0; i < myCards.size(); i++) { int drawable = cardsDrawable.get("" + myCards.get(i).getKey()); myCard = (ImageView) findViewById(cardsID[i]); myCard.setImageResource(drawable); myCard.setVisibility(View.VISIBLE); } for (; i < 5; i++) { myCard = (ImageView) findViewById(cardsID[i]); myCard.setVisibility(View.GONE); } } public void updateParticipantUI(String pid) { Log.d(TAG, "updateParticipantUI()"); int i; int arr[]; Log.d(TAG, "updateParticipantUI() - mParticipantPlayerPosition - " + mParticipantPlayerPosition); Log.d(TAG, "updateParticipantUI() - pid - " + pid); if (mParticipantPlayerPosition.get("top").equals(pid)) { LinearLayout layout = (LinearLayout) findViewById(R.id.player_top); ViewGroup.LayoutParams params = layout.getLayoutParams(); params.width = mParticipantCards.get(pid).size() * topCardWidthParam; layout.setLayoutParams(params); arr = cardsTopID; } else if (mParticipantPlayerPosition.get("left").equals(pid)) { arr = cardsLeftID; } else { arr = cardsRightID; } ImageView myCard; Log.d(TAG, "updateParticipantUI() - mParticipantCards.get(pid) - " + mParticipantCards.get(pid)); for (i = 0; i < mParticipantCards.get(pid).size() && i < 5; i++) { int drawable; if (yaniv) { drawable = cardsDrawable.get("" + mParticipantCards.get(pid).get(i).getKey()); } else { drawable = R.drawable.pile_1; } myCard = (ImageView) findViewById(arr[i]); myCard.setImageResource(drawable); myCard.setVisibility(View.VISIBLE); } for (; i < 5; i++) { myCard = (ImageView) findViewById(arr[i]); myCard.setVisibility(View.GONE); } } public void updateParticipantsCardsOnGameOverUI() { (findViewById(R.id.myPlayIcon)).setVisibility(View.GONE); (findViewById(R.id.topPlayIcon)).setVisibility(View.GONE); (findViewById(R.id.rightPlayIcon)).setVisibility(View.GONE); (findViewById(R.id.leftPlayIcon)).setVisibility(View.GONE); (findViewById(R.id.yaniv_declare)).setVisibility(View.GONE); TextView lastPlayerPick = (TextView) (findViewById(R.id.lastPlayerPick)); lastPlayerPick.setText(""); Log.d(TAG, "updateParticipantsCardsOnGameOverUI()"); int i; ImageView myCard; for (Participant p : mParticipants) { String id = p.getParticipantId(); if (!id.equals(mMyId)) { for (i = 0; i < mParticipantCards.get(id).size(); i++) { int arr[]; if (mParticipantPlayerPosition.get("top").equals(id)) { LinearLayout layout = (LinearLayout) findViewById(R.id.player_top); ViewGroup.LayoutParams params = layout.getLayoutParams(); params.width = mParticipantCards.get(id).size() * topCardWidthParam; layout.setLayoutParams(params); arr = cardsTopID; } else if (mParticipantPlayerPosition.get("left").equals(id)) { arr = cardsLeftID; } else { arr = cardsRightID; } int drawable = cardsDrawable.get("" + mParticipantCards.get(id).get(i).getKey()); myCard = (ImageView) findViewById(arr[i]); myCard.setImageResource(drawable); } } } } public void updateParticipantsNamesAndUI() { Log.d(TAG, "updateParticipantsNames()"); Log.d(TAG, "updateParticipantsNames() - mParticipantPlayerPosition - " + mParticipantPlayerPosition); Log.d(TAG, "updateParticipantsNames() - mParticipantPlayerPosition - " + mParticipantPlayerPosition.toString()); if (mMultiplayer) { for (Participant p : mParticipants) { if (!p.getParticipantId().equals(mMyId)) { String pid = p.getParticipantId(); String a = mParticipantPlayerPosition.get("top"); Log.d(TAG, "updateParticipantsNames() - a - " + a); Log.d(TAG, "updateParticipantsNames() - pid - " + pid); if (mParticipantPlayerPosition.get("top").equals(p.getParticipantId())) { ((TextView) findViewById(R.id.topName)).setText(p.getDisplayName()); (findViewById(R.id.topName)).setVisibility(View.VISIBLE); (findViewById(R.id.topPlayIcon)).setVisibility(View.VISIBLE); } else if (mParticipantPlayerPosition.get("left").equals(p.getParticipantId())) { ((TextView) findViewById(R.id.leftName)).setText(p.getDisplayName()); (findViewById(R.id.leftName)).setVisibility(View.VISIBLE); (findViewById(R.id.leftPlayIcon)).setVisibility(View.VISIBLE); } else { ((TextView) findViewById(R.id.rightName)).setText(p.getDisplayName()); (findViewById(R.id.rightName)).setVisibility(View.VISIBLE); (findViewById(R.id.rightPlayIcon)).setVisibility(View.VISIBLE); } } } //update all participant cards ui for (Participant p : mParticipants) { if (!p.getParticipantId().equals(mMyId)) { updateParticipantUI(p.getParticipantId()); } } } else { for (PCPlayer p : mPCParticipants) { if (!p.getParticipantId().equals(mMyId)) { String pid = p.getParticipantId(); String a = mParticipantPlayerPosition.get("top"); Log.d(TAG, "updateParticipantsNames() - a - " + a); Log.d(TAG, "updateParticipantsNames() - pid - " + pid); if (mParticipantPlayerPosition.get("top").equals(p.getParticipantId())) { ((TextView) findViewById(R.id.topName)).setText(p.getDisplayName()); (findViewById(R.id.topName)).setVisibility(View.VISIBLE); (findViewById(R.id.topPlayIcon)).setVisibility(View.VISIBLE); } else if (mParticipantPlayerPosition.get("left").equals(p.getParticipantId())) { ((TextView) findViewById(R.id.leftName)).setText(p.getDisplayName()); (findViewById(R.id.leftName)).setVisibility(View.VISIBLE); (findViewById(R.id.leftPlayIcon)).setVisibility(View.VISIBLE); } else { ((TextView) findViewById(R.id.rightName)).setText(p.getDisplayName()); (findViewById(R.id.rightName)).setVisibility(View.VISIBLE); (findViewById(R.id.rightPlayIcon)).setVisibility(View.VISIBLE); } } } //update all participant cards ui for (PCPlayer p : mPCParticipants) { if (!p.getParticipantId().equals(mMyId)) { updateParticipantUI(p.getParticipantId()); } } } } public <T> T fromGson(byte[] buf, int start, int finish, Type DATA_TYPE) { byte[] dataArray = Arrays.copyOfRange(buf, start, finish); String fromGson = null; try { fromGson = (String) fromByte(dataArray); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } Log.d(TAG, "fromGson String: " + fromGson); Log.d(TAG, "fromGson dataArray[]: " + Arrays.toString(dataArray)); Log.d(TAG, "fromGson fullbuf[] to: " + Arrays.toString(buf)); T t = new Gson().fromJson(fromGson, DATA_TYPE); return t; } public <T> byte[] toGson(T t, Type DATA_TYPE) throws IOException { Gson gson = new Gson(); return toByte(gson.toJson(t, DATA_TYPE)); } void calculateSum() { mySum = 0; for (Card card : myCards) { mySum += card.v; } ((Button) (findViewById(R.id.button_score))).setText("Current: " + mySum); } public int[] takeFrom() { Log.d(TAG, "takeFrom() called "); String[] splitString = takeCardEditText.getText().toString().split(","); Log.d(TAG, "takeFrom() - splitString[]: " + Arrays.toString(splitString)); int[] split = tokensStringToInt(splitString); Log.d(TAG, "takeFrom() - splitInt[]: " + Arrays.toString(split)); if (split == invalidDrop || split.length == 0 || split.length > 1 || split[0] > 1 || split[0] < 0) { Log.d(TAG, "invalidInput - Enter 0 to take the card from the Primary Deck or 1 from the Card Deck, Try Again"); Toast.makeText(this, "You enter illegal paramater to take, Try again. ", Toast.LENGTH_LONG).show(); return invalidDrop; } return split; } public int[] takeFromLastDrop() { Log.d(TAG, "takeFromLastDrop() called "); String[] splitString = takeCardEditText.getText().toString().split(","); int[] split = tokensStringToInt(splitString); Log.d(TAG, "takeFromLastDrop() - splitString[]: " + Arrays.toString(splitString)); Log.d(TAG, "primaryDeck=" + primaryDeck.toString()); ArrayList<Card> lastDrop = primaryDeck.peek(); Log.d(TAG, "lastDrop=" + lastDrop.toString()); Log.d(TAG, "takeFromLastDrop() - splitInt[]: " + Arrays.toString(split)); if (split == invalidDrop || split.length != 1) { Log.d(TAG, "invalidInput - Enter 0 to take the card from the Primary Deck or 1 from the Card Deck, Try Again"); Toast.makeText(this, "You enter illegal paramater to take, Try again. ", Toast.LENGTH_LONG).show(); return invalidDrop; } //Taking card from 3 optional options to take. if (lastDropType == 1) { //case one card - taking the only one card are in primary deck. if (split[0] >= 0 && split[0] <= lastDrop.size() - 1) { } else { return invalidDrop; } } else if (lastDropType == 2) { //case equal if (split[0] >= 0 && split[0] <= lastDrop.size() - 1) { } else { return invalidDrop; } } else { //case order if (split[0] == 0 || split[0] == lastDrop.size() - 1) { } else { return invalidDrop; } } return split; } private int checkVaildDrop(int[] split) { Log.d(TAG, "checkVaildDrop() - split:" + Arrays.toString(split)); //return 0 - not vaild, 1 - one card, 2 - equal cards, 3- orderd cards if (split.length == 1) { // Checking if there is only 1 card. Log.d(TAG, "checkVaildDrop() - split.length == 1"); if (split[0] > myCards.size() - 1) { Log.d(TAG, "checkVaildDrop() - split.length == 1 - return 0"); return 0; } Log.d(TAG, "checkVaildDrop() - split.length == 1 - return 1"); return 1; } else { for (int i = 0; i < split.length; i++) { if (split[i] >= myCards.size()) { //Checking out of bounds Log.d(TAG, "checkVaildDrop() - Checking out of bounds - return 0"); return 0; } else { Log.d(TAG, "checkVaildDrop() - Checking out of bounds - else"); } } if (split.length == 2) { //Checking case of 2 jokers or 2 equals cards Log.d(TAG, "checkVaildDrop() - Checking case of 2 jokers or 2 equals cards"); if (myCards.get(split[0]).n == myCards.get(split[1]).n) { Log.d(TAG, "checkVaildDrop() - Checking case of 2 jokers or 2 equals cards - return 2"); return 2; } } if (checkEqualArray(split) == 1) { // Vaild drop of equals cards Log.d(TAG, "checkVaildDrop() - Vaild drop of equals cards - return 2"); return 2; } else if (checkOrderArray(split) == 1) { Log.d(TAG, "checkVaildDrop() - Vaild drop of order cards - return 3"); return 3; } return 0; } } private int checkEqualArray(int Tokens[]) { Log.d(TAG, "checkEqualArray() - " + Arrays.toString(Tokens)); int val = -1; for (int i = 0; i < Tokens.length; i++) { if (myCards.get(Tokens[i]).v != 0 && myCards.get(Tokens[i]).n != val) { if (val == -1) { val = myCards.get(Tokens[i]).n; } else if (myCards.get(Tokens[i]).n != val) { return 0; } } } return 1; } private int checkOrderArray(int Tokens[]) { Log.d(TAG, "checkOrderArray() - " + Arrays.toString(Tokens)); char symbol = getSymbol(Tokens); int orderArray[] = getOrder(Tokens, symbol); for (int i = 0; i < orderArray.length - 1; i++) { if (orderArray[i + 1] - orderArray[i] != 1) { return 0; } } return 1; } private int[] getOrder(int Tokens[], char s) { int orderArray[] = new int[Tokens.length]; if ((myCards.get(Tokens[0]).v == 0) && myCards.get(Tokens[Tokens.length - 1]).v == 0) { for (int i = 1; i < Tokens.length; i++) { if ((myCards.get(Tokens[0]).n == 14 || myCards.get(Tokens[0]).n == 15)) { orderArray[i] = myCards.get(Tokens[i - 1]).n + 1; } else if (myCards.get(Tokens[i]).s == s) { orderArray[i] = myCards.get(Tokens[i]).n; } else { orderArray[i] = -100; } } orderArray[0] = orderArray[1] - 1; Log.d(TAG, "Tokens problem()1 - " + Arrays.toString(Tokens)); } else if ((myCards.get(Tokens[0]).v != 0)) { String cards = ""; for (int i = 0; i < Tokens.length; i++) { cards += " " + myCards.get(Tokens[i]).toString(); } Log.d(TAG, "cards - " + cards); for (int i = 0; i < Tokens.length; i++) { Log.d(TAG, "Tokens problem()2 - " + Arrays.toString(Tokens)); if ((myCards.get(Tokens[i]).n == 14 || myCards.get(Tokens[i]).n == 15)) { orderArray[i] = myCards.get(Tokens[i - 1]).n + 1; } else if (myCards.get(Tokens[i]).s == s) { orderArray[i] = myCards.get(Tokens[i]).n; } else { orderArray[i] = -100; } } } else { Log.d(TAG, "Tokens problem()3 - " + Arrays.toString(Tokens)); for (int i = Tokens.length - 1; i >= 0; i--) { Log.d(TAG, "getOrder() - i: " + i + " - " + myCards.get(Tokens[i]).toString()); if ((myCards.get(Tokens[i]).n == 14 || myCards.get(Tokens[i]).n == 15)) { orderArray[i] = myCards.get(Tokens[i + 1]).n - 1; } else if (myCards.get(Tokens[i]).s == s) { orderArray[i] = myCards.get(Tokens[i]).n; } else { orderArray[i] = -100; } } } Log.d(TAG, "getOrder() - orderArray: " + Arrays.toString(orderArray)); return orderArray; } private char getSymbol(int Tokens[]) { char sym = 'X'; for (int i = 0; i < Tokens.length; i++) { if (myCards.get(Tokens[i]).v != 0) { return myCards.get(Tokens[i]).s; } } return sym; } private int[] tokensStringToInt(String[] Tokens) { int[] integerTokens = new int[Tokens.length]; for (int i = 0; i < Tokens.length; i++) { try { integerTokens[i] = Integer.parseInt(Tokens[i]); } catch (NumberFormatException ex) { // handle your exception return invalidDrop; } } return integerTokens; } public void declareYanivOnClick(View view) { //send a declare message to all participants. disableAllCards(); byte[] sendMsg = new byte[5]; sendMsg[0] = (int) 7; byte yanivCallerIndex = 0; boolean isAsaf = false; int min = mySum; for (byte i = 0; i < mParticipants.size(); i++) { String pid = mParticipants.get(i).getParticipantId(); if (!pid.equals(mMyId)) { int score = getPlayerScore(mParticipants.get(i)); if (score <= min) { min = score; isAsaf = true; } } else { yanivCallerIndex = i; } } sendMsg[1] = yanivCallerIndex; if (isAsaf) { sendMsg[2] = 1; int asafCount = 0; for (byte i = 0; i < mParticipants.size(); i++) { String pid = mParticipants.get(i).getParticipantId(); if (!pid.equals(mMyId)) { int score = getPlayerScore(mParticipants.get(i)); if (score == min) { sendMsg[2 + ++asafCount] = i; } } } } else { sendMsg[2] = 0; sendMsg[3] = yanivCallerIndex; } messageToAllParticipants(sendMsg, true); yanivCalled(sendMsg); // updateParticipantsCardsOnGameOverUI(); // each participant "shows" his cards and his score UI //the game stop. } private void disableAllCards() { (findViewById(R.id.my_card_1)).setClickable(false); (findViewById(R.id.my_card_2)).setClickable(false); (findViewById(R.id.my_card_3)).setClickable(false); (findViewById(R.id.my_card_4)).setClickable(false); (findViewById(R.id.my_card_5)).setClickable(false); (findViewById(R.id.dropped_1)).setClickable(false); (findViewById(R.id.dropped_3)).setClickable(false); (findViewById(R.id.dropped_2)).setClickable(false); (findViewById(R.id.dropped_4)).setClickable(false); (findViewById(R.id.dropped_5)).setClickable(false); (findViewById(R.id.deck_cards)).setClickable(false); } public void checkYanivOpportunity() { calculateSum(); if (mySum <= yanivMinScore) { Log.d(TAG, "checkYanivOpportunity: True"); ((findViewById(R.id.yaniv_declare))).setVisibility(View.VISIBLE); } else { Log.d(TAG, "checkYanivOpportunity: False"); ((findViewById(R.id.yaniv_declare))).setVisibility(View.GONE); } } public String getMyCardsWithVal() { String ans = ""; for (int i = 0; i < myCards.size(); i++) { ans += "" + i + "-[" + myCards.get(i) + "] "; } return ans; } public String getPopPrimaryDeckCardWithVal() { String ans = ""; if (primaryDeck == null) { Log.d(TAG, "primaryDeck=null !!!!!!"); } else { Log.d(TAG, "primaryDeck=" + primaryDeck.toString()); } if (lastDropType == 1) { ans = "" + 0 + "-[" + (primaryDeck.peek().get((0)) + "] "); } else if (lastDropType == 2) { for (int i = 0; i < primaryDeck.peek().size(); i++) { ans += "" + i + "-[" + primaryDeck.peek().get(i) + "] "; } } else { ans += "" + 0 + "-[" + (primaryDeck.peek().get((0)) + "] "); ans += "" + (primaryDeck.peek().size() - 1) + "-[" + (primaryDeck.peek().get((primaryDeck.peek().size() - 1)) + "] "); } return ans; } public void initialCardsDrawable() { char hearts = '\u2764'; //hearts char spades = '\u2660'; //spades char diamonds = '\u2666'; //diamonds char clubs = '\u2663'; //clubs char joker = '\u2668'; //joker cardsDrawable.put("" + 1 + clubs, R.drawable.c_1_of_clubs); //clubs cardsDrawable.put("" + 1 + diamonds, R.drawable.c_1_of_diamonds); //diamonds cardsDrawable.put("" + 1 + hearts, R.drawable.c_1_of_hearts); //hearts cardsDrawable.put("" + 1 + spades, R.drawable.c_1_of_spades); //spades cardsDrawable.put("" + 2 + clubs, R.drawable.c_2_of_clubs); //clubs cardsDrawable.put("" + 2 + diamonds, R.drawable.c_2_of_diamonds); //diamonds cardsDrawable.put("" + 2 + hearts, R.drawable.c_2_of_hearts); //hearts cardsDrawable.put("" + 2 + spades, R.drawable.c_2_of_spades); //spades cardsDrawable.put("" + 3 + clubs, R.drawable.c_3_of_clubs); //clubs cardsDrawable.put("" + 3 + diamonds, R.drawable.c_3_of_diamonds); //diamonds cardsDrawable.put("" + 3 + hearts, R.drawable.c_3_of_hearts); //hearts cardsDrawable.put("" + 3 + spades, R.drawable.c_3_of_spades); //spades cardsDrawable.put("" + 4 + clubs, R.drawable.c_4_of_clubs); //clubs cardsDrawable.put("" + 4 + diamonds, R.drawable.c_4_of_diamonds); //diamonds cardsDrawable.put("" + 4 + hearts, R.drawable.c_4_of_hearts); //hearts cardsDrawable.put("" + 4 + spades, R.drawable.c_4_of_spades); //spades cardsDrawable.put("" + 5 + clubs, R.drawable.c_5_of_clubs); //clubs cardsDrawable.put("" + 5 + diamonds, R.drawable.c_5_of_diamonds); //diamonds cardsDrawable.put("" + 5 + hearts, R.drawable.c_5_of_hearts); //hearts cardsDrawable.put("" + 5 + spades, R.drawable.c_5_of_spades); //spades cardsDrawable.put("" + 6 + clubs, R.drawable.c_6_of_clubs); //clubs cardsDrawable.put("" + 6 + diamonds, R.drawable.c_6_of_diamonds); //diamonds cardsDrawable.put("" + 6 + hearts, R.drawable.c_6_of_hearts); //hearts cardsDrawable.put("" + 6 + spades, R.drawable.c_6_of_spades); //spades cardsDrawable.put("" + 7 + clubs, R.drawable.c_7_of_clubs); //clubs cardsDrawable.put("" + 7 + diamonds, R.drawable.c_7_of_diamonds); //diamonds cardsDrawable.put("" + 7 + hearts, R.drawable.c_7_of_hearts); //hearts cardsDrawable.put("" + 7 + spades, R.drawable.c_7_of_spades); //spades cardsDrawable.put("" + 8 + clubs, R.drawable.c_8_of_clubs); //clubs cardsDrawable.put("" + 8 + diamonds, R.drawable.c_8_of_diamonds); //diamonds cardsDrawable.put("" + 8 + hearts, R.drawable.c_8_of_hearts); //hearts cardsDrawable.put("" + 8 + spades, R.drawable.c_8_of_spades); //spades cardsDrawable.put("" + 9 + clubs, R.drawable.c_9_of_clubs); //clubs cardsDrawable.put("" + 9 + diamonds, R.drawable.c_9_of_diamonds); //diamonds cardsDrawable.put("" + 9 + hearts, R.drawable.c_9_of_hearts); //hearts cardsDrawable.put("" + 9 + spades, R.drawable.c_9_of_spades); //spades cardsDrawable.put("" + 10 + clubs, R.drawable.c_10_of_clubs); //clubs cardsDrawable.put("" + 10 + diamonds, R.drawable.c_10_of_diamonds); //diamonds cardsDrawable.put("" + 10 + hearts, R.drawable.c_10_of_hearts); //hearts cardsDrawable.put("" + 10 + spades, R.drawable.c_10_of_spades); //spades cardsDrawable.put("" + 11 + clubs, R.drawable.c_11_of_clubs); //clubs cardsDrawable.put("" + 11 + diamonds, R.drawable.c_11_of_diamonds); //diamonds cardsDrawable.put("" + 11 + hearts, R.drawable.c_11_of_hearts); //hearts cardsDrawable.put("" + 11 + spades, R.drawable.c_11_of_spades); //spades cardsDrawable.put("" + 12 + clubs, R.drawable.c_12_of_clubs); //clubs cardsDrawable.put("" + 12 + diamonds, R.drawable.c_12_of_diamonds); //diamonds cardsDrawable.put("" + 12 + hearts, R.drawable.c_12_of_hearts); //hearts cardsDrawable.put("" + 12 + spades, R.drawable.c_12_of_spades); //spades cardsDrawable.put("" + 13 + clubs, R.drawable.c_13_of_clubs); //clubs cardsDrawable.put("" + 13 + diamonds, R.drawable.c_13_of_diamonds); //diamonds cardsDrawable.put("" + 13 + hearts, R.drawable.c_13_of_hearts); //hearts cardsDrawable.put("" + 13 + spades, R.drawable.c_13_of_spades); //spades cardsDrawable.put("" + 14 + joker, R.drawable.c_0_of_black); //joker1 cardsDrawable.put("" + 15 + joker, R.drawable.c_0_of_red); //joker2 } public void myCard1OnClick(View view) { Log.d(TAG, "myCard1OnClick. viewSelected? " + view.isSelected()); Drawable highlight = getResources().getDrawable(R.drawable.highlight); String card = myCards.get(0).toString(); if (view.isSelected()) { view.setSelected(false); view.setBackground(null); myCardsDrop.remove((Integer) 0); myCardsDropToString.remove(card); } else { view.setSelected(true); view.setBackground(highlight); myCardsDrop.add(0); myCardsDropToString.add(card); } // ((TextView) findViewById(R.id.my_drop)).setText(myCardsDropToString.toString()); } public void myCard2OnClick(View view) { Log.d(TAG, "myCard2OnClick. viewSelected? " + view.isSelected()); Drawable highlight = getResources().getDrawable(R.drawable.highlight); String card = myCards.get(1).toString(); if (view.isSelected()) { view.setSelected(false); view.setBackground(null); myCardsDrop.remove((Integer) 1); myCardsDropToString.remove(card); } else { view.setSelected(true); view.setBackground(highlight); myCardsDrop.add(1); myCardsDropToString.add(card); } // ((TextView) findViewById(R.id.my_drop)).setText(myCardsDropToString.toString()); } public void myCard3OnClick(View view) { Log.d(TAG, "myCard3OnClick. viewSelected? " + view.isSelected()); Drawable highlight = getResources().getDrawable(R.drawable.highlight); String card = myCards.get(2).toString(); if (view.isSelected()) { view.setSelected(false); view.setBackground(null); myCardsDrop.remove((Integer) 2); myCardsDropToString.remove(card); } else { view.setSelected(true); view.setBackground(highlight); myCardsDrop.add(2); myCardsDropToString.add(card); } // ((TextView) findViewById(R.id.my_drop)).setText(myCardsDropToString.toString()); } public void myCard4OnClick(View view) { Log.d(TAG, "myCard4OnClick. viewSelected? " + view.isSelected()); Drawable highlight = getResources().getDrawable(R.drawable.highlight); String card = myCards.get(3).toString(); if (view.isSelected()) { view.setSelected(false); view.setBackground(null); myCardsDrop.remove((Integer) 3); myCardsDropToString.remove(card); } else { view.setSelected(true); view.setBackground(highlight); myCardsDrop.add(3); myCardsDropToString.add(card); } // ((TextView) findViewById(R.id.my_drop)).setText(myCardsDropToString.toString()); } public void myCard5OnClick(View view) { Log.d(TAG, "myCard5OnClick. viewSelected? " + view.isSelected()); Drawable highlight = getResources().getDrawable(R.drawable.highlight); String card = myCards.get(4).toString(); if (view.isSelected()) { view.setSelected(false); view.setBackground(null); myCardsDrop.remove((Integer) 4); myCardsDropToString.remove(card); } else { view.setSelected(true); view.setBackground(highlight); myCardsDrop.add(4); myCardsDropToString.add(card); } // ((TextView) findViewById(R.id.my_drop)).setText(myCardsDropToString.toString()); } private int getPlayerScore(Participant p) { String id = p.getParticipantId(); int sum = 0; for (Card card : mParticipantCards.get(id)) { sum += card.v; } return sum; } private String formatScoresToString() { String message = ""; if (mMultiplayer) { for (int i = 0; i < mParticipants.size(); i++) { Participant p = mParticipants.get(i); String name = p.getDisplayName(); int sum = highscores[i]; message += name + ": " + sum + System.getProperty("line.separator"); } } else { for (int i = 0; i < mPCParticipants.size(); i++) { PCPlayer p = mPCParticipants.get(i); String name = p.getDisplayName(); int sum = highscores[i]; message += name + ": " + sum + System.getProperty("line.separator"); } } return message; } public void showHighscore(View view) { new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle("Highscores") .setMessage(formatScoresToString()).show(); } public void readyToPlay(View view) { Log.d(TAG, "Ready() "); Button readyButton = (Button) (findViewById(R.id.Ready)); readyButton.setVisibility(View.GONE); readyToPlayPlayers.put(mMyId, true); byte[] sendMsg = new byte[1]; sendMsg[0] = 8; messageToAllParticipants(sendMsg, true); checkReadyList(); } public void dropedCard1OnClick(View view) { takeFromDroppedCards(0); } public void dropedCard2OnClick(View view) { takeFromDroppedCards(1); } public void dropedCard3OnClick(View view) { takeFromDroppedCards(2); } public void dropedCard4OnClick(View view) { takeFromDroppedCards(3); } public void dropedCard5OnClick(View view) { takeFromDroppedCards(4); } public boolean takeFromDroppedCards(int pickedCardIndex) { Log.d(TAG, "myCard1OnClick="); boolean b = checkValidDrop(); if (b) { boolean b2 = checkValidTake(pickedCardIndex); if (b2) { final ArrayList<Card> myDrop = new ArrayList<>(); for (int i = 0; i < myCardsDrop.size(); i++) { int card = myCardsDrop.get(i); myDrop.add(myCards.get(card)); Log.d(TAG, "Dropping: " + myCardsDrop.get(i) + " sym: " + myDrop.get(i)); } for (int i = 0; i < myDrop.size(); i++) { myCards.remove(myDrop.get(i)); } Card pop; ArrayList<Card> lastDrop = primaryDeck.pop(); pop = lastDrop.remove(pickedCardIndex); primaryDeck.add(lastDrop); myCards.add(pop); primaryDeck.add(myDrop); myCardsDrop.removeAllElements(); myCardsDropToString.removeAllElements(); // ((TextView) findViewById(R.id.my_drop)).setText(myCardsDrop.toString()); removeHighLightFromCards(); onTurnFinished((byte) pickedCardIndex, myDrop); //take and drop return true; } else { // toat not valid taking return false; } } else { //toast not valid drop return false; } } private boolean checkValidTake(int dropCard) { Log.d(TAG, "takeFromLastDrop() called "); ArrayList<Card> lastDrop = primaryDeck.peek(); //Taking card from 3 optional options to take. if (lastDropType == 1) { //case one card - taking the only one card are in primary deck. if (dropCard >= 0 && dropCard <= lastDrop.size() - 1) { } else { Toast.makeText(this, "You select illegal cards to take, Try again.", Toast.LENGTH_LONG).show(); return false; } } else if (lastDropType == 2) { //case equal if (dropCard >= 0 && dropCard <= lastDrop.size() - 1) { } else { Toast.makeText(this, "You select illegal cards to take, Try again.", Toast.LENGTH_LONG).show(); return false; } } else { //case order if (dropCard == 0 || dropCard == lastDrop.size() - 1) { } else { Toast.makeText(this, "You select illegal cards to take, Try again.", Toast.LENGTH_LONG).show(); return false; } } return true; } public void cardDeckOnClick(View view) { Log.d(TAG, "cardDeckOnClick"); boolean b = checkValidDrop(); if (b) { final ArrayList<Card> myDrop = new ArrayList<>(); for (int i = 0; i < myCardsDrop.size(); i++) { int card = myCardsDrop.get(i); myDrop.add(myCards.get(card)); Log.d(TAG, "Dropping: " + myCardsDrop.get(i) + " sym: " + myDrop.get(i)); } for (int i = 0; i < myDrop.size(); i++) { myCards.remove(myDrop.get(i)); } if (cardDeck.getSize() == 0) { shuffleCardDeck(); } else { } Card pop = cardDeck.jp.remove(0); myCards.add(pop); primaryDeck.add(myDrop); myCardsDrop.removeAllElements(); myCardsDropToString.removeAllElements(); // ((TextView) findViewById(R.id.my_drop)).setText(myCardsDrop.toString()); removeHighLightFromCards(); onTurnFinished((byte) 5, myDrop); } } private void shuffleCardDeck() { Log.d(TAG, "shuffleCardDeck()"); // Move the cards from primarydeck to card deck. ArrayList<Card> lastCards = primaryDeck.pop(); for (ArrayList<Card> card : primaryDeck) { for (int i = 0; i < card.size(); i++) { cardDeck.addToJackpot(card.remove(i)); } } primaryDeck.removeAllElements(); primaryDeck.add(lastCards); // Suffeling the card deck. cardDeck.shuffle(); // Send the primarydeck and card deck to others participations. sendCardDeckToAllParticipants(true); sendPrimaryDeckToAllParticipants(); } private void removeHighLightFromCards() { Log.d(TAG, "removeHighLightFromCards()"); ((findViewById(R.id.my_card_1))).setBackground(null); ((findViewById(R.id.my_card_2))).setBackground(null); ((findViewById(R.id.my_card_3))).setBackground(null); ((findViewById(R.id.my_card_4))).setBackground(null); ((findViewById(R.id.my_card_5))).setBackground(null); } private boolean checkValidDrop() { if (myCardsDrop == null || myCardsDrop.size() == 0) { Toast.makeText(this, "Select cards to drop, Try again. ", Toast.LENGTH_LONG).show(); return false; } int[] split = new int[myCardsDrop.size()]; for (int i = 0; i < myCardsDrop.size(); i++) { split[i] = myCardsDrop.get(i); } int CVD = checkVaildDrop(split); if (CVD == 0) { Toast.makeText(this, "You enter illegal cards to drop, Try again. ", Toast.LENGTH_LONG).show(); return false; } else { this.myLastDropType = CVD; return true; } } // ######################### SinglePlayer - ONLY ############################### private int numOfPC; private void getNumOfPC() { Log.d(TAG, "getNumOfPC()"); AlertDialog.Builder b = new AlertDialog.Builder(this); b.setTitle("Choose amount of players"); String[] types = { "1", "2", "3" }; b.setItems(types, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { turn = 0; myCards = new Vector<>(); highscores = null; initialAllVal(); dialog.dismiss(); switch (which) { case 0: numOfPC = 1; break; case 1: numOfPC = 2; break; case 2: numOfPC = 3; break; } intialPCParticipantAray(); ownerInitial(); updatePrimaryDeckUI(); } }); b.show(); } private void intialPCParticipantAray() { Log.d(TAG, "intialPCParticipantAray()"); mPCParticipants = new ArrayList<>(); String names[] = getNames(); for (int i = 0; i < numOfPC; i++) { mPCParticipants.add(new PCPlayer(names[i], "" + (i + 1), 0, yanivMinScore)); Log.d(TAG, "intialPCParticipantAray() - i=" + i + " - cards=" + mPCParticipants.get(i).toString()); } } private String[] getNames() { ArrayList<String> names = new ArrayList<>(Arrays.asList("David", "Rony", "Or", "Sapir", "Meni", "Yaron", "Elitzor", "Ron", "Tal", "Vered", "Yeuda", "Yael", "Matan")); String[] ans = new String[numOfPC]; for (int i = 0; i < numOfPC; i++) { int rand = (int) (Math.random() * names.size()); ans[i] = names.remove(rand); } return ans; } public static Stack<ArrayList<Card>> getPrimaryDeck() { return primaryDeck; } public static void setPrimaryDeck(Stack<ArrayList<Card>> primaryDeck) { MainActivity.primaryDeck = primaryDeck; } public static Cards getCardDeck() { return cardDeck; } public void setCardDeck(Cards cardDeck) { this.cardDeck = cardDeck; } public static Vector<Card> getMyCard(String myId) { return mParticipantCards.get(myId); } public static void setMyCard(String myId, Vector<Card> v) { mParticipantCards.put(myId, v); } }