async public Task <Deck> CreateNewShuffledDeckAsync(int deckCount) { var random = new Random(); var suits = new[] { "HEARTS", "SPADES", "CLUBS", "DIAMONDS" }; var values = new[] { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "JACK", "QUEEN", "KING" }; var cards = new Card[52 * deckCount]; var deck = new Deck { DeckId = random.Next().ToString("X") }; int newCardIndex = 0; for (int _ = 0; _ < deckCount; _ += 1) { foreach (string suit in suits) { foreach (string value in values) { string code = value.Substring(0, 1) + suit.Substring(0, 1); if (value == "10") { code = "0" + suit.Substring(0, 1); } cards[newCardIndex] = new Card { Deck = deck, Value = value, Suit = suit, Code = code, }; newCardIndex += 1; } } } // Fisher-Yates shuffle for (int cardIndex = cards.Length - 1; cardIndex >= 0; cardIndex -= 1) { int swapIndex = random.Next(0, cardIndex); Card card = cards[swapIndex]; cards[swapIndex] = cards[cardIndex]; cards[cardIndex] = card; cards[cardIndex].Order = cardIndex; cards[swapIndex].Order = swapIndex; } foreach (Card card in cards) { deck.Cards.Add(card); } using (var context = new DeckContext()) { context.Decks.Add(deck); await context.SaveChangesAsync(); } return(deck); }
/// <summary> /// Shuffles the cards of a pile in a given deck. /// </summary> /// <param name="deckId">The ID of the deck.</param> /// <param name="pileName">The name of the pile.</param> /// <returns>True if the shuffle was successful; false otherwise.</returns> public async Task <bool> ShufflePileAsync(string deckId, string pileName) { using (var context = new DeckContext()) { var deck = await context.Decks .Include(d => d.Cards) .Include(d => d.Piles) .SingleAsync(d => d.DeckId == deckId); var piles = deck.Piles; var pile = piles.Single(p => p.Name == pileName); var cards = pile.Cards.ToList(); try { Shuffle(cards); pile.Cards = cards; await context.SaveChangesAsync(); return(true); } catch { return(false); } } }
async public Task <Deck> DrawCardsAsync(string deckId, int numberToDraw) { using (var context = new DeckContext()) { Deck deck = await context.Decks .Include(x => x.Cards) .SingleAsync(x => x.DeckId == deckId); foreach (Card card in deck.Cards) { if (!card.Drawn) { card.Drawn = true; numberToDraw -= 1; } if (numberToDraw == 0) { break; } } await context.SaveChangesAsync(); return(deck); } }
/// <summary> /// Returns a deck with the given ID. /// </summary> /// <param name="deckId">The ID of the deck.</param> /// <returns>The deck.</returns> public async Task <Deck> GetDeckAsync(string deckId) { using (var context = new DeckContext()) { return(await context.Decks .Include(d => d.Cards) .Include(d => d.Piles) .SingleAsync(d => d.DeckId == deckId)); } }
/// <summary> /// Puts a collection of cards of a given deck in a pile. /// </summary> /// <param name="deckId">The ID of the deck.</param> /// <param name="pileName">The name of the pile.</param> /// <param name="cardCodes">The codes of the cards to put in the pile.</param> /// <returns>The updated deck.</returns> public async Task <Deck> AddToPileAsync(string deckId, string pileName, string[] cardCodes) { using (var context = new DeckContext()) { var deck = await context.Decks .Include(d => d.Cards) .Include(d => d.Piles) .SingleAsync(d => d.DeckId == deckId); // TODO Confirm that cards to add are all drawn // I'm not sure how to best format these LINQ statements if (!deck.Piles .Select(p => p.Name) .Contains(pileName)) { deck.Piles.Add(new Pile() { Name = pileName, DeckId = deck.Id }); } // I don't know if I can just modify the pileIds of each card without // modifying all the piles in the deck. // // This will also break when a deck has multiple copies of the same card // (e.g. when the CreateNewShuffledDeckAsync method is passed an int > 1) // because I'm filtering by card code instead of card id. // // Perhaps this can be fixed if we require a "source" field in the request. var cards = deck.Cards .Where(c => cardCodes.Contains(c.Code)) .ToList(); cards.ForEach(c => { if (c.PileId.HasValue) { deck.Piles .Single(p => p.Id == c.PileId.Value) .Cards .Remove(c); } }); var pile = deck.Piles.Single(p => p.Name == pileName); pile.Cards = pile.Cards.Concat(cards).ToList(); await context.SaveChangesAsync(); return(deck); } }
async public Task <Deck> GetDeck(string deckId) { using (var context = new DeckContext()) { Deck deck = await context.Decks .Include(x => x.Cards) .Include(x => x.Piles) .SingleAsync(x => x.DeckId == deckId); return(deck); } }
async public Task <Deck> PutCardsInPile(string deckId, string pileName, List <string> cardCodes) { using (var context = new DeckContext()) { Deck deck = await context.Decks .Include(x => x.Cards) .Include(x => x.Piles) .SingleAsync(x => x.DeckId == deckId); Pile pile = null; foreach (Pile p in deck.Piles) { if (p.Name == pileName) { pile = p; } } if (pile == null) { //create new pile pile = new Pile() { Name = pileName, DeckId = deck.Id, Deck = deck }; context.Piles.Add(pile); context.SaveChanges(); pile = context.Piles .Include(p => p.Cards) .First(p => p.DeckId == deck.Id && p.Name == pileName); } foreach (Card card in deck.Cards) { foreach (string cardCode in cardCodes) { if (card.Code == cardCode) { card.PileId = pile.Id; } } } await context.SaveChangesAsync(); return(deck); } }
async public Task <Pile> AddCardToPileAsync(string deckId, string pileName, string cards) { string[] cardArr = cards.Split(','); using (var context = new DeckContext()) { Deck deck = await context.Decks .Include(x => x.Cards) .SingleAsync(x => x.DeckId.Equals(deckId)); Deck deckPiles = await context.Decks .Include(x => x.Piles) .SingleAsync(x => x.DeckId.Equals(deckId)); //Couldn't figure out how to do multiple includes so I made two Pile pile; try { pile = deckPiles.Piles.Single(x => x.Name.Equals(pileName) && x.DeckId == deckPiles.Id); } catch (Exception) { pile = new Pile(); pile.Deck = deckPiles; pile.DeckId = deckPiles.Id; pile.Name = pileName; pile.Cards = new List <Card>(); deckPiles.Piles.Add(pile); } foreach (var card in cardArr) { Card Card = deck.Cards.Single(x => x.Code.Equals(card)); Card.Drawn = true; // we took it out so it's out of the deck if (pile.Cards.Contains(Card)) { continue; //small check so we won't put multiple instances of the same card in the pile } pile.Cards.Add(Card); Card.Pile = pile; } await context.SaveChangesAsync(); return(pile); } }
/// <summary> /// Draws a number of cards from a given deck. /// </summary> /// <param name="deckId">The ID of the deck.</param> /// <param name="numCards">The number of cards to draw.</param> /// <returns>The updated deck.</returns> public async Task <Deck> DrawCardsAsync(string deckId, int numCards) { using (var context = new DeckContext()) { var deck = await context.Decks .Include(d => d.Cards) .SingleAsync(d => d.DeckId == deckId); // TODO handle the case when there are not enough cards to draw var notDrawn = deck.Cards .Where(c => !c.Drawn) .Take(numCards) .ToList(); notDrawn.ForEach(c => c.Drawn = !c.Drawn); await context.SaveChangesAsync(); return(deck); } }
async public Task <Pile> PileShuffleAsync(string deckId, string pileName) { using (var context = new DeckContext()) { Pile pile = await context.Piles .Include(x => x.Cards) .SingleAsync(x => x.Name.Equals(pileName)); //no try catch this time because if you try to shuffle a pile that doesn't exist you deserve to have the API scream at you /*Pile pile = deckPiles.Piles.Single(x => x.Name.Equals(pileName) && x.DeckId == deckPiles.Id);*/ var rnd = new Random(); var shuffledPile = pile.Cards.OrderBy(x => rnd.Next()).ToList(); pile.Cards = shuffledPile; await context.SaveChangesAsync(); return(pile); } }