Skip to content

Commit

Permalink
Generalised CardDeck by using 'string' as the underlying data type of…
Browse files Browse the repository at this point in the history
… a card type and sub type which will allow users to control what cards their game gave.
  • Loading branch information
12Acorns committed Aug 4, 2024
1 parent 8fc2087 commit 463c4d0
Show file tree
Hide file tree
Showing 21 changed files with 478 additions and 432 deletions.
8 changes: 3 additions & 5 deletions CardDeck/Deck/Card/CardData.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
using Deck.Extensions;

namespace Deck.Deck.Card;
namespace Deck.Deck.Card;

public readonly struct CardData
{
public CardData(CardSubType _subType)
public CardData(CardSubType _subType, Func<CardSubType, byte> _scoreMapping)
{
SubType = _subType;
Score = SubType.MapToScore();
Score = _scoreMapping(_subType);
}

/// <summary>
Expand Down
7 changes: 4 additions & 3 deletions CardDeck/Deck/Card/CardDescription.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Deck.Deck.Card.Colour;
using System.Collections.Frozen;
using Deck.Deck.Card.Colour;

namespace Deck.Deck.Card;

Expand All @@ -9,13 +10,13 @@ public CardDescription(CardType _type, IColour _colour, IColourSet _colourSet, D
Type = _type;
Colour = _colour;
ColourSet = _colourSet;
CardCountMapping = _cardCountMapping.AsReadOnly();
CardCountMapping = _cardCountMapping.ToFrozenDictionary();
TotalCount = CardCountMapping.Values.Sum(x => x);
}

public CardType Type { get; }
public IColour Colour { get; set; }
public IColourSet ColourSet { get; }
public IReadOnlyDictionary<CardSubType, byte> CardCountMapping { get; }
public FrozenDictionary<CardSubType, byte> CardCountMapping { get; }
public int TotalCount { get; }
}
57 changes: 37 additions & 20 deletions CardDeck/Deck/Card/CardSubType.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,42 @@
namespace Deck.Deck.Card;
using System.Diagnostics.CodeAnalysis;

public enum CardSubType : byte
namespace Deck.Deck.Card;

public readonly struct CardSubType
{
// Numeric
Zero,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
public CardSubType(string _name)
{
SubTypeName = _name;
hash = SubTypeName.GetHashCode();
}

public string SubTypeName { get; }

private readonly int hash;

// Special
PlusTwo,
Skip,
Reverse,
public override int GetHashCode()
{
return hash;
}

// Wild (Special
Wild,
WildPlusFour,
public static bool operator ==(CardSubType _this, CardSubType _other)
{
return _this.SubTypeName == _other.SubTypeName;
}
public static bool operator !=(CardSubType _this, CardSubType _other)
{
return !(_this == _other);
}
public override bool Equals([NotNullWhen(true)] object? obj)
{
if(obj == null)
{
return false;
}
if(obj is not CardSubType _subType)
{
return false;
}
return _subType == this;
}
}
56 changes: 52 additions & 4 deletions CardDeck/Deck/Card/CardType.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,55 @@
namespace Deck.Deck.Card;
using System.Collections.Frozen;
using System.Diagnostics.CodeAnalysis;

public enum CardType : byte
namespace Deck.Deck.Card;

public readonly struct CardType
{
Numeric,
Special
public CardType(string _name, FrozenSet<CardSubType> _typeMembers)
{
TypeName = _name;
TypeMembers = _typeMembers;
var _hash = new HashCode();
_hash.Add(TypeName);

for(int i = 0; i < TypeMembers.Count; i++)
{
_hash.Add(TypeMembers.ElementAt(i));
}

hash = _hash.ToHashCode();
}
public CardType(string _name, HashSet<CardSubType> _typeMembers) : this(_name, _typeMembers.ToFrozenSet()) { }
public CardType(string _name, CardSubType[] _typeMembers) : this(_name, _typeMembers.ToFrozenSet()) { }

public string TypeName { get; }
public FrozenSet<CardSubType> TypeMembers { get; }

private readonly int hash;

public override int GetHashCode()
{
return hash;
}

public static bool operator ==(CardType _this, CardType _other)
{
return _this.hash == _other.hash;
}
public static bool operator !=(CardType _this, CardType _other)
{
return !(_this.hash == _other.hash);
}
public override bool Equals([NotNullWhen(true)] object? _obj)
{
if(_obj == null)
{
return false;
}
if(_obj is not CardType _cardType)
{
return false;
}
return _cardType == this;
}
}
16 changes: 2 additions & 14 deletions CardDeck/Deck/Card/GameCard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,9 @@ public GameCard(CardDescription _description, CardData _data)
Description = _description;
Data = _data;

if(Description.Type is CardType.Numeric &&
_data.SubType is not (CardSubType.Zero or CardSubType.One
or CardSubType.Two or CardSubType.Three
or CardSubType.Four or CardSubType.Five
or CardSubType.Six or CardSubType.Seven
or CardSubType.Eight or CardSubType.Nine))
if(!_description.Type.TypeMembers.Contains(_data.SubType))
{
throw new ArgumentException("subType is not a valid numeric type");
}
if(_description.Type is CardType.Special &&
_data.SubType is not (CardSubType.Skip or CardSubType.Reverse
or CardSubType.PlusTwo or CardSubType.WildPlusFour
or CardSubType.Wild))
{
throw new ArgumentException("subType is not a valid special type");
throw new ArgumentException($"Member ({_data.SubType}) does not inherit from {_description.Type.TypeName}.");
}

hash = HashCode.Combine(Description.Colour, Data.SubType, Data.Score);
Expand Down
66 changes: 27 additions & 39 deletions CardDeck/Deck/CardDeckBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ namespace Deck.Deck;

public sealed class CardDeckBuilder
{
private IRandomizer shuffleOptions = RandomizerFactory.Get(RandomizerType.DefualtRandom);
private DeckOptions options = DeckOptions.Default;

public CardDeckBuilder WithCustomDeckOptions(DeckOptions _options)
public CardDeckBuilder(DeckOptions _options, Func<CardSubType, byte> _scoreMapping)
{
scoreMapping = _scoreMapping;
options = _options;
return this;
}

private readonly Func<CardSubType, byte> scoreMapping;
private readonly DeckOptions options;

private IRandomizer shuffleOptions = RandomizerFactory.Get(RandomizerType.DefualtRandom);

public CardDeckBuilder WithCustomShuffleOptions(IRandomizer _randomizer)
{
shuffleOptions = _randomizer;
Expand All @@ -31,48 +34,33 @@ private Span<GameCard> CreateCards()
{
var _cards = new GameCard[options.TotalCards].AsSpan();

var _specialCardOptions = options.SpecialDeckOptions;
var _numericCardOptions = options.NumericDeckOptions;

CreateSpecialCards(0, _specialCardOptions, _cards, out int _offset);
CreateNumericCards(_offset, _numericCardOptions, _cards, out _);
int _index = 0;
foreach(var _groupDescriptor in options.GroupOptions)
{
CreateCardsOfType(_cards, _index, _groupDescriptor, out _index);
}

return _cards;
}

private static void CreateNumericCards(int _initialIndex, DeckDescription _deckOptions,
Span<GameCard> _source, out int _endIndex)
{
CreateCardOfType(_source, _initialIndex, _deckOptions, CardSubType.Zero, out _endIndex);
CreateCardOfType(_source, _endIndex, _deckOptions, CardSubType.One, out _endIndex);
CreateCardOfType(_source, _endIndex, _deckOptions, CardSubType.Two, out _endIndex);
CreateCardOfType(_source, _endIndex, _deckOptions, CardSubType.Three, out _endIndex);
CreateCardOfType(_source, _endIndex, _deckOptions, CardSubType.Four, out _endIndex);
CreateCardOfType(_source, _endIndex, _deckOptions, CardSubType.Five, out _endIndex);
CreateCardOfType(_source, _endIndex, _deckOptions, CardSubType.Six, out _endIndex);
CreateCardOfType(_source, _endIndex, _deckOptions, CardSubType.Seven, out _endIndex);
CreateCardOfType(_source, _endIndex, _deckOptions, CardSubType.Eight, out _endIndex);
CreateCardOfType(_source, _endIndex, _deckOptions, CardSubType.Nine, out _endIndex);
}
private static void CreateSpecialCards(int _initialIndex, DeckDescription _description,
Span<GameCard> _source, out int _endIndex)
{
CreateCardOfType(_source, _initialIndex, _description, CardSubType.PlusTwo, out _endIndex);
CreateCardOfType(_source, _endIndex, _description, CardSubType.Skip, out _endIndex);
CreateCardOfType(_source, _endIndex, _description, CardSubType.Reverse, out _endIndex);
CreateCardOfType(_source, _endIndex, _description, CardSubType.Wild, out _endIndex);
CreateCardOfType(_source, _endIndex, _description, CardSubType.WildPlusFour, out _endIndex);
}
private static void CreateCardOfType(Span<GameCard> _source, int _initialIndex,
DeckDescription _deckDescription, CardSubType _type, out int _endIndex)
private void CreateCardsOfType(Span<GameCard> _source, int _initialIndex,
CardGroupDescription _deckDescription, out int _endIndex)
{
_endIndex = _initialIndex;


foreach(var _cardDescription in _deckDescription.CardDescriptions)
{
CreateCardType(_source, _endIndex, _cardDescription, _type, out _endIndex);
var _types = _cardDescription.CardCountMapping
.Where(x => x.Value > 0)
.Select(x => x.Key);

foreach(var _type in _types)
{
CreateCardType(_source, _endIndex, _cardDescription, _type, out _endIndex);
}
}
}
private static void CreateCardType(Span<GameCard> _source, int _offset, CardDescription _description,
private void CreateCardType(Span<GameCard> _source, int _offset, CardDescription _description,
CardSubType _subType, out int _endIndex)
{
_endIndex = _offset;
Expand All @@ -82,7 +70,7 @@ private static void CreateCardType(Span<GameCard> _source, int _offset, CardDesc
for(int j = 0; j < _count; j++, _endIndex++)
{
_source[_endIndex] =
new GameCard(_description, new CardData(_subType));
new GameCard(_description, new CardData(_subType, scoreMapping));
}
}
}
Loading

0 comments on commit 463c4d0

Please sign in to comment.