Slot Machine Update v3.1

Here’s a revision on the Slot Machine entry I made back in December. If you remember the previous version of the program was a course challenge I did from Bob Tabor’s Learn Visual Studio.net page. Well I’m still going thru the videos on his site. Some of the code you see in this blog is either stuff I’ve taken from classes and improved on as I learn new things. This version of the slot machine is just that. In a nutshell what I’ve done is taken the game and broken it up into different functional classes and methods. I’ve also went from using arrays too collections. This was done after my lessons on collections and I took a liking to them a little more than arrays. I know arrays have their purposes in certain programs as do collections. I just found collections easier to work with for this project.

Oh, also as a note there will be a break in posts for a couple of weeks. I’ll be transitioning my development environment over to a new server. So once I get that up and running and the virtual machines migrated I’ll be back to work. 🙂

GameLayout ProgramStucture

 
Default.aspx HTML Code Contents

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="BasicSlotMachine.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:Image ID="slotOneImage" runat="server" CssClass="auto-style1" Height="150px" Width="150px" />
        <asp:Image ID="slotTwoImage" runat="server" CssClass="auto-style1" Height="150px" Width="150px" />
        <asp:Image ID="slotThreeImage" runat="server" CssClass="auto-style1" Height="150px" Width="150px" />
        <br />
        <br />
        <asp:Label ID="yourBetLabel" runat="server" Font-Names="Arial" Text="Your Bet:"></asp:Label>
        <asp:TextBox ID="betAmountTextBox" runat="server"></asp:TextBox>
        <br />
        <br />
        <asp:Button ID="pullLeverButton" runat="server" Font-Names="Arial" OnClick="leverPullButton_Click" Text="Pull The Lever!" />
        <br />
        <br />
        <asp:Label ID="resultLabel" runat="server" Font-Names="Arial"></asp:Label>
        <br />
        <br />
        <asp:Label ID="moneyLabel" runat="server" Font-Names="Arial"></asp:Label>
        <br />
        <br />
        <asp:Label ID="rulesLabel" runat="server" Font-Names="Arial"></asp:Label>
        <br />
        <br />
        <asp:Label ID="testLabel" runat="server"></asp:Label>
    
    </div>
    </form>
</body>
</html>

I didn’t make any changes to the user interface for this project. Maybe as I think and learn things down the road. Or if you’re reading this and want to comment please do so.

 
Default.aspx.cs Code File Contents

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

namespace BasicSlotMachine
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Setting the text on the rules label.
            rulesLabel.Text = "1 Cherry - x2 Your Bet<br />2 Cherries - x3 Your Bet<br />3 Cherries - x4 Your Bet<br /><br />3 7's - Jackpot x100 Your Bet" +
                "<br /><br />HOWEVER<br /><br />If you even have one BAR you win nothing";

            // Checking to see if this is the first page load.
            if (!Page.IsPostBack)
            {
                // Displaying the initial slots on program load. 
                // Like you are walking up to a slot machine for the first time.
                createGame();

                // Setting the players initial purse amount to 100 dollars and saving to view state.
                ViewState.Add("PlayersMoney", 100);

                // Displaying the purse amount on the initial page load.
                displayPurseAmount();
            }
            else
            {
                resultLabel.Text = "";
            }
        }

        // Protected Methods.
        //
        protected void leverPullButton_Click(object sender, EventArgs e)
        {
            // Getting the amount of money the player has.
            double playersMoney = double.Parse(ViewState["PlayersMoney"].ToString());
            
            // Creating the player object to be used.
            Player playerOne = createPlayer("Daniel", playersMoney);

            // Getting the bet amount from the text box and making sure it's a valid number.
            playerOne.CheckBetAmount(betAmountTextBox.Text.Trim());

            // Making sure the player can bet the amount that was typed in.
            // Or the amount that was typed in is a valid number or amount.
            if (playerOne.PlayerBetAmount == 0)
                resultLabel.Text = "Sorry you must enter a valid bet amount.";
            else if (playerOne.PlayerBetAmount > playerOne.PlayerPurseAmount)
                resultLabel.Text = "Sorry you can't bet that much.";
            else
            {
                // Creating the game object to be used.
                CherryGame cherryGame = createGame(playerOne);

                // Time to play the game. 
                cherryGame.PullLever(playerOne.PlayerBetAmount);
                
                // Saving the new purse amount to ViewState to use in the next round.
                ViewState.Add("PlayersMoney", playerOne.PlayerPurseAmount);

                // Displaying the players purse amount.
                displayPurseAmount();
            }
        }

        // Private Methods.
        //
        private Player createPlayer(string playerName, double purseAmount)
        {
            // Creating the player object and returning.
            Player player = new Player(playerName, purseAmount);
            return player;
        }

        // Method used to display the initial slot images.
        private void createGame()
        {
            CherryGame cherrySlotGame = new CherryGame(createGameObject());
            cherrySlotGame.SpinReels();
            displaySlots(cherrySlotGame);
        }

        // Method used to do the work neccessary to play the slots game.
        private CherryGame createGame(Player player)
        {
            CherryGame cherrySlotGame = new CherryGame(createGameObject(), player);
            cherrySlotGame.SpinReels();
            displaySlots(cherrySlotGame);
            return cherrySlotGame;
        }

        // Method used to create the game object.
        private List<CherrySlots> createGameObject()
        {
            CherrySlots cherrySlotObject = new CherrySlots();
            List<CherrySlots> cherrySlots = cherrySlotObject.CreateCherrySlots();
            return cherrySlots;
        }

        // Method used to display the slot images.
        private void displaySlots(CherryGame cherryGame)
        {
            slotOneImage.ImageUrl = cherryGame.GameSlotObjects[0].SlotImageLocation;
            slotTwoImage.ImageUrl = cherryGame.GameSlotObjects[1].SlotImageLocation;
            slotThreeImage.ImageUrl = cherryGame.GameSlotObjects[2].SlotImageLocation;
        }

        // Method used to display the players purse amount.
        private void displayPurseAmount()
        {
            // Displaying the players purse amount from the value in viewstate.
            moneyLabel.Text = String.Format("Players Money: {0:C2}", ViewState["PlayersMoney"]);
        }
    }
}

Right away you should see the differences between this version and the previous one. Less lines of code to start with. It went from ~230 lines of code down to ~120 lines of code. I can probably shrink it down by seperating things out. I’m learning about SOC (Seperation Of Concerns) principles now. So I’ll be applying what I’ve been learning to new revisons. I’ve taken all the code that was mashed all in the previous Default.aspx file and created different classes to create instances of the objects needed to play the game. And to even further simplify the protected methods I’ve put in private method calls to take care of the creation of the required game and player objects.

Also I’m still using the browser ViewState to store how much money the player has in the purse. You will see things like this scattered in the different classes that were used in the previous version.

 
Player.cs Code File Contents

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

namespace BasicSlotMachine
{
    public class Player
    {
        // Public Read-Only Properties
        //
        public string PlayerName { get; private set; }
        public double PlayerPurseAmount { get; private set; }
        public double PlayerBetAmount { get; private set; }

        // Contsructors
        //
        public Player(string playerName, double purseAmount)
        {
            this.PlayerName = playerName;
            this.PlayerPurseAmount = purseAmount;
        }

        //Public Methods
        //
        // Method used to adjust the players purse amount
        public void AdjustPurseAmount(double amount, bool addOrSubtract)
        {
            // Checking to see if the amount needs to be added or subtracted.
            if (addOrSubtract)
                PlayerPurseAmount += amount;
            else
                PlayerPurseAmount -= amount;
        }

        // Method used to take the string bet amount from the text box and convert to a number to be used.
        public void CheckBetAmount(string amount)
        {
            // Checking the amount being passed in, trying to convert to a valid double number, and using that
            // number to set the players bet amount property. if the text cannot be converted zero is returned.
            double bet;

            if (!double.TryParse(amount, out bet))
                bet = 0;
            else
                PlayerBetAmount = bet;
        }
    }  
}

The Player class has public read only properties for the players name, purse amount, and bet amount. The public methods take care of adding or removing funds from the players. There’s also a small input validation method, CheckBetAmount(), that makes sure the number the user entered is a valid number. Further checks on this number are done once that CherryGame class are created.

 
CherrySlots.cs Code File Contents

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

namespace BasicSlotMachine
{
    public class CherrySlots
    {
        // Public Read-Only Properties
        //
        public string SlotName { get; private set; }                // Property for the slot image name.
        public string SlotImageLocation { get; private set; }       // Property for the location of the slot image file.
        public int SlotValue { get; private set; }                  // Property for the slots numerical value.

        // Public Methods
        //
        public List<CherrySlots> CreateCherrySlots()
        {
            List<CherrySlots> cherrySlots = new List<CherrySlots>
            {
                // Create the slots.
                new CherrySlots { SlotName = "Bar", SlotImageLocation = "~/SlotImages/Bar.png", SlotValue = 1},
                new CherrySlots { SlotName = "Bell", SlotImageLocation = "~/SlotImages/Bell.png", SlotValue = 2 },
                new CherrySlots { SlotName = "Cherry", SlotImageLocation = "~/SlotImages/Cherry.png", SlotValue = 3},
                new CherrySlots { SlotName = "Clover", SlotImageLocation = "~/SlotImages/Clover.png", SlotValue = 4},
                new CherrySlots { SlotName = "Diamond", SlotImageLocation = "~/SlotImages/Diamond.png", SlotValue = 5},
                new CherrySlots { SlotName = "HorseShoe", SlotImageLocation = "~/SlotImages/HorseShoe.png", SlotValue = 6},
                new CherrySlots { SlotName = "Lemon", SlotImageLocation = "~/SlotImages/Lemon.png", SlotValue = 7},
                new CherrySlots { SlotName = "Orange", SlotImageLocation = "~/SlotImages/Orange.png", SlotValue = 8},
                new CherrySlots { SlotName = "Plum", SlotImageLocation = "~/SlotImages/Plum.png", SlotValue = 9},
                new CherrySlots { SlotName = "Seven", SlotImageLocation = "~/SlotImages/Seven.png", SlotValue = 10},
                new CherrySlots { SlotName = "Strawberry", SlotImageLocation = "~/SlotImages/Strawberry.png", SlotValue = 11},
                new CherrySlots { SlotName = "Watermellon", SlotImageLocation = "~/SlotImages/Watermellon.png", SlotValue = 12}
            };
            return cherrySlots;
        }
    }
}

The CherrySlots class has read-only properies for the slots name, image file location, and value. These properties are in a method that when called initializes a collection objects with these properties and returns the created collection object. A simple class that’s taking care of the basic nuts and bolts of the game.

 
CherryGame.cs Code File Contents

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

namespace BasicSlotMachine
{
    public class CherryGame
    {
        // Public Read-Only Properties
        //
        public Random Random { get;  private set; }                      // Random property used for random reel images.
        public Player PlayerOne { get; private set; }                    // Player object that holds the players information.
        public List<CherrySlots> SlotObjects { get; private set; }       // List property for the slot image objects.
        public List<CherrySlots> GameSlotObjects { get; private set; }   // List property for the slots used when the game is played.
        public double Winnings { get; private set; }                     // Property that holds the players winnings for the spin.

        // Constructors
        //
        public CherryGame()
        {
            this.Random = new Random();
        }

        public CherryGame(List<CherrySlots> slots)
        {
            this.Random = new Random();
            this.SlotObjects = slots;
        }

        public CherryGame(List<CherrySlots> slots, Player playerOne)
        {
            this.Random = new Random();
            this.SlotObjects = slots;
            this.PlayerOne = playerOne;
        }

        // Public Methods
        //
        // Method used to randomly select what the reels will be. 
        public void SpinReels()
        {
            // Getting 3 reel objects to place in the GameSlotObjects list. The game will work on this list
            // to determine money gained/lossed based on what random images are placed.
            GameSlotObjects = new List<CherrySlots> { spinReelWork(), spinReelWork(), spinReelWork() };
        }

        // Method that invoked the evaluation of the reels and determines the multiplier / winnings.
        public void PullLever(double betAmount)
        {
            // Taking the bet amount away from the players purse.
            PlayerOne.AdjustPurseAmount(betAmount, false);

            // Trying to figure out of the bet amount needs to be multiplied.
            double multiplier = evaluateSpin(GameSlotObjects);

            // Adjusting how much the player has won for the spin.
            Winnings = PlayerOne.PlayerBetAmount * multiplier;

            // Adjusting the players purse amount based on any winnings.
            PlayerOne.AdjustPurseAmount(Winnings, true);
        }

        // Private Methods
        //
        private CherrySlots spinReelWork()
        {
            CherrySlots slotObject = SlotObjects[Random.Next(SlotObjects.Count)];
            return slotObject;
        }

        private double evaluateSpin(List<CherrySlots> slotObjects)
        {
            // Checking to see if the bar is anywhere in the slots.
            if (isbar(slotObjects)) return 0;

            // Checking to see if there is a jackpot.
            if (isJackpot(slotObjects)) return 100;

            //Checking to see how many cherry images are on the slots.
            int cherryMultiplier = 0;
            if (isWinner(slotObjects, out cherryMultiplier)) return cherryMultiplier;

            // If none of the images are anything of value then return 0.
            return 0;
        }

        // Method used to see if there are any bars in the images.
        private bool isbar(List<CherrySlots> slotObjects)
        {
            // Looking for the bar images.
            if (slotObjects[0].SlotName == "Bar" || slotObjects[1].SlotName == "Bar" || slotObjects[2].SlotName == "Bar")
                return true;    
            else
                return false;
        }

        // Method to see if all the reels have sevens to equal a jackpot.
        private bool isJackpot(List<CherrySlots> slotObjects)
        {
            // Looking for the seven images.
            if (slotObjects[0].SlotName == "Seven" && slotObjects[1].SlotName == "Seven" && slotObjects[2].SlotName == "Seven")
                return true;
            else
                return false;
        }

        // Method to start the process of determining the cherry count.
        private bool isWinner(List<CherrySlots> slotObjects, out int multiplier)
        {
            // Calling on the method to determine the mutiplier amount and return true or false.
            multiplier = determineMultiplier(slotObjects);

            // Return true if the multiplier is greater than 0.
            if (multiplier > 0) return true;
            return false;
        }

        // Method used to determine the multiplier based on the cherry count.
        private int determineMultiplier(List<CherrySlots> slotObjects)
        {
            // Calling the method to evaluate the images and determine the cherry count.
            int cherryCount = determineCherryCount(slotObjects);

            // Checking the value of cherryCount and returning a set value for the reward.
            if (cherryCount == 0) return 0;
            if (cherryCount == 1) return 2;
            if (cherryCount == 2) return 3;
            if (cherryCount == 3) return 4;

            // If no cherries return nothing.
            return 0;
        }

        // Method used to evaluate the reel images and return the cherry count.
        private int determineCherryCount(List<CherrySlots> slotObjects)
        {
            // Variable to hold the cherry count.
            int cherryCount = 0;

            //Looking for cherry images on the reels and updating the cherry count.
            if (slotObjects[0].SlotName == "Cherry") cherryCount++;
            if (slotObjects[1].SlotName == "Cherry") cherryCount++;
            if (slotObjects[2].SlotName == "Cherry") cherryCount++;

            // Returning the cherry count value.
            return cherryCount;
        }
    }
} 

This class is where I put all of the game logic. If you compare this version to the last version you can see I’m using the same methods with modifications so I can use lists intead of arrays and utilizing OOP concepts for game functions.

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 )

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 )

Connecting to %s