¡Hola, Invitado!


Patrocinantes


Síguenos en Facebook


Síguenos en Twitter

Compartir este tema:
[Código] Rompecabezas 2.0
Sifaw En línea
Moderador Global
******

Mensajes: 350
Registro en: Jul 2010
MySpace YouTube
Gracias dados: 25
Gracias recibidos: 32
Mensaje: #1
Rompecabezas 2.0
  • Compartir en Delicious
  • Compartir en Digg
  • Compartir en Linkedin
  • Compartir en MySpace
  • Compartir en Technorati
  • Compartir en Tuenti
Buenas, a continuación les dejo el código de la versión dos del rompecabezas. El código está comentado por encima e intentaré hacer un tutorial bien explicado sobre como crearlo y como funciona cada elemento utilizado.

Licencia:
Creative Commons Reconocimiento-NoComercial-Compartirigual 3.0

Cambios en la versión 2:
  • Cambiado los botones movibles.
  • Añadida opción de rompecabezas con imágenes a partir del nuevo botón o mediante Drag&Drop sobre el panel.
  • Soporta imágenes superiores a 160X160 con formato jpg, png o bmp.
  • Código revisado para un funcionamiento óptimo.

Video:

Requisitos para ejecutar desde código:
  • Python 2.X
  • WxPython
  • PIL

Código:
Lenguaje PYTHON
#!/usr/bin/python
#encoding: utf-8
 
############################################################​#################
## Creado por: Fernando Gomez                                              ##
## Version: 1.0                                                            ##
## Fecha: 18/05/2011                                                       ##
## Fecha2.0: 24/09/2011                                                    ##
## Licencia: Creative Commons Reconocimiento-NoComercial-CompartiIgual 3.0 ##
############################################################​#################
 
#Importamos los modulos necesarios
import wx, random, time
import  wx.lib.buttons  as  buttons
import  wx.lib.rcsizer  as rcs
from PIL import Image as im
from PIL import ImageDraw as id
 
class MyFileDropTarget(wx.FileDropTarget):
    def __init__(self, parent):
        wx.FileDropTarget.__init__(self)
        self.parent = parent
 
    def OnDropFiles(self, x, y, filenames):
        if (filenames[0][-3:] == "jpg") or (filenames[0][-3:] == "png") or (filenames[0][-3:] == "bmp"):
            self.parent.usoImg = True
            self.parent.DescomponerImagen(str(filenames[0]))
 
