Sign in to follow this  

Card Game

This topic is 4757 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have attempted making a card game in the past with C++, but now im trying to do it using Java for my programming class. Im having trouble thinking of how to represent all the card values and suits, and how to go about shuffling them. I've looked around the web and I found some source code examples, but I couldn't follow most of it, so could someone lead me in the right direction? Any help would be greatly appreciated and I'm not going trying to get anyone to do my homework for me. It's just an open project Im working on. Thanks

Share this post


Link to post
Share on other sites
You can use a 2d array. There would be 4 columns(for each suit) and whatever many rows for the numbers. To shuffle you would have a random variable for the suit and for the value. Once a certain combination comes up once, x it out so it won't come up again. That way cards won't repeat.

Share this post


Link to post
Share on other sites
(by the way,havent done any java. only c++)Dont think that this would be a good idea or not, but here it is:
have a 13 by 4 array of chars, and have the 13 side have all the values,and the 4 side have the suites.
You dont need to shuffle. just keep the cards the way they are,and draw a random element of the remaning cards in that two-dementional array.

Share this post


Link to post
Share on other sites
I don't really like that solution; it doesn't make sense. I think it makes more sense to make a card object and create a list or other collection of all the cards. Here's a (simple) example card class:


public class Card
{
//Define suites (I wish Java had enum)
public static final int Spade = 0;
public static final int Club = 1;
public static final int Diamond = 2;
public static final int Heart = 3;

//Define special cards; other cards are just integers
public static final int Ace = 1;
public static final int Jack = 0;
public static final int Queen = 0;
public static final int King = 0;

public int Suite = 0;
public int Value = 1;

//tells whether the card is face down
public bool Visible = true;
}




To fill the list I would just use nested for loops to create each card; that way you have a list representing the deck that has one copy of each card. To shuffle you can just randomize the order of the objects in the list. (Do Java collections have a way to randomize the order? I mainly use C#.)

I just think that this way is easier to program with because it makes more sense. As you play the game you can have one collection for each place a card can be. For example, with Hearts you could have a list for each person's hand, a list for the cards each person has taken, and a list for the cards in the middle.

Basically, have an object for each card and a list for each pile/group of cards you would have if you were physically playing the game. You can just move the card objects from one group to another as the game logic dictates.

Share this post


Link to post
Share on other sites
a shuffle example


any way im pretty sure this will work in terms of shuffle i would make a function like so:

void Shuffle(Card** DeckToShuffle)
{
Card* Temp_Array[52];
for(int i = 0; i < 52; i++)
{
Temp_Array[i] = NULL;//make all pointers null (not sure if we need this)
};
for(int j = 0; j < 52; j++)
{
int C = rand()%52;//whatever
while(DeckToShuffle[C] == NULL)//we loop through till we find a cell that hasnt been read from if its null we make C a diffrent number
{
C = rand()%52;//im dont know how you get random numbers in java
};
Temp_Array[j] = DeckToShuffle[C];//the Temp array is filling each cell sequentialy while were reading from the DeckToShuffle randomly this is the actual shuffle
DeckToShuffle[C] = NULL;//make it NULL so we know that it has been read from
};
for(int k = 0; k < 52; k++)
{
Temp_Array[k] = DeckToShuffle[k];//transfer the newly shuffled data back to the origonal array passed to the function
}
};




i dont know any java so just take it at face value [smile]
good luck[smile]

NOTE: note sure if java supports typedef if so i would use those for suits and types

Share this post


Link to post
Share on other sites
Quote:
Original post by raptorstrike
you could just use numbers but that could get confusing so i recoment typedef's

for example

typedef WORD Suit;
const Suit HEARTS = 0,
CLUBS = 1,
DIAMONDS = 2,
SPADES = 3;
typedef WORD Number;
const Number Ace = 1,
Two = 2,
Three = 3,
Four = 4,
Five = 5,
Six = 6,
Seven = 7,
Eight = 8,
Nine = 9,
Ten = 10,
Jack = 11,
Queen = 12,
Kind = 13;


this is what Enum's are for.

enum Suit
{
HEARTS,CLUBS,DIAMONDS,SPADES
};

the same should go for "Number" as well. the main advantage as that this is type safe.

Share this post


Link to post
Share on other sites
That's C++...

But yeah... Just have 2 ints for the suit and number also to shuffle, just do
[script]
for ( int i = 0 ; i < count; ++i )
{
r = Math.Rand () * count;
Card temp = array [ i ];
array [ i ] = array [ r ];
array [ r ] = temp;
}
[/script]

Share this post


Link to post
Share on other sites
yeah i looked back at the post and it said changing for C++ to Java not C++ from Java and im like "o crap" [looksaround] and i edited the post

thanks though [smile]

Share this post


Link to post
Share on other sites
Thanks for the help everyone. Im still having some trouble getting this to work. Perhaps my teacher will be able to help me out. For some reason when I try to tackle this type of project I always give up because I can't get this stupid card stuff working. I feel like an idiot because I have been programming for a while now, and I can't get this simple thing working :) oh well, I'll try again tomorrow.

