George Willcox
George Willcox

Reputation: 673

How to create objects and then apply methods to them in a loop

I've created a version of noughts and crosses in python using pygame, the finished game turned out much better than expected and I'm quite pleased with it. However, the code appears to be quite messy and I'd like to clean it up a bit. For the code to work, I create 9 objects of a sprite class that I've written. But whenever I need to apply a method to them, I have to write the same line out nine times with a difference of only one number. To fix this, I'd like to know if there is anything that I could do to run the same script for each of the nine objects. The program starts by creating the objects:

board_0 = classes.sprite.Sprite(x = 250, y = 200)
board_0.set_image('board.png')
board_1 = classes.sprite.Sprite(x = 350, y = 200)
board_1.set_image('board.png')
board_2 = classes.sprite.Sprite(x = 450, y = 200)
board_2.set_image('board.png')
board_3 = classes.sprite.Sprite(x = 250, y = 300)
board_3.set_image('board.png')
board_4 = classes.sprite.Sprite(x = 350, y = 300)
board_4.set_image('board.png')
board_5 = classes.sprite.Sprite(x = 450, y = 300)
board_5.set_image('board.png')
board_6 = classes.sprite.Sprite(x = 250, y = 400)
board_6.set_image('board.png')
board_7 = classes.sprite.Sprite(x = 350, y = 400)
board_7.set_image('board.png')
board_8 = classes.sprite.Sprite(x = 450, y = 400)
board_8.set_image('board.png')

Would it be possible to use a for loop to create these in just a few lines rather than the eighteen needed here. The same solution would hopefully work elsewhere in the code, I have these two sections that are repeated nine times for each of the objects:

if board_0.mouse_hover() and grid[0] == 0:
        if   turn == 0: board_0.set_image('cross.png')
        elif turn == 1: board_0.set_image('nought.png')
    else:
        if grid[0] == 0:  board_0.set_image('board.png')

if board_0.mouse_click() and grid[0] == 0:
    if  turn == 0:
        board_0.set_image('cross.png')
        grid[0] = 'X'
        turn = 1
    elif turn == 1:
        board_0.set_image('nought.png')
        grid[0] = 'O'
        turn = 0

Just for those wondering I set grid at the start of the code: grid = [0, 0, 0, 0, 0, 0, 0, 0, 0] So what can be done to achieve the result that I'd like, I believe I've had this issue in the past but I didn't know of Stack Overflow then so I'll be updating some other programs too if there is in fact a solution to this.

Upvotes: 3

Views: 120

Answers (2)

James R
James R

Reputation: 4656

So I note you said "apply methods", but really what you are doing is calling a method on an instance of a type.

You could try something like this:

def set_my_sprites(x_start, y_start)
    sprites = []
    for y_mx in range(1, 4):
        for x_mx in range(1, 4):
            board_x = classes.sprite.Sprite(x = x_start*x_mx, y = y_start*y_mx)
            board_x.set_image('board.png')
            sprites.append(board_x)
     return sprites

then just call this function later as:

set_my_sprites(x_start=250, y_start=200)

You can probably fool around with the calling signature and whatnot to get a bit more flexibility.

In this case, I'm returning the array of sprites in case you want to do something with them later on, but I suppose you don't need to if it isn't required.

Upvotes: 3

Ohjeah
Ohjeah

Reputation: 1307

You can use a list comprehension and iterate over your parameters to create all the instances of Sprite.

from itertools import product

x_coords = [250, 350, 450]
y_coords = [200, 300, 400]

boards = [classes.sprite.Sprite(x=x, y=y) for x, y in product(x_coords, y_coords)]

for board in boards:
    board.set_image('board.png')

board_0 thus becomes boards[0]. Using itertools.product is just short for writing out the x,y pairs you have in your example.

Upvotes: 5

Related Questions