#Frame que contiene la interfaz
class Frame(wx.MiniFrame):
    def __init__ (self):
        wx.MiniFrame.__init__(self, None, -1, '', wx.DefaultPosition, (400, 400), (wx.DEFAULT_FRAME_STYLE)^(wx.RESIZE_BORDER|wx.MAXIMIZE_BOX))​
        self.posiciones = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", ""]
        self.inicio = 0 #Para el tiempo
        self.BitmapNull = wx.EmptyImage(40, 40)
        vacio = vacio = im.new("RGB", (40,40)) #Creamos una imagen vacia de 40X40
        vaciod = id.Draw(vacio)
        vaciod.rectangle((0,0,40,40), fill=(242,242,242))
        self.BitmapNull.SetData(vacio.tostring())
        self.usoImg = False #Variable Auxiliar para saber si se esta usando imagenes o no
        self.imagen = [] #Lista delos trozos de la imagen
        self.panel = wx.Panel(self, wx.NewId())
        self.botones = [wx.BitmapButton(self.panel, -1, bitmap=self.BitmapNull.ConvertToBitmap(), size=(40,40)) for i in range(len(self.posiciones))] #Lista con todos los botones de numeros
        for i in range(len(self.posiciones)):
            self.botones[i].SetLabel(str(self.posiciones[i]))
        dt = MyFileDropTarget(self)
        self.panel.SetDropTarget(dt)
        self.Center()
 
        self.sizer = rcs.RowColSizer() #Sizer para organizar los botones
        self.vertical = wx.BoxSizer(wx.VERTICAL) #Sizer para !Bravo! y el tiempo tardado
        self.s = wx.Button(self.panel, -1, "Mezclar") 
        self.image = wx.Button(self.panel, -1, "Imágen...")
        self.numero = wx.Button(self.panel, -1, "Números")
        self.hecho = wx.StaticText(self.panel, -1)
        self.tiempo = wx.StaticText(self.panel, -1)
        lugar = 0 #Colocamos cada boton en su lugar 
        for r in range(4):
            for c in range(4):
                self.sizer.Add(self.botones[lugar], row=r, col=c)
                lugar += 1
        self.sizer.Add(self.s, row=0, col=4)
        self.sizer.Add(self.image, row=1, col=4)
        self.sizer.Add(self.numero, row=2, col=4)
        self.vertical.Add(self.hecho)
        self.vertical.Add(self.tiempo)
        self.sizer.Add(self.vertical, row=3, col=4)
        self.panel.SetSizerAndFit(self.sizer) #Modificamos el tamaño del panel y la ventana para adaptarla al sizer
        self.SetClientSize(self.panel.GetSize())
 
        for i in self.botones: #Vinculamos cada boton a su funcion
            self.Bind(wx.EVT_BUTTON, self.moverCelda, i)
            i.Bind(wx.EVT_KEY_DOWN, self.moverVacio) 
        self.Bind(wx.EVT_KEY_DOWN, self.moverVacio)
        self.Bind(wx.EVT_BUTTON, self.remover, self.s)
        self.Bind(wx.EVT_BUTTON, self.Numeros, self.numero)
        self.Bind(wx.EVT_BUTTON, self.CargarImg, self.image)
 
    def CargarImg(self, event): #Cargamos la imagen que deseamos
        dlg = wx.FileDialog(self, "Abrir imagen")
        dlg.Centre()
        wildcard = "JPG files (.jpg)|*.jpg|"   \
                   "PNG (.png)|*.png|" \
                   "BMP (.bmp)|*.bmp"
        dlg.SetWildcard(wildcard) #Formatos aceptados
        if dlg.ShowModal() == wx.ID_OK:
            self.usoImg = True
            self.DescomponerImagen(dlg.GetPaths()[0])   
        dlg.Destroy()
 
    def ColocarImagenes(self, trozos): #Colocamos las imagenes en botones
        vacio = im.new("RGB", (40,40)) #Creamos una imagen vacia de 40X40
        vaciod = id.Draw(vacio)
        vaciod.rectangle((5,5,35,35), fill=(242,242,242)) #Le pintamos un rectangulo blanco en el interior
        self.imagen = [wx.EmptyImage(trozos[i].size[0], trozos[i].size[1]) for i in range(16)] #Creamos imagenes vacias
        for i in range(15):
            self.imagen[i].SetData(trozos[i].convert("RGB").tostring()) #Isertamos la informacion en las imagenes vacias
        self.imagen[15].SetData(vacio.tostring())
        self.posiciones = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", ""]
        self.hecho.SetLabel("")
        self.tiempo.SetLabel("")
        for i in range(len(self.posiciones)):
            self.botones[i].SetLabel("")
            self.botones[i].SetBitmapLabel(self.imagen[i].ConvertToBitmap())
 
    def Comprobar(self):
        if self.posiciones == ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", ""]:
            self.hecho.SetLabel("¡Bravo!")
            self.tiempo.SetLabel("%is"%(time.time()-self.inicio))
 
    def DescomponerImagen(self, img): #Descomponemos la imagen en 16 trozos
        image = im.open(img)  
        if image.size >= (160,160):
            image = image.resize((160,160)) #La escalamos a 160X160
            trozos = []
            for r in range(4): #Recortamos trozos de 40X40 y los guardamos
                for c in range(4):
                    trozos.append(image.crop((0+40*c, 0+40*r, 40+40*c, 40+40*r)))
            self.ColocarImagenes(trozos)
        else:
            self.hecho.SetLabel("Imágenes de")
            self.tiempo.SetLabel("160X160")
 
    #Mover celda cuando usamos el raton
    def moverCelda(self, evt):
        btnPos = abs(evt.GetId()-self.botones[0].GetId()) #Obtenemo el boton que se pulso
        label = self.posiciones[btnPos] #Obtenemos el numero que le corresponde
        lugVacio = 0 
        lugPulsado = 0
        while self.posiciones[lugVacio] != "": #Averiguamos donde esta la celda movible
            lugVacio += 1
        while self.posiciones[lugPulsado] != label: #Averiguamos donde esta el pulsado
            lugPulsado += 1
        if (lugVacio-lugPulsado == 1) or (lugVacio-lugPulsado == -1) or (lugVacio-lugPulsado == 4) or (lugVacio-lugPulsado == -4): #Si el pulsado esta a los lados o arriba o abajo
            self.posiciones[lugPulsado] = "" #Intercambiamos los lugares
            self.posiciones[lugVacio] = label
            self.Recolocar()
        self.Comprobar()
 
    #Mover celda cuando pulsamos una tecla
    def moverVacio(self, event):
        lugVacio = 0
        while self.posiciones[lugVacio] != "":
            lugVacio += 1
        if event.GetKeyCode()==314: #Izquierda
            if (((lugVacio-1)!=11) and ((lugVacio-1)!=7) and ((lugVacio-1)!=3) and ((lugVacio-1)!=-1)):
                self.posiciones[lugVacio] = self.posiciones[lugVacio-1]
                self.posiciones[lugVacio-1] = ""
        elif event.GetKeyCode()==315:#Arriba
            if lugVacio-4 >= 0:
                self.posiciones[lugVacio] = self.posiciones[lugVacio-4]
                self.posiciones[lugVacio-4] = ""
        elif event.GetKeyCode()==316:#Derecha
            if (((lugVacio+1)!=16) and ((lugVacio+1)!=12) and ((lugVacio+1)!=8) and ((lugVacio+1)!=4)):
                self.posiciones[lugVacio] = self.posiciones[lugVacio+1]
                self.posiciones[lugVacio+1] = ""
        elif event.GetKeyCode()==317:#Abajo
            if lugVacio+4 <= 15:
                self.posiciones[lugVacio] = self.posiciones[lugVacio+4]
                self.posiciones[lugVacio+4] = ""
        self.Recolocar()
        self.Comprobar()
 
    def Numeros(self, event): #Funcion para crear el juego solo con numeros
        self.posiciones = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", ""]
        self.usoImg = False
        self.hecho.SetLabel("")
        self.tiempo.SetLabel("")
        for i in range(len(self.posiciones)):
            self.botones[i].SetBitmapLabel(self.BitmapNull.ConvertToBitmap())
            self.botones[i].SetLabel(str(self.posiciones[i]))
 
    def Recolocar(self): #Funcion para recolocar los cuadrados cuando sufran cambios
        for i in range(16):
            if self.usoImg:
                if self.posiciones[i] == "":
                    self.botones[i].SetBitmapLabel(self.imagen[15].ConvertToBitmap()) 
                else:
                    self.botones[i].SetBitmapLabel(self.imagen[int(self.posiciones[i])-1].ConvertToBitmap())
            else:
                self.botones[i].SetLabel(self.posiciones[i])
 
    #Remover todos los elementos y obtener el rompecabezas
    def remover(self, evt): 
        lugar = 15
        for i in range(1000): #Movemos el vacio 1000 veces
            hacia = random.randrange(0, 4) #Para indicar aleatoriamente el lado al que se mueve
            if hacia == 0:#Arriba
                if lugar > 4:
                    basura = self.posiciones[lugar]
                    self.posiciones[lugar] = self.posiciones[lugar-4]
                    self.posiciones[lugar-4] = basura
                    lugar -= 4
            elif hacia == 1:#Izquierda
                if (lugar != 0) and (lugar != 4) and (lugar != 8) and (lugar != 12):
                    basura = self.posiciones[lugar]
                    self.posiciones[lugar] = self.posiciones[lugar-1]
                    self.posiciones[lugar-1] = basura
                    lugar -= 1
            elif hacia == 2:#Abajo
                if lugar < 11:
                    basura = self.posiciones[lugar]
                    self.posiciones[lugar] = self.posiciones[lugar+4]
                    self.posiciones[lugar+4] = basura
                    lugar += 4
            else:#Derecha
                if (lugar != 3) and (lugar != 7) and (lugar != 11) and (lugar != 15):
                    basura = self.posiciones[lugar]
                    self.posiciones[lugar] = self.posiciones[lugar+1]
                    self.posiciones[lugar+1] = basura
                    lugar += 1
        self.inicio = time.time() #iniciamos el contador
        self.Recolocar()
 