Thanks

Share this post


Link to post
Share on other sites
Heres mine. (c++)
I hope you understand it!


#include <time.h>

class cards {
public:
int value;
char suits;

};

class deck {
public:
cards cardz[53];
deck();
~deck() { };
int shuffle();
};

deck::shuffle() {
srand(time(NULL));
int rannum;
rannum = rand() % 52 + 1; //hmm...don't remember why this is here
int ValueTemp;
char SuitTemp;

for (int i=1;i<52;i++) {
ValueTemp = cardz[i].value; //stores card i value
SuitTemp = cardz[i].suits; //stores card i suit
rannum = rand() % 52 + 1; //picks a random card
cardz[i].value = cardz[rannum].value //stores the value of the random card in card i
cardz[i].suits = cardz[rannum].suits; //stores the suit of the random card in card i
cardz[rannum].value = ValueTemp; //stores the value of the card i value into the random card
cardz[rannum].suits = SuitTemp; //stores the suits of the card i suit into the random card
}
return 0;
}

deck::deck() {
int val=1;
for (int i=1;i<52;i+=4) {
cardz[i].value = val;
cardz[i].suits = 's';

cardz[i+1].value = val;
cardz[i+1].suits = 'c';

cardz[i+2].value = val;
cardz[i+2].suits = 'd';

cardz[i+3].value = val;
cardz[i+3].suits = 'h';
val++;

}

};


Share this post


Link to post
Share on other sites
Actually it seems to me most of these ways arnt the best way of doing it. I had mine STRICTLY marked by my lecturer who programmed FT on importnat projects etc...


mine

Card.h

#ifndef _CARD_H_
#define _CARD_H_

class Card
{
public:
typedef unsigned int suitType;
typedef unsigned int valueType;

const static suitType SUIT_HEARTS;
const static suitType SUIT_CLUBS;
const static suitType SUIT_SPADES;
const static suitType SUIT_DIAMONDS;

const static suitType FIRST_SUIT;
const static suitType LAST_SUIT;

const static valueType MIN_CARD_VALUE;
const static valueType MAX_CARD_VALUE;

Card();
Card(suitType inVal, valueType inSuit);

virtual ~Card();

inline valueType GetCardValue() { return value; };
inline suitType GetCardSuit() { return suit; };

void SetCardValueAndSuit(valueType inVal, suitType inSuit);

private:
bool cardSet;

suitType suit;
valueType value;
};

#endif



card.cpp


#include "Card.h"
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>


const unsigned int Card::SUIT_HEARTS =1;
const unsigned int Card::SUIT_CLUBS =2;
const unsigned int Card::SUIT_SPADES =3;
const unsigned int Card::SUIT_DIAMONDS =4;

const unsigned int Card::FIRST_SUIT =Card::SUIT_HEARTS;
const unsigned int Card::LAST_SUIT =Card::SUIT_DIAMONDS;

