How to define and access list in a class - How to access a Player's hand in a Card Game

StackOverflow https://stackoverflow.com/questions/23449026

  •  14-07-2023
  •  | 
  •  

質問

I realise that this may have been asked before, but I've been looking and while I understand in theory what I need to do, the way to actually make it work is alluding me at the moment.

I'm trying to learn C# and Object Oriented Programming concepts by attempting a project. This particular project is to replicate the Top Trumps Card Game. My theme is going to be Game of Thrones.

My problem is that I'm stumped in regards to populating the Player 1 and computer Hands when I have initialised them. I can see the cards disappearing from the Deck but I cannot see them in the Player's hands (although when I do the breakpoint/pin to source. I can see the cardinHand populate.

The problem is that the game ends up with 60 cards in their hands (in total) instead of 15. ( I 30 rows in an XML that are loaded when the Deck is created). Can you check my code, give pointers to where I am going wrong. I know that I need to pass the card object around, I fear that I'm just missing something simple. I feel that this is the important part as I want to display the cards in the form based on the players hands.

This is the GameStart Method

public static void startGame()
    {
    Player player1 = new Player();
    Player computer = new Player();

    var newdeck = new Deck();
    newdeck.Shuffle();

    while (newdeck.CountCards() != 0)
    {
        newdeck.dealCards();
    }

    MessageBox.Show("New Game Started");

This is my Deck Class

public class Deck
{

private List<Card> deckofCards = new List<Card>();


//indexer on the deck
// Define the indexer, which will allow client code 
// to use [] notation on the class instance itself. 

public Card this[int i]
{
    get
    {
        // This indexer is very simple, and just returns or sets 
        // the corresponding element from the internal array. 
        return deckofCards[i];
    }
}


public Deck()
{
    resetDeck();
}

public void resetDeck()
{

    XmlDocument xmldata = new XmlDocument();
    xmldata.Load(@"C:\GameofThronesXml.xml");
    XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmldata.NameTable);

    XmlNodeList nodeList;
    XmlElement root = xmldata.DocumentElement;
    nodeList = xmldata.SelectNodes("//CharacterData/record", nsmgr);

    foreach (XmlElement data in nodeList)
    {
        Card singlecard = new Card();
        singlecard.CardID = int.Parse(data.SelectSingleNode("./CardID").InnerText);
        singlecard.Name = data.SelectSingleNode("./Name").InnerText;
        singlecard.Intelligence = int.Parse(data.SelectSingleNode("./Intelligence").InnerText);
        singlecard.Ruthlessness = int.Parse(data.SelectSingleNode("./Ruthlessness").InnerText);
        singlecard.Status = data.SelectSingleNode("./Status").InnerText;
        singlecard.Prestige = int.Parse(data.SelectSingleNode("./Prestige").InnerText);
        singlecard.FightingSkill = int.Parse(data.SelectSingleNode("./FightingSkill").InnerText);
        singlecard.AppearedIn = int.Parse(data.SelectSingleNode("./AppearedIn").InnerText);
        singlecard.Description = data.SelectSingleNode("./Description").InnerText;
        deckofCards.Add(singlecard);
    }

    //string path = @"C:\GameofThronesXml.xml";
    //XElement doc = XElement.Load(path);
    //deckofCards = (from items in doc.Descendants("CharacterData")
    //                select new Card(
    //                        int.Parse(items.Element("CardID").Value),
    //                        items.Element("Picture").Value,
    //                        items.Element("Name").Value,
    //                        int.Parse(items.Element("Intelligence").Value),
    //                        int.Parse(items.Element("Ruthlessness").Value),
    //                        items.Element("Status").Value,
    //                        int.Parse(items.Element("Prestige").Value),
    //                        int.Parse(items.Element("FightingSkill").Value),
    //                        int.Parse(items.Element("AppearedIn").Value),
    //                        items.Element("Description").Value)).ToList();
}

public void Shuffle()
{

    deckofCards = deckofCards.OrderBy(c => Guid.NewGuid())
                 .ToList();

}

public int CountCards()
{

    int number = deckofCards.Count();
    return number;

}

public Card dealCards()
{

    Hand hand = Player.hand;
    //Hand computerHand = Player.hand;

    if (this.deckofCards.Count == 0)
        throw new InvalidOperationException("There are no cards to deal.");

    Card card = deckofCards[0];

    hand.cardsinHand.Add(card);
    deckofCards.RemoveAt(0);
    return card;

 }
}

Hand Class

public class Hand
  {

    /// <summary>
    /// The deck in the hand
    /// </summary>
    public List<Card> cardsinHand = new List<Card>();

    public int GetNumberofCards()
    {
        int count = cardsinHand.Count;
        return count;
    }

    public void AddCard(Card card)
    {
        cardsinHand.Add(card);
    }



}

Player Class

public class Player
{

    public static Hand hand = new Hand();


}

tl;dr - Want to have two players of Player Class where I can access the number of dealt cards in this case, 15 cards each - I know it has something to do with hand.cardsinhand.Count - I just can't access it with the defined player classes.

Solution -

        Player Player1 = new Player();
        Player Computer = new Player();

        Deck newdeck = new Deck();
        Hand CompHand = new Hand();
        Hand PlyrHand = new Hand();

        newdeck.Shuffle();

        while (newdeck.CountCards() != 0)
        {
            //The Hand adds the return dealt cards to the respective lists.
            CompHand.AddCard(newdeck.dealCards());
            PlyrHand.AddCard(newdeck.dealCards());
        }

        MessageBox.Show("New Game Started");

        //Snoopy Dance - Each card has 15 cards in each hand.
        MessageBox.Show(CompHand.cardsinHand.Count().ToString());
        MessageBox.Show(PlyrHand.cardsinHand.Count().ToString());
役に立ちましたか?

解決

This code in startGame keeps dealing until there are no cards left:

while (newdeck.CountCards() != 0)
{
    newdeck.dealCards();
}

But dealCards is accessing the static (i.e. shared by all instances of the class) Player.hand, so all the cards get added to that. (I guess you were getting 60 when you were adding each card for both players, and that you're only getting 30 when one of the players is commented out, as in the question.)

You don't want all players to share the same hand, so change Player.Hand to not be static (i.e. remove the static keyword). Then pass your two initialised players' hands (player1.hand and computer.hand) as parameters into dealCards:

public Card dealCards(Hand hand, Hand computerHand)
...

I think there's some tidying up to do with regard to which classes have responsibility for doing what (maybe post to codereview.stackexchange.com once you've got the game working), but this change should get you up and running.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top