patternpythonMinor
Python magic balls game
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
```
# 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
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:
You may replace it with this:
(as you originally did the similar things 4 times).
The explanation:
The builtin function
and in the
its values are unpacked with expression
You may use the similar method in other parts of your code, too.
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 loopfor (x, y), pos in zip(CORNERS, coords):its values are unpacked with expression
(x, y), posYou 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), posContext
StackExchange Code Review Q#159664, answer score: 2
Revisions (0)
No revisions yet.