Class Libraries / Classes & Focusing on OOP

This was actually a challenge lesson from a course I’ve been taking. The lesson instructor actually gave us some program requirements. The challenge was a dart game of 300. I had to create a re-usable class library for the Darts class that has to be used by the 300 game. The idea was that this class could be used no matter what type of dart game was being played. Be it a game of 300, high score game, etc… Each game could refer to this class library for the basic methods, properties etc.., to function. This game was really simple in  nature. Each player has 3 chances, or darts to throw each round. The first player to get 300 or more wins the game. Sounds simple huh? It was actually  more involved the more I got into programming this along with following the requirements. I won’t list ALL of the requirements as you can guess they got pretty involved. Things like what the score was if the dart hit the inner bulls-eye or outer bulls-eye, if the darts lands in the inner or outer bands, calculating and updating the score, displaying the results, etc… And trying to keep my methods within 6-10 lines of code. Whew!!!! Again if you want to download the source-code you can via the download page. I’ve included comments in the code to try and explain what I’m doing the best that I can. It will probably help some of the gaps because I’ll no doubt leave holes in my descriptions below. And if you have any questions leave a comment below. I will probably come back to this program later and add more classes to the class library based on different types of games. maybe, so stay tuned.

DartsGameSS

Looking at the screenshot and the HTML code the webform is basically some labels and a button the user can click on. Simple, easy, and to the point.

Default.aspx HTML Code File Contents

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ChallengeSimpleDarts.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

        <asp:Button ID="okButton" runat="server" OnClick="okButton_Click" Text="Ok" />
        <br />
        <br />
        <asp:Label ID="playerOneResultLabel" runat="server"></asp:Label>
        <br />
        <asp:Label ID="playerTwoResultLabel" runat="server"></asp:Label>
        <br />
        <asp:Label ID="winnerResultLabel" runat="server"></asp:Label>
        <br />
        <br />
        <asp:Label ID="testResultLabel" runat="server"></asp:Label>

    </div>
    </form>
</body>
</html>

Default.aspx Code File Contents

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DartsClassLibrary;

namespace ChallengeSimpleDarts
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Setting the initial look of the result labels.
            playerOneResultLabel.Text = "Player 1 Name / Score: ";
            playerTwoResultLabel.Text = "Player 2 Name / Score: ";
            winnerResultLabel.Text = "Winner: ";
        }

        protected void okButton_Click(object sender, EventArgs e)
        {
            // Creating the objects needed to start a game of 300.
            Random random = new Random();

            string playerOne = "Daniel";
            string playerTwo = "Daryl";
            ThreeHundredGame threeHundredTwoPlayer = new ThreeHundredGame(playerOne, playerTwo, random);

            // Starting a two player game of 300.
            threeHundredTwoPlayer.PlayTwoPlayer();

            // Displaying the player info and game winner.
            DisplayResult displayResult = new DisplayResult(threeHundredTwoPlayer);
            playerOneResultLabel.Text += String.Format("{0} / {1}",
                displayResult.DisplayPlayerName(playerOne), displayResult.DisplayPlayerScore(playerOne));
            playerTwoResultLabel.Text += String.Format("{0} / {1}",
                displayResult.DisplayPlayerName(playerTwo), displayResult.DisplayPlayerScore(playerTwo));
            winnerResultLabel.Text += String.Format("{0}", displayResult.DisplayGameWinner());
        }
    }
}

Again like the previous post I wanted to keep this file as small as possible. Basically instantiating my objects, defining their properties, and calling on the other classes and methods to do the work. I am using the Page_Load method to set my labels so I can change them later. Here I will set my random object, player names, use them as parameters for the ThreeHundredGame class and call a public method in that class to start things off.

ThreeHundredGame.aspx Code File Contents

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DartsClassLibrary;

namespace ChallengeSimpleDarts
{
    // Class that handled a game of darts to 300.
    public class ThreeHundredGame
    {
        // Private properties
        //
        private Game _playerOne;
        private Game _playerTwo;
        private Random _random;

        // Public Properties
        //
        public string GameWinner { get; private set; }

        // Constructors
        //
        // Constructor for a two player game.
        public ThreeHundredGame(string playerOne, string playerTwo, Random random)
        {
            this._random = random;

            this._playerOne = new Game(playerOne, _random);
            this._playerTwo = new Game(playerTwo, _random);
        }

        // Public methods.
        //
        // Method that starts the two player game.
        public void PlayTwoPlayer()
        {
            // Playing the first to 300 game.
            while(_playerOne.PlayerScore < 300 && _playerTwo.PlayerScore < 300)
            {
                _playerOne.ThrowDarts();
                _playerTwo.ThrowDarts();
            }
        }

        // Method that returns the players score.
        public int GetPlayerScore(string playerName)
        {
            if (_playerOne.PlayerName == playerName)
                return _playerOne.PlayerScore;
            else if (_playerTwo.PlayerName == playerName)
                return _playerTwo.PlayerScore;
            else
                return 0;
        }

        // Method that returns the players name.
        public string GetPlayerName(string playerName)
        {
            if (_playerOne.PlayerName == playerName)
                return _playerOne.PlayerName;
            else if (_playerTwo.PlayerName == playerName)
                return _playerTwo.PlayerName;
            else
                return "";
        }

        // Method used to see who the winner of the two player game is.
        public string GetTwoPlayerWinner()
        {
            if (_playerOne.PlayerScore > _playerTwo.PlayerScore)
                return _playerOne.PlayerName;
            else
                return _playerTwo.PlayerName;
        }
    }
}

I’ve only defined a two player game to be played from here. Granted it wouldn’t be hard to incorporate more players if I wanted to. I wouldn’t have to modify much since I try and keep my methods specific to their desired functions. I’m also making the use of limiting my properties to being read only and using constructors and private methods to set the properties where needed. You will see that the constructor is setting the properties for each player to new game instances along with a random propery / instance. I’ll explain in the next section for the Game class.

Game.aspx Code File Contents

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DartsClassLibrary;

namespace ChallengeSimpleDarts
{
    public class Game
    {
        // Private properties
        //
        private Player _player;
        private Random _random;

        // Public properties
        //
        public int PlayerScore { get; private set; }
        public string PlayerName { get; private set; }

        // Constructors
        //
        public Game(string playerName, Random random)
        {
            // Creating and setting the private objects.
            _player = new Player();
            _player.Name = playerName;
            PlayerName = _player.Name;

            _random = random;
        }

        // Private methods
        //
        private void determineMultiplier(Darts darts)
        {
            /*
            Each dart can score from 1 to 20, or the bullseye.
            If the dart lands in the outer band, multiply the dart's score by two.
            If the dart lands in the inner band, multiply the dart's score by three.
            If the dart lands in the outer bullseye, it is scored as 25.
            If the dart lands in the inner bullseye, it is scored as 50.
             */

            // Checking to see if there's a multiplier amount. If not add the score to the players
            // score amount.
            if (darts.IsInnerBullseye)
                PlayerScore += darts.Score * 50;
            else if (darts.IsOuterBullseye)
                PlayerScore += darts.Score * 25;
            else if (darts.IsTriple)
                PlayerScore += darts.Score * 3;
            else if (darts.IsDouble)
                PlayerScore += darts.Score * 2;
            else
                PlayerScore += darts.Score;
        }

        // Public methods.
        //
        public void ThrowDarts()
        {
            //Random random = new Random();
            Darts dartsGame = new Darts(_random);

            // Loop to represent the 3 darts each player gets.
            for (int i = 0; i < 3; i++)
            {
                dartsGame.Throw();
                determineMultiplier(dartsGame);
            }
        }
    }
}

The Game class has two main properties that are set with a constuctor. A Player property, which is also a class that I’ll explain later, and the Random class. There are two public read-only properties for the player name and the player score. Methods include a public Throw method which takes care of creating a Darts class object from the class library and looping three times to simulate the three darts each player gets for each round of play. Inside the loop a method is called in the Darts class that takes care of setting some bool properties for the various values the dart lands on based on random numbers from the Random class. Again I’ll explain when I get to that classes code listing. Once the multipliers have been set a private determineMultiplier method is called to do exactly that, determine the mutiplier amount based on where the dart landed.

Player.aspx Code File Contents

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ChallengeSimpleDarts
{
    public class Player
    {
        // Public properties
        //
        public string Name { get; set; }    // Property for the players name.
        public int Score { get; set; }      // Property for the players score.
    }
}

This is a really simple class that holds the player properties of the name and score. I didn’t see a need for anything fancy here but just public full-access properties.

Darts.aspx Code File Contents (Part Of The Class Library)

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

// Class library that controls the darts and the score represented by where the darts hit.
namespace DartsClassLibrary
{
    public class Darts
    {
        // Private Properties
        //
        private Random _random;

        //Public Properties
        //
        public int Score { get; private set; }              // Holding the score amount. 1-20 based on a dartboard.
        public bool IsDouble { get; private set; }          // Check to see if the double ring was hit. 15% chance.
        public bool IsTriple { get; private set; }          // Check to see if the triple ring was hit. 10% chance
        public bool IsOuterBullseye { get; private set; }   // Check to see if the outer bullseye was hit. 5% chance.
        public bool IsInnerBullseye { get; private set; }   // Check to see if the inner bullseye was hit. 3% chance.

        // Constructors
        //
        public Darts(Random random)
        {
            _random = random;
        }

        // Private methods.
        //
        // Method used to reset the state of the bool variables from the previous throw.
        private void resetState()
        {
            IsDouble = false;
            IsTriple = false;
            IsOuterBullseye = false;
            IsInnerBullseye = false;
        }

        // Public methods
        //
        // Throw method used to determine where the dart has landed on the dartboard.
        public void Throw()
        {
            // Checking to see if any of the bool variables need to be reset for the dart throws.
            if (IsDouble || IsTriple || IsOuterBullseye || IsInnerBullseye)
                resetState();

            // Getting a random number from 1 to 20.
            Score = _random.Next(0, 21);

            // Getting the 1 - 100 percentage amount.
            int multiplier = _random.Next(1, 101);

            // Checking the percentage amount and setting the ring and bullseye variables.
            if (multiplier >= 97) IsInnerBullseye = true;           // Inner bullseye check.
            else if (multiplier >= 95) IsOuterBullseye = true;      // Outer bullseye check.
            else if (multiplier >= 90) IsTriple = true;             // Triple ring check.
            else if (multiplier >= 85) IsDouble = true;             // Double ring check.
        }
    }
}

OK now onto the Darts class. Like I explained earlier. The idea I had here was to make this a class library because no matter what kind of dart game you play it will always come back and reference this class. Makes it so you can type less code and re-use what you’ve already done. You can see there are some public read-only properties of the int and bool data types. The only thing the constructor does is initialize the random property from the Random parameter passed in from the ThrowDarts method in the Game class. I did have to add a private method to reset the data types state if the webpage wasn’t refreshed. Otherwise the class objects were still resident with the previous values thus messing up the game. The Throw method is something I modified from the original requirements because they seemed stale in my opinions. I wanted to use more of a random state when the darts were being thrown.

DisplayResult.aspx Code File Contents

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

namespace ChallengeSimpleDarts
{
    public class DisplayResult
    {
        // Private properties.
        //
        private ThreeHundredGame _threeHundredGame;

        // Constructors
        //
        public DisplayResult(ThreeHundredGame threeHundredGame)
        {
            this._threeHundredGame = threeHundredGame;
        }

        // Public methods
        // Method used to get the players name.
        public string DisplayPlayerName(string playerName)
        {
            string result = _threeHundredGame.GetPlayerName(playerName);
            return result;
        }

        // Method used to get the players score.
        public string DisplayPlayerScore(string playerName)
        {
            string result = _threeHundredGame.GetPlayerScore(playerName).ToString();
            return result;
        }

        // Method used to get the three hundred game winner.
        public string DisplayGameWinner()
        {
            string result = _threeHundredGame.GetTwoPlayerWinner();
            return result;
        }
    }
}

The DisplayResult class is like something you’ve probably seen me do before. I’m a fan of having a class with methods that takes care of my string maniplation before displaying it on the screen to the user. For right now the only property this class that’s set by the constructor is the ThreeHundredGame object that can be passed in. If more games are to be added this class will have to be modified a little. So for the sake of this assignments sake I coded this up rather quickly because I was running out of time. Again, if I make changed to the program or add more game types I’ll have to refactor this class some.

Advertisements

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s