Counting Money Game – Generics & Collections

CoinsCd

CoinsMainForm

This is a coin counting game that demonstrates the use of generic collections. Instead using arrays or arraylists collections are a better fit in most cases. Plus I’m finding out that in my collections classes my add, remove, sort, etc.., algorithms don’t have to be as complicated. It’s making for some cleaner code. This combined with the knowledge of events, event handlers, delegates, and lambda expressions things are moving right along. When the game is started a random amount is selected. The players job is to use the amount buttons provided to match that amount. There are mouse button event handlers in place to remove the money from the screen by clicking on them. I’m trying to create more classes that do the work behind the scenes away from my MainForm code.


MainForm Class


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Coins
{
    public partial class MainForm : Form
    {
        private CoinGame _coinGame = new CoinGame();

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Shown(object sender, EventArgs e)
        {
            //Exit event lambda expression.
            exitButton.Click += (from, ea) => this.Close();

            //Reset button lambda expression.
            resetButton.Click += (from, ea) =>
                {
                    _coinGame.Reset();
                    moneyPictureBox.Invalidate();
                    CheckAmount();
                };

            // PictureBox Mouseup lambda expression
            addPennyButton.Click += (from, ea) => { _coinGame.Add(new Penny()); moneyPictureBox.Invalidate(); CheckAmount(); };
            addNickelButton.Click += (from, ea) => { _coinGame.Add(new Nickel()); moneyPictureBox.Invalidate(); CheckAmount(); };
            addDimeButton.Click += (from, ea) => { _coinGame.Add(new Dime()); moneyPictureBox.Invalidate(); CheckAmount(); };
            addQuarterButton.Click += (from, ea) => { _coinGame.Add(new Quarter()); moneyPictureBox.Invalidate(); CheckAmount(); };

            //Adding the lamda expression for the 3 cent button click event. DS
            addThreeCentButton.Click += (from, ea) => { _coinGame.Add(new ThreeCent()); moneyPictureBox.Invalidate(); CheckAmount(); };

            //Adding the lambda expression for the 1 dollar button click event. DS
            addOneDollarButton.Click += (from, ea) => { _coinGame.Add(new OneDollar()); moneyPictureBox.Invalidate(); CheckAmount(); };

            //Adding the lambda expression for the 5 dollar button click event. DS
            addFiveDollarsButton.Click += (from, ea) => { _coinGame.Add(new FiveDollar()); moneyPictureBox.Invalidate(); CheckAmount(); };

            //Setup a PictureBox Paint event.
            moneyPictureBox.Paint += (from, ea) =>
                {
                    _coinGame.Update(ea.Graphics, moneyPictureBox.ClientSize);
                    currentValueLabel.Text = _coinGame.TotalWorth.ToString();
                    targetValueLabel.Text = _coinGame.TargetAmount.ToString();
                    countPennyLabel.Text = _coinGame.CountPenny.ToString();
                    countNickelLabel.Text = _coinGame.CountNickel.ToString();
                    countDimeLabel.Text = _coinGame.CountDime.ToString();
                    countQuarterLabel.Text = _coinGame.CountQuarter.ToString();
                    countThreeCentLabel.Text = _coinGame.CountThreeCent.ToString();
                    countOneDollarLabel.Text = _coinGame.CountOneDollar.ToString();
                    countFiveDollarsLabel.Text = _coinGame.CountFiveDollar.ToString();
                };

            //PictureBox MouseUp lambda expression.
            moneyPictureBox.MouseUp += (from, ea) => { _coinGame.Remove(ea.Location); moneyPictureBox.Invalidate(); CheckAmount(); };
        }

        private void CheckAmount()
        {
            if (_coinGame.TotalWorth == 0)
                matchStatusLabel.Text = "";
            else if (_coinGame.TargetAmount == _coinGame.TotalWorth)
                matchStatusLabel.Text = "Matched!";
            else if (_coinGame.TotalWorth > _coinGame.TargetAmount)
                matchStatusLabel.Text = "Over!";
            else
                matchStatusLabel.Text = "Under...";
        }
    }
}


