3
\$\begingroup\$

I created this game inspired by this problem: https://www.codechef.com/ZCOPRAC/problems/ZCO14001

The problem needs you create a machine that can lift boxes and drop them in a new column. Then, when the problem asks you to, you have to print how many boxes are in every column.

I tried to improvise it and make it as as interesting and interactive as possible, but it's a bit too long, and also might contain bugs. How do I make it shorter?

It provides you a controller with tkinter buttons.

Here's the code:

from os import system
from tkinter import *

cls = lambda: system('cls')

class VideoGame:
    def __init__(self, rows, columns, stacks):
        self.stacks = stacks
        self.rows = rows
        self.columns = columns
        self.cur_column = 0
        self.box_in_hand = False

        self.commands = {'1': self.move_left, '2': self.move_right,
                         '3': self.pick_up_box, '4': self.drop_box,
                         '5': self.add_row, '6': self.add_column,
                         '7': self.del_row, '8': self.del_column,
                         '9': self.fill_all, '10': self.remove_all
                        }


    def command_parser(self, command):
        cls()
        self.commands[command]()
        self.print()


    def move_left(self):
        if self.cur_column < 0:
            print(f'\nNo place to move left\n')
            return

        self.cur_column -= 1


    def move_right(self):
        if self.cur_column >= self.rows:
            print(f'\nNo place to move right\n')
            return

        self.cur_column += 1


    def pick_up_box(self):
        if self.box_in_hand:
            print('\nAlready have a box in hand\n')
            return

        if self.cur_column == -1:
            self.add_box()
            return

        if self.cur_column >= self.rows:
            print('\nCan\'t pick up box from ()\n')
            return

        if self.stacks[self.cur_column] == 0:
            print(f'\nNo box to pick up in row {self.cur_column + 1}\n')
            return

        self.stacks[self.cur_column] -= 1
        self.box_in_hand = True


    def drop_box(self):
        if not self.box_in_hand:
            print('\nDon\'t have a box in hand\n')
            return

        if self.cur_column == self.rows:
            self.remove_box()
            return

        if self.cur_column < 0:
            print('\nCan\'t drop box to {}\n')
            return

        if self.stacks[self.cur_column] == self.columns:
            print(f'\nMax stack reached in row {self.cur_column + 1}\n')
            return

        self.stacks[self.cur_column] += 1
        self.box_in_hand = False


    def print(self):
        print()

        s1 = list('--') + list('--' * self.rows) + list('-')
        s2 = list('  ') + list('  ' * self.rows) + list(' ' * 3)

        s1[self.cur_column * 2 + 2] = 'O'
        s2[self.cur_column * 2 + 2] = 'C'

        if self.box_in_hand:
            s2[self.cur_column * 2 + 3] = '['
            s2[self.cur_column * 2 + 4] = ']'

        print(''.join(s1))
        print(''.join(s2))

        print()

        for i in range(self.columns, 0, -1):
            print(end='  ')

            for j in range(self.rows):
                if self.stacks[j] >= i:
                    print('[]', end='')

                else:
                    print('  ', end='')
            print()

        print('{}' + '  ' * self.rows + '()')
        print()


    def add_column(self):
        self.columns += 1


    def add_row(self):
        self.rows += 1
        self.stacks.append(0)


    def del_row(self):
        self.rows = max(0, self.rows - 1)
        self.stacks = self.stacks[:-1]

        self.cur_column = min(self.rows, self.cur_column)


    def del_column(self):
        self.columns = max(0, self.columns - 1)
        self.stacks = [min(i, self.columns) for i in self.stacks]


    def add_box(self):
        self.box_in_hand = True


    def remove_box(self):
        self.box_in_hand = False


    def fill_all(self):
        self.stacks = [self.columns] * self.rows


    def remove_all(self):
        self.stacks = [0] * self.rows


def parser(arr):
    return (list(map(lambda x: max(int(min(int(x), r)), 0), arr)) + [0] * r)[:r]


print('{} - Pick up box to create box\n'
      '() - Drop box to delete box\n')

while True:
    tk = Tk()

    r = int(input('Enter number of rows: '))
    c = int(input('Enter number of columns: '))
    s = parser(input(f'Enter {r} spaced integers all less than or equal to {c}: ').split())

    cls()
    game = VideoGame(r, c, s)
    game.print()

    Button(tk, text='Enter Command', width=20, command=None).grid(row=0, column=0, columnspan=2)
    Button(tk, text='Move Left', width=10, command=lambda: game.command_parser('1')).grid(row=2, column=0)
    Button(tk, text='Move Right', width=10, command=lambda: game.command_parser('2')).grid(row=2, column=1)
    Button(tk, text='Pick Box', width=10, command=lambda: game.command_parser('3')).grid(row=3, column=0)
    Button(tk, text='Drop Box', width=10, command=lambda: game.command_parser('4')).grid(row=3, column=1)
    Button(tk, text='Add Row', width=10, command=lambda: game.command_parser('5')).grid(row=4, column=0)
    Button(tk, text='Add Column', width=10, command=lambda: game.command_parser('6')).grid(row=4, column=1)
    Button(tk, text='Del Row', width=10, command=lambda: game.command_parser('7')).grid(row=5, column=0)
    Button(tk, text='Del Column', width=10, command=lambda: game.command_parser('8')).grid(row=5, column=1)
    Button(tk, text='Fill All', width=10, command=lambda: game.command_parser('9')).grid(row=6, column=0)
    Button(tk, text='Remove All', width=10, command=lambda: game.command_parser('10')).grid(row=6, column=1)
    Button(tk, text='Row Size', width=10, command=lambda: print('Number of rows =', game.rows)).grid(row=7, column=0)
    Button(tk, text='Column Size', width=10, command=lambda: print('Number of columns =',game.columns)).grid(row=7, column=1)
    Button(tk, text='Quit', width=5, command=lambda: tk.destroy()).grid(row=8, column=0, columnspan=2)

    tk.mainloop()

    cls()

How do I make my code shorter and easier to read?
Also, tips for making the code more interactive are welcome!

Thank you for your help!

\$\endgroup\$
  • \$\begingroup\$ Please include a short description of what the game is about. Links can rot. \$\endgroup\$ – Mast Nov 8 at 8:31
  • \$\begingroup\$ Sure, I've edited the question accordingly, and also provided the link. \$\endgroup\$ – Srivaths Nov 8 at 8:54
3
\$\begingroup\$

I don't have enough reputation to add comments in this stack site. So I'll leave my thoughts in an answer.

Something that really caught my eye was that you are overloading Pythons print() function. Sure you CAN do that, but SHOULD you do really do that? I get what you are trying to do, but I would just make a new function of it instead. Also, there are a lot of code that can break in there, I suggest some error handling.

Your drop_box and pick_up_box functions have a lot of returns, but none of them returns anything. I would have used 'elif' and a final 'else' instead.

The function 'fill_all' should be renamed to 'fill_all_stacks'.

\$\endgroup\$
  • \$\begingroup\$ +1 for the nice answer. Might as well become the accepted answer if you can add a bit more improvisations! \$\endgroup\$ – Srivaths Nov 8 at 14:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.