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

Python magic balls game

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

Problem

I wrote a simple magic balls game in Python with GTK3. If the user clicks on a button with a ball, this ball will move to the selected point. If the user makes 5 consecutive balls horizontally or vertically, the balls disappear. In my move_ball function, there are many for loops that check for 5 balls. How can I simplify this?

```
# coding=utf-8
from random import randrange

import gi

gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GdkPixbuf

class Cell(Gtk.Button):
def __init__(self):
Gtk.Button.__init__(self)
self.ball_color = None
self.is_ball = False
self.button = Gtk.ToggleButton().new()
self.button.set_size_request(50, 50)

def place_ball(self, color):

ball = GdkPixbuf.Pixbuf.new_from_file_at_size(str(color) + '.svg', 35, 35)
image = Gtk.Image()

image.set_from_pixbuf(ball)
image.show()
self.ball_color = color
self.is_ball = True
self.button.add(image)
self.button.show()

# noinspection PyUnresolvedReferences
class BallsGrid(Gtk.Grid):
def __init__(self, rows, cols):
Gtk.Grid.__init__(self)
self.rows = rows
self.cols = cols
self.cells = []
self.dict = {1: 'blue', 2: 'fiolet', 3: 'green', 4: 'red', 5: 'yellow'}

for row in range(rows):
for col in range(cols):
cell = Cell()
self.cells.append(cell)
self.attach(cell.button, row, col, 1, 1)

self.place_balls(5)

def place_balls(self, number):

balls = 0

while balls <= number:

row = randrange(0, self.rows)
col = randrange(0, self.cols)
color = randrange(1, 6)

i = self.get_index(row, col)

if not self.cells[i].is_ball:
self.cells[i].place_ball(self.dict[color])
balls += 1

def move_ball(self, from_point, to_point):

color = self.cells[from_po

Solution

You probably mean this part of your code:

if horizontal_left == 5:
        for i in range(0, 5):
           delete_point = self.get_index(row - i, col)
           self.cells[delete_point].button.get_child().destroy()

    if horizontal_right == 5:
        for i in range(0, 5):
           delete_point = self.get_index(row + i, col)
           self.cells[delete_point].button.get_child().destroy()

    if vertical_top == 5:
        for i in range(0, 5):
            delete_point = self.get_index(row, col + i)
            self.cells[delete_point].button.get_child().destroy()

    if vertival_down == 5:
        for i in range(0, 5):
            delete_point = self.get_index(row, col - i)
            self.cells[delete_point].button.get_child().destroy()


You may replace it with this:

CORNERS = ((-1, 0), (+1, 0), (0, +1), (0, -1))
    coords =  (horizontal_left, horizontal_right, vertical_top, vertival_down)

    for (x, y), pos in zip(CORNERS, coords):
        if pos == 5:
            for i in range(0, 5):
               delete_point = self.get_index(row + x*i, col + y*i)
               self.cells[delete_point].button.get_child().destroy()


(as you originally did the similar things 4 times).

The explanation:

The builtin function zip() creates pairs from the corresponding elements:

(
    ((-1, 0), horizontal_left), 
    ((+1, 0), horizontal_right),
    ((0, +1), vertical_top),
    ((0, -1), vertival_down)
)


and in the for loop

for (x, y), pos in zip(CORNERS, coords):


its values are unpacked with expression

(x, y), pos


You may use the similar method in other parts of your code, too.

Code Snippets

if horizontal_left == 5:
        for i in range(0, 5):
           delete_point = self.get_index(row - i, col)
           self.cells[delete_point].button.get_child().destroy()

    if horizontal_right == 5:
        for i in range(0, 5):
           delete_point = self.get_index(row + i, col)
           self.cells[delete_point].button.get_child().destroy()

    if vertical_top == 5:
        for i in range(0, 5):
            delete_point = self.get_index(row, col + i)
            self.cells[delete_point].button.get_child().destroy()

    if vertival_down == 5:
        for i in range(0, 5):
            delete_point = self.get_index(row, col - i)
            self.cells[delete_point].button.get_child().destroy()
CORNERS = ((-1, 0), (+1, 0), (0, +1), (0, -1))
    coords =  (horizontal_left, horizontal_right, vertical_top, vertival_down)

    for (x, y), pos in zip(CORNERS, coords):
        if pos == 5:
            for i in range(0, 5):
               delete_point = self.get_index(row + x*i, col + y*i)
               self.cells[delete_point].button.get_child().destroy()
(
    ((-1, 0), horizontal_left), 
    ((+1, 0), horizontal_right),
    ((0, +1), vertical_top),
    ((0, -1), vertival_down)
)
for (x, y), pos in zip(CORNERS, coords):
(x, y), pos

Context

StackExchange Code Review Q#159664, answer score: 2

Revisions (0)

No revisions yet.