const unsigned int Card::MIN_CARD_VALUE =1;
const unsigned int Card::MAX_CARD_VALUE =13;


//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: Card
// Params: value - Number value for the card
// suit - Suit value for the card
// Desc: Constructor. Does simple initialisation of member data to the values specified in the
// parameters. This function is called on object creation.
//////////////////////////////////////////////////////////////////////////////////////////////////
Card::Card()
{
cardSet = false;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: Card
// Params:
// Desc: Constructor. Does simple initialisation of member data to the values specified in the
// parameters. This function is called on object creation.
//////////////////////////////////////////////////////////////////////////////////////////////////
Card::Card(valueType inVal, suitType inSuit)
{
cardSet = false;
SetCardValueAndSuit(inVal, inSuit);
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: ~Card
// Params: N/A
// Desc: Destructor. This function is called on object deletion.
//////////////////////////////////////////////////////////////////////////////////////////////////
Card::~Card()
{

}

//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: SetCardValueAndSuit
// Params: N/A
// Desc: Sets the member value to the value passed in the parameter and do the same for the
// suit.
//////////////////////////////////////////////////////////////////////////////////////////////////
void Card::SetCardValueAndSuit(valueType inVal, suitType inSuit)
{
assert (cardSet == false);
if (cardSet == false)
{
//validate the value and suit
if ( (inVal >= MIN_CARD_VALUE) && (inVal <= MAX_CARD_VALUE) )
{
if ( (inSuit >= FIRST_SUIT) && (inSuit <= LAST_SUIT) )
{
value = inVal;
suit = inSuit;

cardSet = true;
}
else
{
printf("");
;;
}
}
}
}



Deck.h

// Deck.h: interface for the Deck class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_DECK_H__B87D490E_EAA7_4456_BA0B_04C8414A8321__INCLUDED_)
#define AFX_DECK_H__B87D490E_EAA7_4456_BA0B_04C8414A8321__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Card.h"
#include <stdio.h>

#include <string>
#include <time.h>
#include <stdlib.h>
#include <windows.h>
#include <assert.h>
#include <iostream>

using std::string;

class Deck
{
public:
Deck();
virtual ~Deck();

void Shuffle();

void TakeFromTop(Card** outCard);
void PutToBottom(Card** inCard);

private:
typedef unsigned int suitType;
typedef unsigned int valueType;

Card* pCards[52];

unsigned int deckStart;
unsigned int deckEnd;
unsigned int numCardsInDeck;

void SetupDeck();
void SetDeck();
void IncrementDeckStartPtr();
void IncrementDeckEndPtr();
int GenerateRandomNumber(int max);

void mySwap(Card* itemA, Card* itemB);

void DeleteDeck();
};

#endif // !defined(AFX_DECK_H__B87D490E_EAA7_4456_BA0B_04C8414A8321__INCLUDED_)



deck.cpp

// Deck.cpp: implementation of the Deck class.
//
//////////////////////////////////////////////////////////////////////

#include "Deck.h"

namespace
{
const unsigned int SUIT_HEARTS = 1;
const unsigned int SUIT_CLUBS = 2;
const unsigned int SUIT_SPADES = 3;
const unsigned int SUIT_DIAMONDS = 4;

const unsigned int FIRST_SUIT = SUIT_HEARTS;
const unsigned int LAST_SUIT = SUIT_DIAMONDS;

const unsigned int MIN_CARD_VALUE = 1;
const unsigned int MAX_CARD_VALUE = 13;

const unsigned int NUM_SHUFFLE_SWAPS = 100000;

const unsigned int OVERFLOW_INDEX_OF_DECK = 52;
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: Deck
// Params: N/A
// Desc: Constructor.
//////////////////////////////////////////////////////////////////////////////////////////////////
Deck::Deck()
{
SetupDeck();
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: ~Deck
// Params: N/A
// Desc: Destructor
//////////////////////////////////////////////////////////////////////////////////////////////////
Deck::~Deck()
{
DeleteDeck();
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: SetupDeck
// Params: N/A
// Desc: Destructor
//////////////////////////////////////////////////////////////////////////////////////////////////
void Deck::SetupDeck()
{
SetDeck();
Shuffle();
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: SetInDeckCards
// Params: N/A
// Desc: Iterates thorugh the linked list setting the values of the cards.
//////////////////////////////////////////////////////////////////////////////////////////////////
void Deck::SetDeck()
{
unsigned int suitIterator;
unsigned int valueIterator;
unsigned int cardNumIterator = 0;

// set start and end pointers.
deckStart = 0;
deckEnd = (LAST_SUIT * MAX_CARD_VALUE) - 1;
numCardsInDeck = (LAST_SUIT * MAX_CARD_VALUE);

// loop and assign the card values and suits
for (suitIterator = FIRST_SUIT; suitIterator != (LAST_SUIT+1); suitIterator++ )
{
for (valueIterator = MIN_CARD_VALUE; valueIterator != (MAX_CARD_VALUE+1); valueIterator++ )
{
pCards[cardNumIterator] = new Card(valueIterator, suitIterator);
cardNumIterator++;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: Shuffle
// Params: N/A
// Desc: This function shuffles the list of cards. Calls GenerateRandomNumber to select two
// elements from the deck list.
//////////////////////////////////////////////////////////////////////////////////////////////////
void Deck::Shuffle()
{
unsigned int shuffleSwapCount = 0;
unsigned int cardNum1 = 0;
unsigned int cardNum2 = 0;

for ( shuffleSwapCount;
shuffleSwapCount < NUM_SHUFFLE_SWAPS;
shuffleSwapCount++)
{
cardNum1 = GenerateRandomNumber( LAST_SUIT * MAX_CARD_VALUE );
cardNum2 = GenerateRandomNumber( LAST_SUIT * MAX_CARD_VALUE );

mySwap(pCards[cardNum1], pCards[cardNum2]);
}
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: GenerateRandomNumber
// Params: N/A
// Desc: Returns a random number from 1 to max. The first time the function is called, the
// randomiser is seeded. The static variable keeps track of whether the randomiser has
// seeded or not.
//////////////////////////////////////////////////////////////////////////////////////////////////
int Deck::GenerateRandomNumber(int max)
{
static bool beenSeeded;

if (beenSeeded == false)
{
srand(time(NULL));
beenSeeded = true;
}

return (rand() % max);
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: TakeFromTop
// Params: outCard - ptr to be set to the top card.
// Desc: This function will pass a pointer out through the paramater as long as there
// cards in the deck.
//////////////////////////////////////////////////////////////////////////////////////////////////
void Deck::TakeFromTop(Card** outCard)
{
assert(numCardsInDeck != 0);
if ( numCardsInDeck > 0 )
{
// pass out the pointer to the top card
(*outCard) = pCards[deckStart];
pCards[deckStart] = NULL;

IncrementDeckStartPtr();

numCardsInDeck--;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: PutToBottom
// Params: inCard - Ptr to the card to be put back
//
// Desc: -
//////////////////////////////////////////////////////////////////////////////////////////////////
void Deck::PutToBottom(Card** inCard)
{
assert(numCardsInDeck != 52);

if ( numCardsInDeck < 52 )
{
// increment the deckEnd index
IncrementDeckEndPtr();

pCards[deckEnd] = (*inCard);

(*inCard) = NULL;

numCardsInDeck++;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: IncrementDeckStartPtr
// Params: N/A
//
// Desc: Shifts the pointer indicating where the deck starts to the next array member. If
// after the shift the pointer flows over the end of the error it is put to the 0th
// element.
//////////////////////////////////////////////////////////////////////////////////////////////////
void Deck::IncrementDeckStartPtr()
{
// move the deck start pointer
deckStart++;
// loop if necessary
if (deckStart == 52)
{
deckStart = 0;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: IncrementDeckEndPtr
// Params: N/A
//
// Desc: Shifts the pointer indicating where the deck ends to the next array member. If
// after the shift the pointer flows over the end of the error it is put to the 0th
// element.
//////////////////////////////////////////////////////////////////////////////////////////////////
void Deck::IncrementDeckEndPtr()
{
// move the deck end pointer
deckEnd++;
// loop if necessary
if (deckEnd == 52)
{
deckEnd = 0;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: mySwap
// Params: itemA - Pointer to the first card to be swapped
// itemB - Pointer to the second card to be swapped.
// Desc: A Simple swapping function. Swaps what the pointers are pointing at.
//////////////////////////////////////////////////////////////////////////////////////////////////
void Deck::mySwap(Card* itemA, Card* itemB)
{
Card temp;

temp = *itemA;
*itemA = *itemB;
*itemB = temp;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Name: DeleteDeck
// Params: N/A
// Desc: Delete all the cards from the heap. Also keep count of how many have been deleted.
// If the amount deleted does not equal the amount that should be in the deck, throw
// an exception.
//////////////////////////////////////////////////////////////////////////////////////////////////
void Deck::DeleteDeck()
{
unsigned int cardIndex;
unsigned int numCardsDeleted = 0;
for (cardIndex = 0; cardIndex < 52; cardIndex++)
{
if (pCards[cardIndex] != NULL)
{
delete pCards[cardIndex];
numCardsDeleted++;
}
}
// confirm full deletion
if (numCardsDeleted != (LAST_SUIT * MAX_CARD_VALUE))
{
assert(0);
}
}



Ace

Share this post


Link to post
Share on other sites
to keep it simple you could do something like this (pseudoJava)

class Deck{
Deck(){.. CTOR takes care of all initialising stuff, creating the cards ...}
void Shuffle(){... randomize ...}
Card GetCard(){... remove from Deck ...}

// and the cards
vector Cards;
}

class Card{
Card(char value,String suit){}
}


EDIT:
:) and maybe a CardDeckHolder - one of those fancy ones that can shuffle decks and hold many decks at the same time ... would require a modification of the Deck class of course

Share this post


Link to post
Share on other sites
Have you tried snippets.org


/*
** CARDS.HPP - Declare card classes
**
** public domain by Bob Stout
*/


#ifndef CARDS__HPP
#define CARDS__HPP

const int Card_Error = -1;
const int Deck_Size = 52;

typedef enum {Rank_Error = Card_Error, Ace = 1, Deuce, Trey, Spot_4, Spot_5,
Spot_6, Spot_7, Spot_8, Spot_9, Spot_10, Jack = 11, Queen = 12,
King = 13} cardRank;

typedef enum {Suit_Error = Card_Error, Diamond, Club, Heart, Spade} cardSuit;


class card
{
private:
cardRank rank_;
cardSuit suit_;

public:
card(void);
card(cardSuit s, cardRank r);
cardRank rank(void);
cardSuit suit(void);
void get_card(cardSuit &s, cardRank &r);
char *rankText(void);
char *suitText(void);
void set_rank(cardRank r);
void set_suit(cardSuit s);
void set_card(cardSuit s, cardRank r);
};

class deck
{
private:
class card card_[Deck_Size];
unsigned top;

public:
deck(void);
void shuffle(void);
void deal(class card &c);
int cards_left(void);
};

#endif // CARDS__HPP




/*
** CARDS.CPP - Playing card classes
**
** public domain by Bob Stout
*/


#include <stddef.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "cards.hpp"

const char *suits[] = {"Diamonds", "Clubs", "Hearts", "Spades"};
const char *cards[] = {"Ace", "Deuce", "Trey", "4", "5", "6", "7", "8", "9",
"10", "Jack", "Queen", "King"};


inline card::card(void)
{
rank_ = Rank_Error;
suit_ = Suit_Error;
}

inline card::card(cardSuit s, cardRank r)
{
rank_ = r;
suit_ = s;
}

inline cardRank card::rank(void)
{
return rank_;
}

inline cardSuit card::suit(void)
{
return suit_;
}

inline char * card::rankText(void)
{
return (char *)cards[(int)rank_ - 1];
}

inline char * card::suitText(void)
{
return (char *)suits[(int)suit_];
}

inline void card::set_rank(cardRank r)
{
rank_ = r;
}

inline void card::set_suit(cardSuit s)
{
suit_ = s;
}

inline void card::set_card(cardSuit s, cardRank r)
{
rank_ = r;
suit_ = s;
}

inline void card::get_card(cardSuit &s, cardRank &r)
{
r = rank_;
s = suit_;
}


deck::deck(void)
{
int n = 0;

for (int s = int(Diamond); s <= int(Spade); ++s)
{
for (int c = int(Ace); c <= int(King); ++c)
{
deck::card_[n].set_rank(cardRank(c));
deck::card_[n].set_suit(cardSuit(s));
++n;
}
}
top = 0;
}

inline void deck::deal(class card &c)
{
if (top < Deck_Size)
c = deck::card_[top++];
}

inline int deck::cards_left(void)
{
return int(Deck_Size - top);
}

void deck::shuffle(void)
{
int used[Deck_Size], posn = 0;

srand((unsigned)time(NULL) | 1);
memset(used, 0, Deck_Size * sizeof(int));

for (int s = int(Diamond); s <= int(Spade); ++s)
{
for (int c = int(Ace); c <= int(King); ++c)
{
posn = (posn + rand()) % Deck_Size;
while (used[posn])
posn = ++posn % Deck_Size;
deck::card_[posn].set_rank(cardRank(c));
deck::card_[posn].set_suit(cardSuit(s));
used[posn] = -1;
}
}
top = 0;
}

#ifdef TEST

#include <iostream.h>

void showem(class deck &d);

main()
{
class deck d;

cout << "Deck initially:" << endl << endl;
showem(d);
d.shuffle();
cout << endl << "After shuffling:" << endl << endl;
showem(d);
return EXIT_SUCCESS;
}

void showem(class deck &d)
{
for (int i = 0; i <= Deck_Size; ++i)
{
class card card_;

if (0 < d.cards_left())
{
d.deal(card_);
cout << "Card #";
cout.width(2);
cout.setf(ios::left, ios::adjustfield);
cout << (i + 1) << " - " <<
card_.rankText() << " of " <<
card_.suitText() << endl;
}
else cout << "No cards left" << endl;
}
}

#endif // TEST

Share this post


Link to post
Share on other sites
I would say a queue for a deck and have it put random number 1 - 52 in and then draw a number and get a corresponding card object from an arraylist. Or you can make a queue using card object randomly enqueued.

Share this post


Link to post
Share on other sites
Thanks everyone for the help. I got it all working fine now. Ace_lovegrove your code really helped me figure it all out. If anyone ever wants the source to use just PM me, however it's Java not C++.

Share this post


Link to post
Share on other sites
Quote:
Original post by ace_lovegrove
Actually it seems to me most of these ways arnt the best way of doing it. I had mine STRICTLY marked by my lecturer who programmed FT on importnat projects etc...

*** Huge amounts of "industry-standard" code ***


Haha, good one. Er, you *were* joking yes?

Quote:
Original post by Tokiko
Thanks everyone for the help. I got it all working fine now. Ace_lovegrove your code really helped me figure it all out. If anyone ever wants the source to use just PM me, however it's Java not C++.


::shudders in horror::

Share this post


Link to post
Share on other sites
Maybe you need to take a leaf out of the more, and i quote "industry-standard", book.

ace

Share this post


Link to post
Share on other sites
Anyone else looking at this topic, go to this link, it will really help you.

Note it is for Java 1.5.0

http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

[Edited by - TriSwords on January 7, 2005 10:18:00 AM]

Share this post


Link to post
Share on other sites

This topic is 4757 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this