Counter Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Coins
{
    public class Counter where T : Money
    {
        //Private class variables.
        private List _counterList;

        //Private backing class variables.
        private decimal _totalWorth = 0.00m;

        //Accessors / Properties.
        public decimal TotalWorth { get { return _totalWorth; } }
        public int Count { get { return _counterList.Count; } }

        //Indexers.
        public T this[int index]
        {
            get
            {
                if (_counterList.Count > 0 && index < _counterList.Count)
                    return _counterList[index];
                else
                    return default(T);
            }
        }

        //Constructors.
        public Counter()
        {
            _counterList = new List();
        }

        //Public methods.
        public void Add(T t)
        {
            _counterList.Add(t);
            _totalWorth += t.Worth;
        }

        //Public enumerator.
        public IEnumerator GetEnumerator()
        {
            return _counterList.GetEnumerator();
        }

        public void Reset()
        {
            _counterList.Clear();
            _totalWorth = 0.00m;
        }

        public void Remove(T t)
        {
            T foundT = _counterList.Find(item => item == t);
            if (foundT != null)
            {
                _totalWorth -= foundT.Worth;
                _counterList.Remove(foundT);
            }
        }
    }
}


Money Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Coins
{
    public class Money
    {
        //Private backing class variables.
        private decimal _worth;
        private Point _location;
        private Size _dimensions;
        private string _text;
        private Color _color;

        //Accessors / Properties.
        public decimal Worth { get { return _worth; } }
        public Point Location { get { return _location; } set { _location = value; } }
        public Size Dimensions { get { return _dimensions; } set { _dimensions = value; } }
        public string Text { get { return _text; } set { _text = value; } }
        public Color Color { get { return _color; } set { _color = value; } }

        //Constructors.
        public Money(decimal worth, string text, Color color)
        {
            _worth = worth;
            _text = text;
            _color = color;
        }

        //Public methods.
        public bool Hit(Point location)
        {
            return new Rectangle(_location, _dimensions).Contains(location);
        }
    }

    public class Penny : Money
    {
        public Penny() : base(0.01m, "Penny", Color.Brown) { }
    }

    public class Nickel : Money
    {
        public Nickel() : base(0.05m, "Nickel", Color.Silver) { }
    }

    public class Dime : Money
    {
        public Dime() : base(0.10m, "Dime", Color.SlateGray) { }
    }

    public class Quarter : Money
    {
        public Quarter() : base(0.25m, "Quarter", Color.Gold) { }
    }
    
    //Adding the class for the 3 cent piece. DS
    public class ThreeCent : Money
    {
        public ThreeCent() : base(0.03m, "3 Cent", Color.SkyBlue) { }
    }

    //Adding the class for the 1 dollar piece. DS
    public class OneDollar : Money
    {
        public OneDollar() : base(1.00m, "1 Dollar", Color.Green) { }
    }

    //Adding the class for the 5 dollar piece. DS
    public class FiveDollar : Money
    {
        public FiveDollar() : base(5.00m, "5 Dollars", Color.LightGreen) { }
    }
}


