Skip to content

Instantly share code, notes, and snippets.

@Lnirmohi
Last active March 30, 2022 04:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Lnirmohi/4210750ac8380b2be8d0eedf5753ea9b to your computer and use it in GitHub Desktop.
Save Lnirmohi/4210750ac8380b2be8d0eedf5753ea9b to your computer and use it in GitHub Desktop.
import java.util.*;
class Cards{
String suit;
int value;
public Cards( String suit, int value ) {
this.suit = suit;
this.value = value;
}
public String toString() {
if(value > 9){
switch (value){
case 10:
return "10" + " OF " + suit;
case 11:
return "J" + " OF " + suit;
case 12:
return "Q" + " OF " + suit;
case 13:
return "K" + " OF " + suit;
default:
return "A" + " OF " + suit;
}
}
return value + " OF " + suit;
}
}
//using comparator interface to sort hand by suit
class sortBySuit implements Comparator<Cards> {
public int compare( Cards a, Cards b ) {
return a.suit.compareTo(b.suit);
}
}
//using comparator interface to sort hand by value
class sortByValue implements Comparator<Cards> {
public int compare( Cards a, Cards b ) {
return a.value - b.value;
}
}
import java.util.*;
public class Deck{
private final int A = 14,
J = 11,
Q = 12,
K = 13;
private final String SPADE = "SPADE",
CLUB = "CLUB",
HEART = "HEART",
DIAMOND = "DIAMOND";
void fillDeckWithCards(List<Cards> cards){
//creating deck of 4 suits, each containing 13 cards.
for( int i = 2; i < 15; i++ ){
Cards c1 = new Cards( SPADE, i); Cards c3 = new Cards( CLUB, i);
Cards c2 = new Cards( HEART, i); Cards c4 = new Cards( DIAMOND, i);
cards.add(c1); cards.add(c2); cards.add(c3); cards.add(c4);
}
}
List<Cards> shuffleCards(List<Cards> cards){
Random random = new Random();
for(int i = 0; i < 52; i++ ){
int n = random.nextInt(52);
int m = random.nextInt(52);
swap(cards, n , m);
}
return cards;
}
void swap(List<Cards> cards, int n, int m) {
Cards temp = cards.get(n);
cards.set( n, cards.get(m) );
cards.set( m, temp );
}
}
/*
* Player[] array consists of three values i.e name of player, his/her points, cards in hand.
* Sequence[] arrays are used for determining next player in sequence.
* Not using subList to create each player hands because it only creates view and clearing cards List
* gives concurrentmodification exception.
*/
import java.util.*;
public class Hearts{
//deck of 52 cards
private List<Cards> cards = new ArrayList<Cards>(52);
//player objects of type Player initilized with names and 0 pts
private Player player1 = new Player( "SOUTH", 0 );
private Player player2 = new Player( "WEST" , 0 );
private Player player3 = new Player( "NORTH", 0 );
private Player player4 = new Player( "EAST" , 0 );
//default player array names: SOUTH WEST NORTH EAST
private Player[] player = new Player[]{ player1, player2, player3, player4 };
Scanner scan = new Scanner(System.in);
public static void main(String[] args){
Hearts hearts = new Hearts();
hearts.initializeGame();
}
void initializeGame(){
enterPlayersName(inputHowManyPlayers());
Deck deck = new Deck();
//fills a deck with cards
deck.fillDeckWithCards(cards);
startGameLoop(deck);
}
void startGameLoop(Deck deck){
MainLoop loop = new MainLoop();
do{
//shuffles deck
cards = deck.shuffleCards(cards);
//distributes card among players and sort hand of each
//player with the help of Collection.sort and comparator interface.
distributeCards();
//sorting each player's hand
sortHand();
//clear the card list to accumlate 12 cards passed by players.
cards.clear();
//ask players to pass cards to players on their left.
playerTurnToPassCards();
//adding passed cards to players
passCards();
//sorting each player's hand
sortHand();
//remove 12 passed cards
cards.clear();
loop.mainLoop(player, cards);
}while( player1.points < 100 && player2.points < 100 && player3.points < 100 && player4.points < 100 );
whoWonTheGame();
}
int inputHowManyPlayers(){
int noOfPlayers = -1;
//input validation
//change noOfPlayers < 0 and enter 0 to make computer play whole game while noOfPlayer is asked to input.
while(noOfPlayers < 1 || noOfPlayers > 4){
System.out.println( "\nChoose how many players will play(1-4): " );
///input validation
try{
noOfPlayers = scan.nextInt();
}
catch( Exception e ) {
System.out.println( "Please enter a number form 1-4!" );
scan.nextLine();
continue;
}
scan.nextLine();
}
return noOfPlayers;
}
void enterPlayersName(int noOfPlayers){
System.out.println("\nEnter player names!");
for( int i = 0; i < noOfPlayers; i++ ) {
System.out.print("\nEnter " + (i+1) + " player's name : ");
player[i].playerName = scan.nextLine().toUpperCase();
player[i].isPlayerHuman = true;//declares player is human and not a computer.
}
System.out.println( "\n\nPlayer 1: " + player[0].playerName + "\nPlayer 2: " + player[1].playerName +
"\nPlayer 3: " + player[2].playerName + "\nPlayer 4: " + player[3].playerName + "\n" );
}
void whoWonTheGame(){
int lowestPoints = 1000;
String winner = "";
for( int i = 0; i < 4; i++ ){
if( player[i].points < lowestPoints ){
winner = player[i].playerName;
lowestPoints = player[i].points;
}
}
System.out.println( "\n\t\t\t\t\t\t\t" + winner + " won the game!" );
}
void distributeCards() {
//distributes cards among players
for( int i = 0; i < 52; ) {
player[0].playerHand.add( cards.get(i++) ); player[1].playerHand.add( cards.get(i++) );
player[2].playerHand.add( cards.get(i++) ); player[3].playerHand.add( cards.get(i++) );
}
}
void displayHand( List<Cards> playerHand ) {
for( int i = 0; i < playerHand.size(); i++ ) {
System.out.println( (i+1) + ":\t" + playerHand.get(i) );
}
}
void playerTurnToPassCards(){
for(int i = 0; i < 4; i++){
//last player pass cards to first player.
if( i == 3 )
System.out.println( "\n" + player[i].playerName + " pass 3 cards to " + player[0].playerName + "." );
else
System.out.println( "\n" + player[i].playerName + " pass 3 cards to " + player[i+1].playerName + "." );
if(player[i].isPlayerHuman == true)
choseCardsToPass(i);
else if(player[i].isPlayerHuman == false)
computerSelectsThreeCards(i);
}
}
void choseCardsToPass(int i){
int[] passedCards = new int[]{ 1, 1, 1 };
displayHand( player[i].playerHand );
while( passedCards[0] == passedCards[1] || passedCards[1] == passedCards[2] || passedCards[0] == passedCards[2] ){
System.out.println( "\nPlease select three DIFFERENT number in front of cards you want to pass(1-13):" );
try{
System.out.print( "First Card: " );
passedCards[0] = scan.nextInt() - 1;//array starts from index 0
System.out.print( "Second Card: " );
passedCards[1] = scan.nextInt() - 1;
System.out.print( "Third Card: " );
passedCards[2] = scan.nextInt() - 1;
}catch( Exception e ){
scan.next();//consumes nextLine character
passedCards[0] = passedCards[1] = passedCards[2] = 1;
continue;
}
//if player enters a number less than 1 or a greater than 13
if( passedCards[0] < 0 || passedCards[0] > 12 || passedCards[1] < 0 || passedCards[1] > 12 || passedCards[2] < 0 || passedCards[2] > 12 ) {
passedCards[0] = passedCards[1] = passedCards[2] = 1;
continue;
}
}
passedCards = sortPassedCards(passedCards);
removeCardsFromPlayerHandAfterPassing(i, passedCards);
}
void computerSelectsThreeCards(int i){
Random random = new Random();
int[] passedCards = new int[]{ 1, 1, 1 };
System.out.println("\n");
displayHand( player[i].playerHand );
System.out.println( "\nPlease select three DIFFERENT number in front of cards you want to pass(1-13):" );
passedCards[0] = random.nextInt(13);
//to make sure passed cards are not same
do{
passedCards[1] = random.nextInt(13);
}
while(passedCards[1] == passedCards[0]);
//to make sure passed cards are not same
do{
passedCards[2] = random.nextInt(13);
}while(passedCards[2] == passedCards[0] || passedCards[2] == passedCards[1]);
passedCards = sortPassedCards(passedCards);
System.out.println( "First Card: " + (passedCards[0]+1) );
System.out.println( "Second Card: " + (passedCards[1]+1) );
System.out.println( "Third Card: " + (passedCards[2]+1) );
removeCardsFromPlayerHandAfterPassing(i, passedCards);
}
int[] sortPassedCards(int[] passedCards){
for( int j = 1; j < 4; j++ ) {
int temp;
if( passedCards[0] > passedCards[1] ) {
temp = passedCards[0];
passedCards[0] = passedCards[1];
passedCards[1] = temp;
}
if( passedCards[1] > passedCards[2] ) {
temp = passedCards[1];
passedCards[1] = passedCards[2];
passedCards[2] = temp;
}
if( passedCards[0] < passedCards[1] && passedCards[1] < passedCards[2] )
break;
}
return passedCards;
}
void removeCardsFromPlayerHandAfterPassing(int i, int[] passedCards){
//using empty cards list to hold passed cards
//adding removed cards to list cards
//which is empty after cards were distuributed among players
cards.add( player[i].playerHand.get( passedCards[0]) );
cards.add( player[i].playerHand.get( passedCards[1]) );
cards.add( player[i].playerHand.get( passedCards[2]) );
//removing passed cards from player's hand
player[i].playerHand.remove( player[i].playerHand.get( passedCards[0]) );
player[i].playerHand.remove( player[i].playerHand.get( passedCards[1]-1) );
player[i].playerHand.remove( player[i].playerHand.get( passedCards[2]-2) );
}
void passCards(){
int[] cardPassingSequence = new int[]{ 1, 2, 3, 0 };
//finally adding passed cards to players
//from cards list to playerhand
//cardPassingSequence array is used to loop through players array
for( int k = 0, l = 0; k < cardPassingSequence.length; k++, l += 3 ){
player[cardPassingSequence[k]].playerHand.add( cards.get(0+l) );//adding 'l' i.e 3, 6, 9 to increase
player[cardPassingSequence[k]].playerHand.add( cards.get(1+l) );//cards index
player[cardPassingSequence[k]].playerHand.add( cards.get(2+l) );
}
}
void sortHand(){
for( int i = 0; i < 4; i++ ){
Collections.sort( player[i].playerHand, new sortByValue() );
Collections.sort( player[i].playerHand, new sortBySuit() );
}
}
}
/*
* Player holding 2 OF CLUB will begin the TRICK.
* The game logic consists of 13 iteration of mainloop i.e trickLoop < 13.
* For each iteration of mainLoop, there is 4 iteration of trickLoop i.e innerloop < 4.
* Each iteration of trickLoop asks player to play a valid card.
* First card of first GAME i.e when mainLoop & trickLoop both are 0, player should play 2 of CLUB.
* First player can decide which suit to play except HEART.
* HEART can be played only when it is broken i.e player's hand does not contain card
* similar to suitInPlay or player is left with all HEART cards.
* Each time a card is played, it's suit value i.e SPADE, CLUB, HEART, DIAMOND is checked.
* All the players have to follow the suit played by first player.
* If the card played doesn't follow the suit in play i.e suitInPlay, player's hand is
* checked for if it contains suitInPlay or not.
*/
import java.util.*;
class LoopCount{
int mainLoopCount;
int trickLoopCount;
}
public class MainLoop{
Scanner loopScan = new Scanner(System.in);
final int[] SEQUENCE1 = new int[]{ 0, 1, 2, 3 };
final int[] SEQUENCE2 = new int[]{ 1, 2, 3, 0 };
final int[] SEQUENCE3 = new int[]{ 2, 3, 0, 1 };
final int[] SEQUENCE4 = new int[]{ 3, 0, 1, 2 };
//sequence to follow for each player e.g if second player starts the trick sequence will be equal to SEQUENCE2.
private int[] sequence;
//container for card played in one trick
private Cards[] handContainer = new Cards[4];
//suit which is to be followed by players.
private String suitInPlay = "CLUB";
//boolean to check if heart is broken or not.
private boolean heartBroken = false;
void mainLoop(Player[] player, List<Cards> cards){
heartBroken = false;
//finds first player for first time i.e when outerlopp = 0;
String firstPlayer = has2OfCLUB(player);
LoopCount loopCount = new LoopCount();
for(loopCount.mainLoopCount = 0; loopCount.mainLoopCount < 13; loopCount.mainLoopCount++){
//decides which sequence to follow
sequence = decideSequence(firstPlayer, player);
//runs 4 times each time a players turn to play a valid card
trickLoop(loopCount, player);
//decides who will start the next TRICK i.e player with card having highest value A being heighest and 2 being lowest.
firstPlayer = whoGetsPoints(player);
showPointsDistribution(player);
addingCardsBackToDeck(cards);
}
}
String has2OfCLUB(Player[] player){
for(int i = 0; i < 4; i++){
if( player[i].playerHand.get(0).suit.equals("CLUB") && player[i].playerHand.get(0).value == 2 ) {
System.out.println("\nThe 2 OF CLUB starts the game. " + player[i].playerName + " play 2 OF CLUB.");
return player[i].playerName;
}
}
return null;
}
int[] decideSequence(String firstPlayer, Player[] player){
//return the sequence to be followed while playing the trick, each index decides player's no.
for(int i = 0; i < 4; i++){
if( firstPlayer.equals( player[0].playerName ) )
return SEQUENCE1;
else if( firstPlayer.equals( player[1].playerName ) )
return SEQUENCE2;
else if( firstPlayer.equals( player[2].playerName ) )
return SEQUENCE3;
else if( firstPlayer.equals( player[3].playerName ) )
return SEQUENCE4;
}
return null;
}
void trickLoop(LoopCount loopCount, Player[] player){
for(loopCount.trickLoopCount = 0; loopCount.trickLoopCount < 4; loopCount.trickLoopCount++){/*==============TRICK=================*/
//asks player to play a card.
playCard(loopCount, player[sequence[loopCount.trickLoopCount]]);
//card played by first player becomes suitInPlay.
suitInPlay = handContainer[0].suit;
//display notification after card is played.
displayInGameNotifications();
//show cards played in TRICK
showHand(handContainer, loopCount.trickLoopCount);
}
}
void playCard(LoopCount loopCount, Player currentPlayer){
int cardPlayed;
do{
displayHand(currentPlayer.playerHand);
if(currentPlayer.isPlayerHuman == true)
cardPlayed = getCardNumber(-1, currentPlayer.playerName); //gets card number from player
else{
//if player is computer
cardPlayed = selectCardsForComputer(currentPlayer, loopCount);
System.out.print( "\n" + currentPlayer.playerName + "'s turn. Play a valid card: " + (cardPlayed+1));
break;
}
//part below runs only if the player is not computer
//first card of each GAME needs to be 2 of CLUB
if(loopCount.mainLoopCount == 0 && loopCount.trickLoopCount == 0 && cardPlayed != 0){
System.out.println("\nPlease play 2 of CLUB!" );
System.out.println("\nPlease play " + suitInPlay + "\n");
}else if(loopCount.mainLoopCount == 0 && (currentPlayer.playerHand.get(cardPlayed).suit.equals("HEART") ||
(currentPlayer.playerHand.get(cardPlayed).suit.equals("SPADE") &&
currentPlayer.playerHand.get(cardPlayed).value == 12))){
System.out.println( "\nA Heart or the Q of SPDADE cannot be played for first trick.");
}else if(validSuit( currentPlayer, cardPlayed, loopCount ))// if card is valid break the loop
break;
}while(true);
if(currentPlayer.playerHand.get(cardPlayed).suit.equals("HEART"))
heartBroken = true;
//card is removed from player's hand and added to handContainer array
handContainer[loopCount.trickLoopCount] = currentPlayer.playerHand.remove( cardPlayed );
}
void displayHand(List<Cards> playerHand){
for(int i = 0; i < playerHand.size(); i++)
System.out.println( (i+1) + ":\t" + playerHand.get(i) );
}
int getCardNumber(int cardPlayed, String playerName){
while( cardPlayed < 0 || cardPlayed > 12 ){
System.out.print( "\n" + playerName + "'s turn. Play a valid card: ");
//input validation
try{
cardPlayed = loopScan.nextInt() - 1;
}catch( Exception e ){
System.out.println( "Please enter valid number(1-13):" );
loopScan.nextLine();
continue;
}
loopScan.nextLine();
}
return cardPlayed;
}
boolean validSuit(Player player, int cardPlayed, LoopCount loopCount){
boolean containsSuit = false;
try{
//checking if player has card of suit which is in play i.e suitInPlay if he plays card other than suitInPlay
if( !player.playerHand.get(cardPlayed).suit.equals(suitInPlay) ){
containsSuit = validCard( player, cardPlayed, loopCount);
return containsSuit;
}
}catch(Exception e){
System.out.println("Please enter valid card number!\n");
return false;
}
return !containsSuit;
}
boolean validCard(Player player, int cardPlayed, LoopCount loopCount){
if(loopCount.mainLoopCount == 0 && (player.playerHand.get(cardPlayed).suit.equals("HEART") ||
(player.playerHand.get(cardPlayed).suit.equals("SPADE") && player.playerHand.get(cardPlayed).value == 12)))
return false;
else if(player.playerHand.get(cardPlayed).suit.equals("HEART") ){//If card played by player is HEART
return checkForHEART(loopCount, player);
}else if(!player.playerHand.get(cardPlayed).suit.equals(suitInPlay) && loopCount.trickLoopCount > 0){//trickLoopCount > 0 to not check first card unless it's HEART.
//if player's hand contains card of suitInPlay returns false
if(suitCheckingLoop(player, suitInPlay))
return false;
}
return true;
}
boolean checkForHEART(LoopCount loopCount, Player player){
//If first card played is HEART
if(loopCount.trickLoopCount == 0){
//If first card played is HEART and HEART is not broken
if(heartBroken == false){
//to check if player hand contains all HEART card
for(int n = 0; n < player.playerHand.size(); n++){
if(!player.playerHand.get(n).suit.equals("HEART"))
return ifHeartIsNotBroken(player.isPlayerHuman);
}
}
}else if(loopCount.trickLoopCount > 0){
if(suitCheckingLoop(player, suitInPlay))
return false;
}
if(player.isPlayerHuman == true)
System.out.println("\n\t\t\t\tHeart is borken!");
return true;
}
boolean suitCheckingLoop(Player player, String suitToCheck){
for(int k = 0; k < player.playerHand.size(); k++){
if(player.playerHand.get(k).suit.equals(suitToCheck)){
if( player.isPlayerHuman == true)
System.out.println("\nPlease play " + suitInPlay + "!\n");
return true;
}
}
return false;
}
boolean ifHeartIsNotBroken(boolean isPlayerHuman){
if(isPlayerHuman == true)
System.out.println("\nHeart is not broken! You can't play a HEART unless it's broken.\n");
return false;
}
void displayInGameNotifications(){
System.out.println( "\n\t\t\t\tSuit in play: " + suitInPlay + "\n" );
System.out.println( "\t\t\t\tHeart broken: " + isHeartBroken() );
System.out.println( "\n\t\t\t\tCurrent Hand: ");
}
void showHand(Cards[] handContainer, int trickLoopCount){
for( int i = 0; i <= trickLoopCount; i++ )
System.out.println( "\t\t\t\t" + handContainer[i]);
}
void showPointsDistribution(Player[] player){
System.out.println("\n\t\t\t\t\tPoints");
for( int i = 0; i < 4; i++ )
System.out.println("\t\t\t\t"+ player[i].playerName + ": \t" + player[i].points);
}
//indicates if HEART is broken or not.
String isHeartBroken(){
if( heartBroken == true )
return "Yes";
else
return "No";
}
String whoGetsPoints(Player[] player){
int largest = handContainer[0].value;
int indexOfBiggestCard = 0;
int pointsInTheTrick = 0;
for( int i = 1; i < 4; i++ ){
//suit played by first player has to be followed by other players unless they
//dont have card that belongs to suit played by first player i.e suitInPlay
if( handContainer[0].suit.equals(handContainer[i].suit) && handContainer[i].value > largest ){//handContainer[0].suit is suit of card played by first player.
largest = handContainer[i].value;
indexOfBiggestCard = i;
}
}
//determines how many points to add to players point table;
pointsInTheTrick = determinePoints(pointsInTheTrick);
player[sequence[indexOfBiggestCard]].points += pointsInTheTrick;
//returns name of player holding heighest card in each TRICK
return player[sequence[indexOfBiggestCard]].playerName;
}
int determinePoints(int pointsInTheTrick){
for( int j = 0; j < 4; j++ ){
//if card is of HEART suit one point is added and if card is Q of CLUB then 13 points are added.
if( handContainer[j].suit.equals("HEART") || (handContainer[j].suit.equals("SPADE") && handContainer[j].value == 12) ){
if( handContainer[j].suit.equals("HEART") )
pointsInTheTrick++;
else if(handContainer[j].suit.equals("SPADE") && handContainer[j].value == 12 )
pointsInTheTrick += 13;
}
}
return pointsInTheTrick;
}
void addingCardsBackToDeck(List<Cards> cards){
for( int k = 0; k < 4; k++ )
//cards which are played are added back to the deck.
cards.add( handContainer[k] );
}
int selectCardsForComputer(Player player, LoopCount loopCount){
Random random = new Random();
List<Integer> validCardsForComputerToPlay = new ArrayList(13);
if(loopCount.mainLoopCount == 0 && loopCount.trickLoopCount == 0)
return 0;
validCardsForComputerToPlay.clear();
for(int i = 0; i < player.playerHand.size(); i++){
if(validSuit(player, i, loopCount)){
validCardsForComputerToPlay.add(i);
//uncomment the belove line to see no of playable cards for computer player
System.out.println(i+1);
}
}
//size for random.nextInt
int playableCards = validCardsForComputerToPlay.size();
return validCardsForComputerToPlay.get(random.nextInt(playableCards));
}
}
import java.util.*;
public class Player
{
String playerName;
int points;
List<Cards> playerHand = new ArrayList<Cards>(13);
Player( String playerName, int points ) {
this.playerName = playerName;
this.points = points;
}
public String toString() {
return playerName + ": " + points;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment