Project: Code a Slot machine Using Python's random library

 In this blog I am going to explain how I created A Slot Machine using Python:

Some of the key features of this program:

  1. We have to maintain balance that player will add throughout the whole program 
  2. We have to show balance 
  3. We have to give an option to update the balance from user
  4. Tackle every situation accordingly 
So, let's start




So, first let us think what we are going to make. We are going to make a 3 by 3 slot machine which will be shown on the screen, and the player will bet on rows. The elements we are using are As, Bs, Cs and Ds. We are using alphabets and not numbers just for simplification. To give you a sneak peak how that slot will look like let me show you the output:

Example: how the output of slot machine will look like

First, we will import the random library:

Code:

import random

We just imported it and will use it later, now our first task is to take a deposit from user which will be his balance throughout the program or game. It must be a natural number (means 1 to infinite).

So, let's start by making a function for this:

Code:

def deposit():
    while True:
        amount = input("Enter the amount you want to deposit: $")
        if amount.isdigit():
            amount = int(amount)
            if amount>0:
                break
            else:
                print("Enter positive value")
        else:
            print("Please enter a number")
    return amount

Here we used while loop which is initialized with True then we used input to get the amount from user then we used an if condition to check if the entered number is digit or not and later, we used nested if to check if the amount entered by used is positive after conforming that the amount is a digit. If it clears all the condition, then we will break the while loop using "break". If any of the condition will be False, then it will print the required sentence, and the loop will again run until both conditions become True and break is implemented. break will end this infinite loop. In the end we will return the amount user entered which is a positive digit. Now we will take the number of rows our player wants to take bet on. Let's see how that work:

Code:

def get_number_of_lines():
    while True:
        lines = input(f"Enter the number of lines(1 to {MAX_LINES}): ")
        if lines.isdigit():
            lines = int(lines)
            if lines>0 and lines<=MAX_LINES:
                break
            else:
                print(f"No. of lines must be more than 0 and less than {MAX_LINES + 1}.")
        else:
            print("Please enter a numerical value")
    return lines

Here using same infinite loop and checking if the input is integer and the within the range using if nested if conditions and break if it satisfies the conditions. Here we used MAX_LINES means we will use 3 as example for our machine.  What we have to do is add few constants in the top of our program.

Code for constants: 

MAX_LINES = 3
MAX_BET = 100
MIN_BET = 1

ROWS = 3
COLS = 3

Remember these are constants and therefore should be written in Capital letters.

We took a Max lines constant which is 3 in our case. It will be used so that the maximum number of rows a player can bet on is 3 because we have a 3 by 3 slot machine. The other constants are Rows and cols representing number of rows and columns respectively. Max_bet and min_bet will be used later. Now let us code to get the amount player want to bet on each line.

Code:

def get_bet():
    while True:
        amount = input("Enter the amount you want to bet on each line: $")
        if amount.isdigit():
            amount = int(amount)
            if MIN_BET <=amount<=MAX_BET:
                break
            else:
                print(f"Enter value from ${MIN_BET} to ${MAX_BET} ")
        else:
            print("Please enter a number")

    return amount

we used the same loop and conditions; this time we checked if the amount is in between Min_bet and Max_bet which is 1 and 100 respectively.

Now let us create a main function and write call all of these functions that we have created till now. We will also calculate the total bet.

Code:

main():
    balance = deposit()
    lines = get_number_of_lines()
    bet_on_line = get_bet()
    total_bet = lines * bet_on_line 


Now, from now things will get little interesting, we will write code to get slot machine. let's see how it goes:

What we are doing is making a dictionary where we will write all the values and their frequency that that can come in our slot machine.

Code:

symbol_count ={
    "A":3,
    "B":5,
    "C":7,
    "D":9,
    }
#I will use this dictionary that there are 3 As, 5 Bs, 7 Cs and 9 Ds.

Let's write code for getting the slot:

def get_machine_spin(rows,cols,symbols):
    all_symbols = [] #saving all symbols of symbol_count dictionary.
    for symbol,symbol_count in symbols.items(): # to get it in pair of symbol, symbol_count
        for _ in range(symbol_count): #this _ is when no index required
            all_symbols.append(symbol)
    #print(all_symbols)

    columns = []
    current_symbol = all_symbols[:] # copying the list

    for _ in range(cols):
        column = []
        for _ in range(rows):
            value = random.choice(current_symbol)
            column.append(value)
            current_symbol.remove(value)
        columns.append(column)
    return(columns)

Here, we defined the function get_machine_spin with parameters as rows, cols and symbols, first we made an empty list named all_symbols. The symbols parameter here will get the dictionary that we created as symbol_count. Then we started a for loop to get symbol and symbol_count using symbols.items(). symbols.items() will create a list of tuples containing two elements of dictionary in it. Symbol will get the alphabet and symbol_count will get the frequency of that alphabet. In nested for loop wi will use range and then add the symbol in the list that we created earlier named all_symbols. all_symbols list contains all the alphabets with their frequency. Make another empty list columns and copy the all_symbols list. 

Again, we will use for loop and then we will create a temporary list named column which will store the column. Remember we are storing column in the list not rows, so, later we have to print rows for our slot machine. the _ after for loop is used when we have to go through all of the list without requiring the index. The nested for loop is for getting the value of column using random module that we already imported by using random.choice(). We will append the value in column list and remove that value from the curren_symbol_list and then we will add this list in another list columns which will contain all the list of column.

Columns list will look like this for example:

[[column1], [column2], [column3]]

In the end we will return the columns list. Now let us create function to print the slot machine.

Code:

def print_slot_machine(columns):
    for row in range(len(columns[0])):
        
        for i,column in enumerate(columns):
            if i != len(columns)-1:
                print(column[row],end = " | ")
            else:
                print(column[row], end = "")
        print()

First for loop is to get the number of rows, nested loop is used with enumerate function. Enumerate function returns the index and the element. Then we checked if the index i is not 2. This i will go from 0 then 1 and then if it's 2 then the condition will become False and the code in else block will execute.
Now what we have done in if and else block is if the if condition is True then in will print the first element in column1 then we also used end here which will print | after printing the element then this nested loop will again continue and this time it will print the first element of column2 and then i will become 2 else block will be executed and this time it will print the first element of column3 and then it will execute end = "". To avoid next row to merge with the previous one we will use print() it will work as newline or \n. Then the upper loop will work this time the value of row will become 1. Then the nested loop will work again this time second element of column1 then second element of column2 and at last 2 element of column3.Then row will become 2 and nested loop will work in this same manner.
It was little bit tricky for me too when I was doing it for the first time. My suggestion is dry run this part of code on paper so that you can understand it properly.


Let me try to explain it with another example:
Assume the columns list looks like this:
columns = [[1,2,3],[4,5,6],[7,8,9]]
[1,2,3] is column1, [4,5,6] is column2 and [7,8,9] is column3.
for row in range(len(columns[0])):
value of row will be from 0 to 2.
for i,column in enumerate(columns):
value of i will be from 0 to 2 and in column we will get [1,2,3] first till [7,8,9].
 if i != len(columns)-1:
                print(column[row],end = " | ")
if i not equal to 2 then print row element of column{[1,2,3]} and the value of row will be 0 so it will print 1 and then | then the nested loop will again run with i equals to 1 and this time column will be [4,5,6] so this time it will print 4(because row is still 0) in same manner it will print 7 by else block. Then the value of row will change to 1 and this nested loop will again run with printing 2 then 5 then 8. Same for third row also. But in our slot machine instead of printing numbers like 1 or 7 or anything it will print the value which is present at that number. Now let us setup the main function and tryout the code:


Code:
def main():
    balance = deposit()
    lines = get_number_of_lines()
    bet_on_line = get_bet()
    total_bet = lines * bet_on_line
    if total_bet<=balance:
        print(f"You are betting ${bet_on_line} on {lines} lines.\nTotal bet is ${total_bet}.")
        slot = get_machine_spin(ROWS,COLS,symbol_count) 
        print_slot_machine(slot)
    else:
        print(f"Your current balance is: ${balance}\nyou are betting: ${total_bet}.")

we just call the functions, if the total bet is less than balance then it will print the slot machine otherwise the program will end. Now we have to check the winnings and update the balance according to it.


Code:
symbol_values ={
    "A":6,
    "B":5,
    "C":4,
    "D":3,
    }

We created another dictionary with the values of multiplier for each alphabet. If we get 3 Ds in a row then the row will get multiplied by 3.

If the player chooses to bet on 1 line, then he is betting on 1st row, if he chooses 2 lines then he is betting on first 2 rows and if he chooses 3 lines then he is betting on all three rows that's how our slot machine will work.

Now let's create a function to check the winnings.

Code:

def check_winnings(columns, lines, bet, values):

    winnings = 0
    for line in range(lines):
        symbol = columns[0][line]
        for column in columns:
            symbol_to_check = column[line]
            if symbol != symbol_to_check:
                break
        else:
            winnings += bet* values[symbol]

    return winnings
here the parameters will take 
columns will take slot which is returned in get_machine_spin(), which is the list of columns.
lines will take lines which is returned in get_number_of_lines(), which is the number of lines the user is betting.
bet will take bet_on_line which is returned in get_bet(), which is the amount player is betting.
values will get the dictionary symbol_values.
Again, using the example of columns = [[1,2,3],[4,5,6],[7,8,9]],
this is how our slot machine will look like with using these numbers, remember these numbers are just position representation:

1 4 7
2 5 8
3 6 9

for line in range(the number of line user is betting),
symbol will get [1] now in nested loop column will get [1,2,3] symbol_to_check =[1,2,3][0] it will get 1 now in the nested loop column will get 2nd element of columns which is  [4,5,6] symbol to check will be 4 if it's not equal to symbol which is 1 then if it's not equal then the loop will break and the outer loop will start if its equal then nested loop will run now column will get [7,8,9] and it will check symbol with 7. We have used for else here if this inner loop terminates normally without break then this else block will get executed which is winnings = winnings +(bet*value[symbol]). Then the outer loop will get executed if the user is betting on more than 1 line, if it is 2 then the value of line will be 1, then in the same manner this nested loop will work and check first element of row 2 with 2nd and 3rd element of row 2 and if they will be same then it will flow of program will get into the else block increasing the winnings, then same will happen for the third row. In the end we will return the winnings.
Now we add these two line of code in our main function:

Code: 

winnings = check_winnings(slot,lines,bet_on_line,symbol_values)
print(f"Winnings:{winnings}")
It will simply print the number of winnings.
Now this is what the output we are getting after writing this much of code:



This became a complete single cycle of our game, now we have to update the deposit means if player wins then add the amount in balance which they deposited and if they lose then reduce the amount from their balance and to run the cycle of game again and again with updating the balance.
Now let us made some changes in main function and create another function game() which will represent the 1 cycle of the game.

Code:

def game(balance):
    print(f"balance:{balance}")
    while True:
        lines = get_number_of_lines()
        bet_on_line = get_bet()
        total_bet = lines * bet_on_line
        if total_bet<=balance:
            print(f"You are betting ${bet_on_line} on {lines} lines.\nTotal bet is ${total_bet}.")
            slot = get_machine_spin(ROWS,COLS,symbol_count) 
            print_slot_machine(slot)
            winnings = check_winnings(slot,lines,bet_on_line,symbol_values)
            print(f"Winnings:{winnings}")
        else:
            print(f"Your current balance is: ${balance}\nyou are betting: ${total_bet}.")
            continue

Just copy paste the code that we have written in main() function to make a function game() representing one cycle of game also do some minor changes like printing the balance. The main() function will look like this:

Code:

def main():
    balance = deposit()
    game(balance)

Now we have to update the values:

Code:

def update_balance(balance,winnings,bet):
    balance+= (winnings - bet)

    if balance>0:
        game(balance)
    else:
        balance = update_balance_user()
    return balance

here we created the update_balance() function it will update the balance like:
balance = balance +(winnings- bet). If balance is greater than 0 means players still have some balance, then we will again run the game with game(balance) function this time with updated balance after one game. This is recursion. We are calling update_balance() function inside game() function and game() function inside update_balance() function. If the balance is negative then we will create another function to ask user if he wants to add more amount in balance. Let us see how it works:

Code:

def update_balance_user():
    
    ask = input("Do You want to update/add balance?")
    if ask =="no" or ask == "NO":
        print("Thank-you for playing\nGame Over")
    else:
        balance = deposit()
        game(balance)

If he inputs no then the program will get end. If he presses enter or anything else, then the else block will get executed and then we will call the deposit() function and start the game() function with updated balance which user entered. In this way program will run again. Now add this function in your game() function:

Code:

update_balance(balance,winnings,total_bet)
break

This break is used to terminate the program if the user enters no in update_balance_user() function. Your game() function will look like this:


def game(balance):

    print(f"balance:{balance}")
    while True:
        lines = get_number_of_lines()
        bet_on_line = get_bet()
        total_bet = lines * bet_on_line
        if total_bet<=balance:
            print(f"You are betting ${bet_on_line} on {lines} lines.\nTotal bet is ${total_bet}.")
            slot = get_machine_spin(ROWS,COLS,symbol_count) 
            print_slot_machine(slot)
            winnings = check_winnings(slot,lines,bet_on_line,symbol_values)
            print(f"Winnings:{winnings}")
            update_balance(balance,winnings,total_bet)
            break
            
        else:
            print(f"Your current balance is: ${balance}\nyou are betting: ${total_bet}.")
            continue

Now I will run the program and try to get as many variety of outputs as possible:
The program is executed without any error with proper functioning






I hope it helped you and with this project I also learned a lot, I also faced some issues while doing it but they were resolved with time. We can also add new features in it like getting a code from user something like Code500 or bonus500 which will add the 500 in the balance.
If you guys have any new idea which will challenge my learnings or something which will help me improve, please let me know guys.
All the suggestions are welcomed.
Thank-you




Comments