CoinGame Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Coins
{
    public class CoinGame
    {
        //Private class variables.
        private Counter _myCounter = new Counter();
        private Counter _myPennies = new Counter();
        private Counter _myNickel = new Counter();
        private Counter _myDime = new Counter();
        private Counter _myQuarter = new Counter();
        private Counter _myThreeCent = new Counter();     //Adding a private collector for the 3 cent pieces. DS
        private Counter _myOneDollar = new Counter();     //Adding a private collector for the 1 dollar piece. DS
        private Counter _myFiveDollar = new Counter();  //Adding a private collector for the 5 dollar piece. DS
        private int _coinHeight = 20;
        private Random _random = new Random();

        //Private backing class variables.
        private decimal _targetAmount = 0.00m;

        //Properties / Accessors.
        public decimal TargetAmount
        {
            get { return _targetAmount; }
            set { _targetAmount = value; }
        }

        public decimal TotalWorth { get { return _myCounter.TotalWorth; } }
        public int CountPenny { get { return _myPennies.Count; } }
        public int CountNickel { get { return _myNickel.Count; } }
        public int CountDime { get { return _myDime.Count; } }
        public int CountQuarter { get { return _myQuarter.Count; } }
        public int CountThreeCent { get { return _myThreeCent.Count; } }    //Accessor for the 3 cent collection. DS
        public int CountOneDollar { get { return _myOneDollar.Count; } }    //Accessor for the 1 dollar collection. DS
        public int CountFiveDollar { get { return _myFiveDollar.Count; } }  //Accessor for the 5 dollar collection. DS

        //Constructors.
        public CoinGame()
        {
            SetTargetAmount();
        }

        //Public methods.
        public void Add(Money money)
        {
            _myCounter.Add(money);
            switch (money.GetType().Name)
            {
                case "Penny":
                    _myPennies.Add(money as Penny);
                    break;
                case "Nickel":
                    _myNickel.Add(money as Nickel);
                    break;
                case "Dime":
                    _myDime.Add(money as Dime);
                    break;
                case "Quarter":
                    _myQuarter.Add(money as Quarter);
                    break;
                case "ThreeCent":                              //Case to add a 3 cent piece to the collection. DS
                    _myThreeCent.Add(money as ThreeCent);
                    break;
                case "OneDollar":
                    _myOneDollar.Add(money as OneDollar);   //Case to add a 1 Dollar piece to the collection. DS
                    break;
                case "FiveDollar":
                    _myFiveDollar.Add(money as FiveDollar); //Case to add a 5 dollar piece to the collection. DS
                    break;
            }
        }

        public void Remove(Point location)
        {
            //Loop thru each coin to see which one was selected.
            foreach (Money money in _myCounter)
            {
                if (money.Hit(location))
                {
                    switch (money.GetType().Name)
                    {
                        case "Penny":
                            _myPennies.Remove(money as Penny);
                            break;
                        case "Nickel":
                            _myNickel.Remove(money as Nickel);
                            break;
                        case "Dime":
                            _myDime.Remove(money as Dime);
                            break;
                        case "Quarter":
                            _myQuarter.Remove(money as Quarter);
                            break;
                        case "3 Cent":                  //Case to remove a 3 cent piece from the collection. DS
                            _myThreeCent.Remove(money as ThreeCent);
                            break;
                        case "1 Dollar":
                            _myOneDollar.Remove(money as OneDollar);    //Case to remove 1 dollar piece from the collection. DS
                            break;
                        case "5 Dollar":
                            _myFiveDollar.Remove(money as FiveDollar);  //Case to remove 5 dollar piece from the collection. DS
                            break;
                    }
                    _myCounter.Remove(money);
                    break;
                }
            }
        }

        public void Update(Graphics graphics, Size boardSize)
        {
            //Note using for loop to allow updating money.
            for (int i = 0; i < _myCounter.Count; i++)
            {
                Money money = _myCounter[i];

                //Set the coin location.
                int startingY = boardSize.Height - (i * (_coinHeight + 1)) - _coinHeight - 1;
                money.Location = new Point(1, startingY);
                money.Dimensions = new Size(boardSize.Width - 2, _coinHeight);

                //Draw the coin.
                using (SolidBrush solidBrush = new SolidBrush(money.Color))
                    graphics.FillRectangle(solidBrush, new Rectangle(money.Location, money.Dimensions));

                //Draw Text.
                RectangleF boundingRectangle = new RectangleF(money.Location.X, money.Location.Y, money.Dimensions.Width, money.Dimensions.Height);
                using (Font font = new Font("Arial", 12, FontStyle.Bold))
                using (StringFormat stringFormat = new StringFormat())
                using (SolidBrush brush = new SolidBrush(Color.White))
                {
                    //Align the text horizontally and vertically.
                    stringFormat.Alignment = StringAlignment.Center;
                    stringFormat.LineAlignment = StringAlignment.Center;
                    graphics.DrawString(money.Text, font, brush, boundingRectangle, stringFormat);
                }
            }
        }

        public void Reset()
        {
            _myCounter.Reset();
            _myPennies.Reset();
            _myNickel.Reset();
            _myDime.Reset();
            _myQuarter.Reset();
            _myThreeCent.Reset();
            _myOneDollar.Reset();
            _myFiveDollar.Reset();
            SetTargetAmount();
        }

        //Private methods.
        private void SetTargetAmount()
        {
            _targetAmount = _random.Next(1, 1000) / 100.00m;
        }
    }
}

Advertisements

2 thoughts on “Counting Money Game – Generics & Collections

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s