HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Puzzle game - converting binary numbers to decimal

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
numbersdecimalgamebinaryconvertingpuzzle

Problem

I've been learning Python for a few weeks and I created a simple game where you convert binary numbers to decimal. It shows you n binary numbers and you are supposed to enter the numbers in decimal system in sequence as a password. After failing three times you lose. I'd like to implement it into a bigger game later.

Here's the code:

import random

# Conver decimal to binary.
def toBin(i):
    bin = "{0:b}".format(i)
    return bin

# Generate random password and it's binary version.
def generatePassword(n):
    password = []
    passwordBin = []
    for i in range(n):
        a = random.randint(0, 9)
        password.append(a)
        passwordBin.append(toBin(a))
    return password, passwordBin

# Prints the binary password and a frame.
def printPassword(password):
    print(12 * '#')
    for i in range(len(password[1]) + 4):
        if i  0:
            printPassword(password)
            print('Attempts remaining: ' + str(attempts) + '\n')
            # Looping through password numbers.
            for i in range(n):
                print('Number ' + str(i + 1), '\t\t', end='')
                # Input and check for ValueError.
                try:
                    inp = int(input())
                except ValueError:
                    print('You can only enter numbers.')
                    break
                # Is input correct?
                if inp == password[0][i]:
                    print('CORRECT')
                else:
                    attempts -= 1
                    print('WRONG\n')
                    break
            # End loop and win.
            else:
                endLoop = True
                win = True
        # End loop.
        else:
            endLoop = True
    # Check win condition.
    if win is True:
        print('ACCESS GRANTED')
    else:
        print('ACCESS DENIED')

# Run the game.
puzzle(4)


Are there any ways to improve my code, expecially the puzzle(n) function? The conditions and loops took me some

Solution

Style

Please follow PEP8 conventions on naming: function names should be lowercase_with_underscores

On documentation: information on functions should be put below their definition in the form of a docstring, in order to allow programmatic access via help(function).

generatePassword

List comprehension

The explicit loop in generate_password is unnecessary, it is too long making the reader forget about the logic behind such function.

def generate_password_and_binary(n):
    """ A "password" is a list of length `n` containing random digits. """ 
    password = [random.randint(0, 9) for _ in range(n)]
    return password, [to_bin(digit) for digit in password]


This version with list comprehension is shorter and more to the point.

I also incorporated the comment into the function name (self-documenting code is better than code + comments) and added a more detailed docstring.

printPassword

I think your printPassword has a serious bug:

>>> generatePassword(8)
([2, 1, 7, 6, 4, 5, 7, 3], ['10', '1', '111', '110', '100', '101', '111', '11'])
>>> printPassword(_)
############
##        ##
##        ##
##  0010  ##
##  0001  ##
##  0111  ##
##  0110  ##
##        ##
##        ##
##        ##
##        ##
##        ##
##        ##
############


Only the first four digits where printed and the rest ignored.
This bug is probably a result of over-complication caused by indexes and comparison, while a plain for iteration over the collection is sufficient, here is a simpler (and correct!) way to write this function:

def print_password(binary_version): # No need to pass all password if only binary part is shown
    wall = "#" * 12
    spaced = "{0}{1}{0}".format("##", " " * 8)
    print(wall, spaced, sep="\n")
    for binary_digit in binary_version:
        print("{0}{1}{2}{1}{0}".format("##", "  ", binary_digit.rjust(4, "0")))
    print(spaced, wall, sep="\n")


Now all of the password is printed:

>>> print_password(['10', '1', '111', '110', '100', '101', '111', '11'])
############
##        ##
##  0010  ##
##  0001  ##
##  0111  ##
##  0110  ##
##  0100  ##
##  0101  ##
##  0111  ##
##  0011  ##
##        ##
############

Code Snippets

def generate_password_and_binary(n):
    """ A "password" is a list of length `n` containing random digits. """ 
    password = [random.randint(0, 9) for _ in range(n)]
    return password, [to_bin(digit) for digit in password]
>>> generatePassword(8)
([2, 1, 7, 6, 4, 5, 7, 3], ['10', '1', '111', '110', '100', '101', '111', '11'])
>>> printPassword(_)
############
##        ##
##        ##
##  0010  ##
##  0001  ##
##  0111  ##
##  0110  ##
##        ##
##        ##
##        ##
##        ##
##        ##
##        ##
############
def print_password(binary_version): # No need to pass all password if only binary part is shown
    wall = "#" * 12
    spaced = "{0}{1}{0}".format("##", " " * 8)
    print(wall, spaced, sep="\n")
    for binary_digit in binary_version:
        print("{0}{1}{2}{1}{0}".format("##", "  ", binary_digit.rjust(4, "0")))
    print(spaced, wall, sep="\n")
>>> print_password(['10', '1', '111', '110', '100', '101', '111', '11'])
############
##        ##
##  0010  ##
##  0001  ##
##  0111  ##
##  0110  ##
##  0100  ##
##  0101  ##
##  0111  ##
##  0011  ##
##        ##
############

Context

StackExchange Code Review Q#146033, answer score: 5

Revisions (0)

No revisions yet.