#mostramos el frame que contiene la interfaz
class App(wx.App):
    def OnInit(self):
            frame = Frame()
            frame.Show()
            self.SetTopWindow(frame)
            return True
 
#Iniciamos si no hay errores
if __name__ == '__main__':
    app = App()
    app.MainLoop()


Cualquier duda pregunten en este mismo tema.
Intentaré ir creando ejecutables para los que no tengan Python.

[Imagen: moderadorglobal.png]
25-09-2011 03:44 AM
Buscar Citar
-Gosw- Sin conexión
Administrador
*******

Mensajes: 1.984
Registro en: Jul 2010
Facebook Twitter YouTube
Gracias dados: 62
Gracias recibidos: 93
Mensaje: #2
RE: Rompecabezas 2.0
  • Compartir en Delicious
  • Compartir en Digg
  • Compartir en Linkedin
  • Compartir en MySpace
  • Compartir en Technorati
  • Compartir en Tuenti
Interesante, me gusta como quedo. Ira a la portada de Cibernodo (que hace mucho tiempo que no se actualiza. :S).

[Imagen: administradorq.png]
HTC Desire SLCD: S-OFF, cm7/r2 hboot, CyanogenMod Kernel, CyanogenMod NB 262
Samsung Galaxy S i9000: Chainfire Kernel (CF-ROOT), Value Pack ROM 2.3.6 JVU
SE Xperia x10i: Unlocked Bootloader, FXP052 Kernel, CyanogenMod 7.2.0 FXP052
Motorola Dext MB200: CyanogenMod 7.1 RC1
LG Optimus One P500: Stock ROM 2.3.3
ZTE Racer: Stock
25-09-2011 12:07 PM
WWW Buscar Citar
Sifaw En línea
Moderador Global
******

