My code works as expected except for when I add a playerHand, which is a list of cards, to a playerHands list, it changes all previous player hands in the list to the current playerHand.
My thought as to what is happening is that there is only one playerHand in memory which is constantly being updated with dealt cards. The items in playerHands list are simply pointing to that single playerHand.
How do I create multiple instances of playerHand so that each item in the playerHands list is unique?
Note: my initial reaction was to use Arrays instead of List, but as far as I can tell Arrays are old-school and deprecated in favor of List.
Solving my problem is my goal here but if there are any thoughts as to the direction I am taking with this program would be accepted.
using System;
using System.Collections.Generic;
namespace Blackjack
{
class Program
{
static void Main()
{
int numOfDecks = 2;
List<Cards> shoe = Deck.createDeck(numOfDecks);
Deck.shuffleDeck(shoe, numOfDecks);
Hand playerHand = new Hand();
Hands playerHands = new Hands();
//Test Hands
//Create ten hands of dealt cards
for (int i = 0 ; i < 10; i++)
{
playerHand.clearHand();
playerHands.addHand(playerHand);
for (int j = 0; j < 5; j++)
{
playerHand.addCard(shoe[j]);
shoe.RemoveAt(0); //delete card delt from shoe
}
}
//Display the cards in each of the hands
for (int i = 0; i < playerHands.hands.Count; i++)
{
Console.Write("Hand {0}: Cards: ", i);
for (int j = 0; j < playerHand.hand.Count; j++)
{
Console.Write("{0}{1}, ", playerHands.hands[i].hand [j].rank, playerHands.hands[i].hand[j].suit);
}
Console.WriteLine();
}
Console.Read();
}
}
}
class Hand
{
/////////////////////////////////////////////////////////////////////
//Hand should contain, at a minimum:
// A List<> of cards that holds the individual cards delt to a player
// Game Number: A game is continues until the player quits
// Hand Number: Sequential hand played during a game
//////////////////////////////////////////////////////////////////////
public List<Cards> hand;
public Hand()
{
hand = new List<Cards>();
}
public void addCard(Cards card)
{
this.hand.Add(card);
}
public void clearHand()
{
hand.Clear();
}
}
class Hands
{
public List<Hand> hands;
public Hands()
{
hands = new List<Hand>();
}
public void addHand(Hand hand)
{
hands.Add(hand);
}
}
The issue is really, really simple: you are not creating enough Hand instances.
You call Hand playerHand = new Hand(); just once.
This means you have only one Hand instance, which you are clearing and filling over and over in your first for loop.
You need to call new Hand() once for each hand instance (just editing the relevant part of your code):
Hands playerHands = new Hands();
//Test Hands
//Create ten hands of dealt cards
for (int i = 0 ; i < 10; i++)
{
Hand playerHand = new Hand();
playerHands.addHand(playerHand);
for (int j = 0; j < 5; j++)
{
playerHand.addCard(shoe[j]);
shoe.RemoveAt(0); //delete card delt from shoe
}
}
Have fun!
Related
This is my first time using C#. I have to convert an old project from Java. The old project works, but when I attempted to convert it, something went wrong? The Card class sets the default card to the Ace of Spades, but it is displaying Ace of Clubs. Ace and Clubs are each the first listed of the enums so I guess it is not using the default?
Since it is displaying the same card I thought it would be something wrong with my shuffle method..but I am unsure at this point.
There is a Card, Deck, and Hand class. Then Enums for Suit and Face.
UPDATE: I believe the error is in the method directly below? I need to figure out how to use the 'n' in c#. It is needed in a different class.
In Java I had it as:
public Card(int n)
{
face = Face.values()[n % 13];
suit = Suit.values()[n % 4];
} //end Card (int n) method
c#:
public Card(int n) //??
{
var face = (Face) 13;
var suit = (Suit) 4;
}
The code above is in the Card class? I know that is not too helpful, but the only other way it to post ALL of the code here.
//Some of the Deck class
public void Shuffle()
{
Random ran = new Random();
for (int nextCard = 0; nextCard < deck.Length; nextCard++)
{
Card hold = deck[nextCard];
int random = ran.Next(deck.Length);
deck[nextCard] = deck[random];
deck[random] = hold;
}
}
public Card DealACard()
{
if (nextCard > 51)
{
return null;
}
return deck[nextCard++];
}
public Hand DealAHand(int handSize)
{
Hand hand = new Hand(handSize);
for (int i = 0; i < handSize; i++)
{
hand.AddCard(DealACard());
}
return hand;
}
//Some of the Hand Class
public void AddCard(Card card)
{
hand[cardsInHand] = card;
cardsInHand++;
}
public override string ToString()
{
String handToString = ""; //string to hold display format
//for loop to display each card in a hand
for (int n = 0; n < cardsInHand; n++)
{
handToString += hand[n].ToString() + "\n";
}
return handToString;
}
// Driver Class
Deck deck1 = new Deck();
int cardsToGet = 53;
do
{
Console.Write("How many cards are in one hand? ");
int handSize = Convert.ToInt32(Console.ReadLine());
// int handSize = Console.Read();
Console.Write("How many players are playing? ");
int players = Convert.ToInt32(Console.ReadLine());
cardsToGet = handSize * players;
if (cardsToGet < 53) // if to shuffle deck and display players' hands
{
deck1.Shuffle();
for (int i = 0; i < players; i++) // displays each players hand
{
Console.WriteLine("\nPlayer " + (i + 1) + ":");
Console.WriteLine(deck1.DealAHand(handSize));
}
}
else
{
Console.WriteLine("\nThere are not enough cards in the deck to deal " + players + " hands of " + handSize + " cards. Try again.\n");
}
}
while (cardsToGet > 52);
It is suppose to ask for a number of cards per hand and a number of players then displays a hand for each player without duplicating cards. Currently, it fills every players hand with Ace of Clubs. There are no errors showing.
Now that you've updated your question, this is answerable. The mistake is in your Card constructor, which no matter the value of n that you pass in, creates every card with the Face with value 13 and the Suit with value 4. You have the right method for turning an int into a Face or Suit enum (just cast it), so you just need to do the modulo operation like your Java version did:
public Card(int n)
{
var face = (Face) n % 13;
var suit = (Suit) n % 4;
}
Well, almost. The var keyword in C# just creates a local variable that's not visible outside the scope it's declared in: in this case, the constructor. What you meant to do is assign values to instance properties of your Card class. You haven't shown us what those properties are named, but I'm going to assume they're named Face and Suit (with initial uppercase as is C# naming convention); rename as appropriate:
public Card(int n)
{
this.Face = (Face) n % 13;
this.Suit = (Suit) n % 4;
}
And now your cards should all be different, rather than all being the ace of clubs.
Hello TJ and welcome to S/O, coming from other languages can be a learning curve. Same as if I switched to Java. I quickly threw this together to introduce working with lists and classes within C#. Not perfect, but does what you are looking to get at. Hope it helps. I originally wrote this with C# via a WPF application vs Console app, but the core is all the same (only thing that would be different is the "MessageBox.Show()" that shows each hand vs the Console output which I also included.
I am notorious for commenting through my code and hope this all (or most of it) makes sense as you dive into C#...
I'm starting with enums for the card faces and suits.
public enum CardFace
{
Two = 0,
Three = 1,
Four = 2,
Five = 3,
Six = 4,
Seven = 5,
Eight = 6,
Nine = 7,
Ten = 8,
Jack = 9,
Queen = 10,
King = 11,
Ace = 12
}
public enum CardSuit
{
Hearts = 0,
Clubs = 1,
Diamonds = 2,
Spades = 3
}
Next, a class to represent a single card
public class SingleCard
{
public CardFace Face { get; set; }
public CardSuit Suit { get; set; }
// place-holder for randomizing cards
public int RndNumber { get; set; }
// return the name of the card based on it's parts as single string
public string NameOfCard { get { return $"{Face} of {Suit}"; } }
}
Now, the class for building the initial deck of cards, shuffling, dealing and displaying the cards (of the entire deck, or of the individual hands)
public class DeckOfCards
{
public List<SingleCard> SingleDeck { get; private set; } = new List<SingleCard>();
public List<SingleCard> ShuffledDeck { get; private set; }
// create a single random generator ONCE and leave active. This to help prevent
// recreating every time you need to shuffle and getting the same sequences.
// make static in case you want multiple decks, they keep using the same randomizing object
private static Random rndGen = new Random();
public DeckOfCards()
{
// build the deck of cards once...
// Start going through each suit
foreach (CardSuit s in typeof(CardSuit).GetEnumValues())
{
// now go through each card within each suit
foreach (CardFace f in typeof(CardFace).GetEnumValues())
// Now, add a card to the deck of the suite / face card
SingleDeck.Add(new SingleCard { Face = f, Suit = s });
}
// so now you have a master list of all cards in your deck declared once...
}
public void ShuffleDeck()
{
// to shuffle a deck, assign the next random number sequentially to the deck.
// don't just do random of 52 cards, but other to prevent duplicate numbers
// from possibly coming in
foreach (var oneCard in SingleDeck)
oneCard.RndNumber = rndGen.Next(3901); // any number could be used...
// great, now every card has a randomized number assigned.
// return the list sorted by that random number...
ShuffledDeck = SingleDeck.OrderBy( o => o.RndNumber).ToList();
}
public void DisplayTheCards( List<SingleCard> theCards )
{
// show the deck of cards, or a single person's hand of cards
var sb = new StringBuilder();
foreach (var c in theCards)
sb = sb.AppendLine( c.NameOfCard );
MessageBox.Show(sb.ToString());
}
public void ConsoleDisplayTheCards(List<SingleCard> theCards)
{
// show the deck of cards, or a single person's hand of cards
foreach (var c in theCards)
Console.WriteLine(c.NameOfCard);
}
public List<List<SingleCard>> DealHands( int Players, int CardsPerHand )
{
// create a list of how many hands to be dealt...
// each player hand will consist of a list of cards
var Hands = new List<List<SingleCard>>(Players);
// prepare every players hand before dealing cards
for (var curPlayer = 0; curPlayer < Players; curPlayer++)
// each player gets their own list of cards
Hands.Add( new List<SingleCard>());
// prepare card sequence to deal
var nextCard = 0;
// loop for as many cards per hand
for (var oneCard = 0; oneCard < CardsPerHand; oneCard++)
{
// loop every player gets a card at a time vs one player gets all, then next player
for (var curPlayer = 0; curPlayer < Players; curPlayer++)
// add whatever the next card is to each individual's hand
Hands[curPlayer].Add(ShuffledDeck[nextCard++]);
}
return Hands;
}
}
I did not include the input of getting how many players, how many cards as you already had that. I also did not validate total cards to be dealt as you had that too. HTH
I have 3 classes in my program: Program, Board, and Square.
In program I'm creating a new board:
class Program
{
static void Main(string[] args)
{
Board b = new Board();
}
}
Now I'm looking for a way to call the Board I created here in my Square class.
Anyone have an Idea how to do this? (not to create a new Board in the Square class).
Edit:
I'm trying to create a simple mine-sweeper game.
In the Board class I have a two-dimensional array of Squars. then I creat in each part of the square array a new Square. Then the board is creating mines with the "AddMine" function in the Square class. I have deleted the way the board is choosing which square to set to a mine.
class Board
{
public Square[,] board;
public int n;
public Board()
{
Console.Write("Enter the nuber of rows on column(int): ");
n = int.Parse(Console.ReadLine());
board = new Square[n, n];
mines = (n * n) / 6;
for (int row = 0; row < board.GetLength(0); row++)
{
for (int col = 0; col < board.GetLength(1); col++)
{
board[row, col] = new Square(row, col);
}
}
board[row, col].AddMine();
}
}
In the Square class, at first it is setting is val to 0. After that when I'm calling The "AddMine" function from board, I need to add one to the val of each Square nearby the square who is set to mine.
class Square
{
public Board b;
private int row, col;
public int val;
private bool open;
public Square(int row, int col)
{
this.row = row;
this.col = col;
open = false;
val = 0;
}
public void AddMine()
{
#region set this to bomb (-9), nearby squars ++
val = -9;
b.board[row, (col + 1)].val++;
#endregion
}
}
The real question is how do I call the board array in the Board class in the Square class? because this way is not working, I get a 'System.NullReferenceException' error, I know it is because b is set to 'null', but I don't know to what to do so it will be able to see the Board from Main in Programe class.
All the answers I found in the internet is or to set a new Board, or to set a prorame class in the squarwe class, but because I'm setting a new board in a static function, it is not working.
Thanks to anyone for helping and I hope now the question is clearer.
As many have said you need to pass the reference to the board into the Square. You almost have it in your example, you just don't actually pass the board in.
Here's what your square class should look like.
class Square
{
public Board b;
private int row, col;
public int val;
private bool open;
public Square(Board board, int row, int col)
{
this.row = row;
this.col = col;
open = false;
val = 0;
**b = board;**
}
public void AddMine()
{
#region set this to bomb (-9), nearby squars ++
val = -9;
b.board[row, (col + 1)].val++;
#endregion
}
}
You received the null reference exception because you never actually set the board object so it was null when you tried to use it.
Then to edit your board example, this is how you would add the new squares.
class Board
{
public Square[,] board;
public int n;
public Board()
{
Console.Write("Enter the nuber of rows on column(int): ");
n = int.Parse(Console.ReadLine());
board = new Square[n, n];
mines = (n * n) / 6;
for (int row = 0; row < board.GetLength(0); row++)
{
for (int col = 0; col < board.GetLength(1); col++)
{
board[row, col] = new Square(this, row, col);
}
}
board[row, col].AddMine();
}
}
The "this" keywoard is just a reference to the calling object.
That should solve your problem, but I should note this is not usually considered the best practice. It seems your heading in the direction of tightly coupling your classes which can easily lead to smelly and unmaintainable code. You should look into tightly coupled vs loosely coupled code. A quick google search turned up this article
http://www.c-sharpcorner.com/uploadfile/yusufkaratoprak/difference-between-loose-coupling-and-tight-coupling/
Using passing object reference as a parameter in method you can achieve your desire output. Here is an example:
class Program
{
static void Main(string[] args)
{
Board d=new Board();
Square s=new Square();
s.m1(d);
}
}
class Board
{
int x=10;
}
class Square
{
public void m1(Board a)
{
Console.WriteLine(a.x);
}
Console.ReadLine();
}
I have a class called Players that holds various player attributes. I want to use a loop to initialize a list of Players based on certain user input. I will then use the list to play a card game with each of the players. I guess the List needs to be global in scope.
I can't figure out how to initialize the list since I can't seem to user a var
in the name field when trying to create a new Player.
Thanks
class Players
{
public string name;
public double bank;
public Hands playerHands; //A List of hands played
public Players ()
{
name = "Unknown";
bank = 0.0;
playerHands = null;
}
public Players(string name, double bank, Hands playerHands)
{
this.name = name;
this.bank = bank;
this.playerHands = playerHands;
}
}
class Program
{
private static int numOfPlayers;
private static int numOfDecks;
private static List<Cards> shoe;
public static void Main()
{
Console.OutputEncoding = Encoding.UTF8; //required to display special characters
Hands playerHands = new Hands();
Hands dealerHands = new Hands();
SetUpTable();
//Initilize Players
Players player = new Players("Ken", 100.00, playerHands);
Players dealer = new Players("Dealer", 0.0, dealerHands);
int dealerScore = 0, playerScore = 0;
//Deal initial cards
//The deal starts with the dealer who gets the first card face down
Cards dealerUpCard = null;
Hand dealerHand = new Hand();
Hand playerHand = new Hand();
dealer.playerHands.addHand(dealerHand);
player.playerHands.addHand(playerHand);
for (int iii = 1; iii < 3; iii++)
{
//Deal dealer's hand
dealerHand.addCard(shoe[0]);
dealerScore += shoe[0].value;
if (iii == 2) { dealerUpCard = shoe[0]; }
shoe.RemoveAt(0);
//Deal Player's aHand
playerHand.addCard(shoe[0]);
playerScore += shoe[0].value;
shoe.RemoveAt(0);
}
//Print out the test hands
displayHand(dealer);
displayHand(player);
Console.Read();
}
static void displayHand(Players player)
{
//Print out the test hands
for (int i = 0; i < player.playerHands.hands.Count; i++)
{
Console.Write("{0}'s hand: ", player.name);
for (int j = 0; j < player.playerHands.hands[i].hand.Count; j++)
{
Console.Write(" {0}{1} ", player.playerHands.hands[i].hand[j].rank, (char)player.playerHands.hands[i].hand[j].suit);
}
Console.WriteLine();
}
}
static void SetUpTable()
{
//Create players
numOfPlayers = validateUserInput("How many players (1-6)?",1,6);
for (int i = 0; i<numOfPlayers; i++)
{ //get player elements
//initiliz a new unique player in the Players list
//ie: Players player = new Players("Ken", 100.00, playerHands);
}
//Create shoe of cards
numOfDecks = validateUserInput("How many decks of cards (1-8)?", 1, 8);
shoe = Deck.createDeck(numOfDecks);
Deck.shuffleDeck(shoe, numOfDecks);
}
}
public List<Players> ListOfPlayers=new List<Players>();
static void SetUpTable()
{
//Create players
numOfPlayers = 6;
for (int i = 0; i<numOfPlayers; i++)
{
ListOfPlayers.Add(new Players());
//or with initial values with ctor:
ListOfPlayers.Add(new Players("Ken", 100.00, playerHands));
//or
ListOfPlayers.Add(new Players(){name="Ken", bank=100.00, playerHands=_playerHands});
//ie: Players player = new Players("Ken", 100.00, playerHands);
}
}
I am working on an assignment for school (Assignment Here).
I am currently trying to shuffle a deck of cards. I have used PlayingCards from Codeplex (sorry, could only have two links...) to create a collection of cards to create a deck. Please help, when I click the Shuffle button, nothing happens. You can see my progress here it's easier to see the entire code: Github
public void Shuffle()
{
PlayingCards.Deck theDeck = new PlayingCards.Deck();
random = new Random();
for (int i = 0; i < theDeck.Cards.Count; i++)
{
int second = random.Next(NUMBER_OF_CARDS);
PlayingCards.Card temp = theDeck.Cards[i];
theDeck.Cards[i] = theDeck.Cards[second];
theDeck.Cards[second] = temp;
}
}
You are creating a new instance of PlayingCards.Deck, shuffling it, and then throwing it away at the end of the shuffle.
PlayingCards.Deck theDeck = new PlayingCards.Deck();
You need to change the call to Shuffle to include PlayingCards.Deck as a parameter, so you should be doing this:
public void Shuffle(PlayingCards.Deck theDeck)
{
random = new Random();
for (int i = 0; i < theDeck.Cards.Count; i++)
{
int second = random.Next(NUMBER_OF_CARDS);
PlayingCards.Card
temp = theDeck.Cards[i];
theDeck.Cards[i] = theDeck.Cards[second];
theDeck.Cards[second] = temp;
}
}
You should also move the new Random() outside of this method as you may find that if you tried to create two shuffled decks immediately after one another that they'll have the same order because the seed Random uses is based on the system clock.
I had a look at the code you've got for adding the cards to the deck. You should use this code instead:
foreach (var face in Enum.GetValues(typeof(PlayingCards.CardSuits)).Cast<PlayingCards.CardSuits>())
{
foreach (var value in Enum.GetValues(typeof(PlayingCards.CardValues)).Cast<PlayingCards.CardValues>())
{
theDeck.Cards.Add(new PlayingCards.Card(face, value));
}
}
I have developed small program, which randomly generates several connections between the graphs (the value of the count could be randomly too, but for the test aim I have defined const value, it could be redefined in random value in any time).
Code is C#: http://ideone.com/FDCtT0
( result: Success time: 0.04s memory: 36968 kB returned value: 0 )
If you don't know, what is the adjacency matrix, go here : http://en.wikipedia.org/wiki/Adjacency_matrix
I think, that my version of code is rather not-optimized.
If I shall work with large matrixes, which have the size: 10k x 10k.
What are your suggestions, how is better to parallel calculations in
this task? Should I use some of the lockers-models like semaphore
etc for multi-threading calculations on large matrixes.
What are your suggestions for redesigning the architecture of
program. How should I prepare it for large matrixes?
As you see, upper at ideone, I have showed the time execution parameter and allocated memory in RAM. What is the asymptotic value of execution of my program? Is it O(n^2)?
So I want to listen to your advice how to increase the asymptotic mark, parallel calculations with using semaphores ( or maybe better locker-model for threads ).
Thank you!
PS:
SO doesn't allow to post topic without formatted code, so I'm posting in at the end (full program):
/*
Oleg Orlov, 2012(c), generating randomly adjacency matrix and graph connections
*/
using System;
using System.Collections.Generic;
class Graph
{
internal int id;
private int value;
internal Graph[] links;
public Graph(int inc_id, int inc_value)
{
this.id = inc_id;
this.value = inc_value;
links = new Graph[Program.random_generator.Next(0, 4)];
}
}
class Program
{
private const int graphs_count = 10;
private static List<Graph> list;
public static Random random_generator;
private static void Init()
{
random_generator = new Random();
list = new List<Graph>(graphs_count);
for (int i = 0; i < list.Capacity; i++)
{
list.Add(new Graph(i, random_generator.Next(100, 255) * i + random_generator.Next(0, 32)));
}
}
private static void InitGraphs()
{
for (int i = 0; i < list.Count; i++)
{
Graph graph = list[i] as Graph;
graph.links = new Graph[random_generator.Next(1, 4)];
for (int j = 0; j < graph.links.Length; j++)
{
graph.links[j] = list[random_generator.Next(0, 10)];
}
list[i] = graph;
}
}
private static bool[,] ParseAdjectiveMatrix()
{
bool[,] matrix = new bool[list.Count, list.Count];
foreach (Graph graph in list)
{
int[] links = new int[graph.links.Length];
for (int i = 0; i < links.Length; i++)
{
links[i] = graph.links[i].id;
matrix[graph.id, links[i]] = matrix[links[i], graph.id] = true;
}
}
return matrix;
}
private static void PrintMatrix(ref bool[,] matrix)
{
for (int i = 0; i < list.Count; i++)
{
Console.Write("{0} | [ ", i);
for (int j = 0; j < list.Count; j++)
{
Console.Write(" {0},", Convert.ToInt32(matrix[i, j]));
}
Console.Write(" ]\r\n");
}
Console.Write("{0}", new string(' ', 7));
for (int i = 0; i < list.Count; i++)
{
Console.Write("---");
}
Console.Write("\r\n{0}", new string(' ', 7));
for (int i = 0; i < list.Count; i++)
{
Console.Write("{0} ", i);
}
Console.Write("\r\n");
}
private static void PrintGraphs()
{
foreach (Graph graph in list)
{
Console.Write("\r\nGraph id: {0}. It references to the graphs: ", graph.id);
for (int i = 0; i < graph.links.Length; i++)
{
Console.Write(" {0}", graph.links[i].id);
}
}
}
[STAThread]
static void Main()
{
try
{
Init();
InitGraphs();
bool[,] matrix = ParseAdjectiveMatrix();
PrintMatrix(ref matrix);
PrintGraphs();
}
catch (Exception exc)
{
Console.WriteLine(exc.Message);
}
Console.Write("\r\n\r\nPress enter to exit this program...");
Console.ReadLine();
}
}
I will start from the end, if you don't mind. :)
3) Of course, it is O(n^2). As well as the memory usage.
2) Since sizeof(bool) == 1 byte, not bit, you can optimize memory usage by using bit masks instead of raw bool values, this will make it (8 bits per bool)^2 = 64 times less.
1) I don't know C# that well, but as i just googled i found out that C# primitive types are atomic, which means you can safely use them in multi-threading. Then, you are to make a super easy multi-threading task: just split your graphs by threads and press the 'run' button, which will run every thread with its part of graph on itself. They are independent so that's not going to be any problem, you don't need any semaphores, locks and so on.
The thing is that you won't be able to have an adjacency matrix with size 10^9 x 10^9. You just can't store it in the memory. But, there is an other way.
Create an adjacency list for each vertex, which will have a list of all vertices it is connected with. After building those lists from your graph, sort those lists for each vertex. Then, you can answer on the 'is a connected to b' in O( log(size of adjacency list for vertex a) ) time by using binary search, which is really fast for common usage.
Now, if you want to implement Dijkstra algorithm really fast, you won't need an adj. matrix at all, just those lists.
Again, it all depends on the future tasks and constraints. You cannot store the matrix of that size, that's all. You don't need it for Dijkstra or BFS, that's a fact. :) There is no conceptual difference from the graph's side: graph will be the same no matter what data structure it's stored in.
If you really want the matrix, then that's the solution:
We know, that number of connections (1 in matrix) is greatly smaller than its maximum which is n^2. By doing those lists, we simply store the positions of 1 (it's also called sparse matrix), which consumes no unneeded memory.