Mensajes: 350
Registro en: Jul 2010
MySpace YouTube
Gracias dados: 25
Gracias recibidos: 32
Mensaje: #3
RE: Rompecabezas 2.0
  • Compartir en Delicious
  • Compartir en Digg
  • Compartir en Linkedin
  • Compartir en MySpace
  • Compartir en Technorati
  • Compartir en Tuenti
Gracias Gosw, tengo que modificarlo algo para windows a ver si consigo los ejecutables jeje

PD: Tengo otro par de código que intentaré ir subiendo en breve.

[Imagen: moderadorglobal.png]
(Este mensaje fue modificado por última vez en: 26-09-2011 01:38 AM por Sifaw.)
26-09-2011 01:37 AM
Buscar Citar
.:WindHack:. Sin conexión
Administrador
*******

Mensajes: 841
Registro en: Jul 2010
Facebook Google+ Twitter YouTube
Gracias dados: 62
Gracias recibidos: 60
Mensaje: #4
RE: Rompecabezas 2.0
  • Compartir en Delicious
  • Compartir en Digg
  • Compartir en Linkedin
  • Compartir en MySpace
  • Compartir en Technorati
  • Compartir en Tuenti
¡Está genial!

Me agradó mucho, muy buen trabajo, jeje.

[Imagen: WindSig.php]
[Imagen: DaW-User.png]
[Imagen: administradorq.png]
"The only thing they can't take from us are our minds."
10-10-2011 02:58 AM
WWW Buscar Citar




Usuario(s) navegando en este tema: 1 invitado(s)