diff options
author | Pablo Moleri <pmoleri@PABLOMOLERI-PC.(none)> | 2009-08-28 04:37:26 (GMT) |
---|---|---|
committer | Pablo Moleri <pmoleri@PABLOMOLERI-PC.(none)> | 2009-08-28 04:37:26 (GMT) |
commit | f8c647e53f49f1cc96c55814eb29d8c32e71c3f6 (patch) | |
tree | 59a31a3aa028e178c4d4e8902b3ec4babcd56c99 | |
parent | 6678b5b4b0b1115089e6280ce329b37389da126a (diff) |
Versión final para ceibalJAM 4
Se agregan los 5 pasos del taller y un archivo que muestra que cambios hay.
-rw-r--r-- | BatallaNaval.activity/BatallaNaval.py | 249 | ||||
-rw-r--r-- | BatallaNaval.activity/BatallaNavalActivity.py | 28 | ||||
-rw-r--r-- | BatallaNaval.activity/Collaboration.py | 21 | ||||
-rw-r--r-- | BatallaNaval.activity/activity/activity.info | 2 | ||||
-rw-r--r-- | BatallaNaval.activity/activity/batalla-naval-icon.svg | 25 | ||||
-rw-r--r-- | taller/BatallaNaval-1.py | 151 | ||||
-rw-r--r-- | taller/BatallaNaval-2.py | 224 | ||||
-rw-r--r-- | taller/BatallaNaval-3.py | 228 | ||||
-rw-r--r-- | taller/BatallaNaval-4.py | 284 | ||||
-rw-r--r-- | taller/BatallaNaval-5.py | 325 | ||||
-rw-r--r-- | taller/pasos.txt | 55 |
11 files changed, 1437 insertions, 155 deletions
diff --git a/BatallaNaval.activity/BatallaNaval.py b/BatallaNaval.activity/BatallaNaval.py index ceee1ee..ea99a1d 100644 --- a/BatallaNaval.activity/BatallaNaval.py +++ b/BatallaNaval.activity/BatallaNaval.py @@ -7,14 +7,11 @@ import gtk import logging import random -try: - from sugar.activity.activity import Activity, ActivityToolbox -except: - pass - +# Permite definir un Log que filtra mensajes a la salida estándar dependiendo de nivel elegido. log = logging.getLogger('BatallaNaval') log.setLevel(logging.DEBUG) +# Diccionario que contiene el nombre y largo de cada barco lista_barcos = { "Portaaviones": 5, "Acorazado": 4, @@ -23,6 +20,8 @@ lista_barcos = { "Destructor": 2} class PanelPrincipal(gtk.HBox): + ''' Panel Principal es un Widget que contiene ambos tableros y se encarga + de crear los barcos en posiciones al azar para cada tablero ''' def __init__(self): gtk.HBox.__init__(self, True) @@ -34,23 +33,25 @@ class PanelPrincipal(gtk.HBox): barcos_propios = crear_barcos() for barco in barcos_propios: self.tablero1.agregar_barco(barco, True) - log.debug("barco:%s, %s (%s, %s)" % (barco.name, barco.orientacion, barco.pos[0], barco.pos[1])) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) log.debug("Barcos Enemigos") self.barcos_enemigos = crear_barcos() for barco in self.barcos_enemigos: self.tablero2.agregar_barco(barco, False) - log.debug("barco:%s, %s (%s, %s)" % (barco.name, barco.orientacion, barco.pos[0], barco.pos[1])) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) self.add(self.tablero1) self.add(self.tablero2) - self.show_all() - self.jugadas_enemigas = [] # Lleva un registro de las jugadas hechas por la computadora + + self.show_all() # Carga barcos remotos def cargar_barcos(self, barcos): + ''' Esta función es llamada cuando me conecto en red con otro usuario, recibo + una tupla con los datos de los barcos enemigos. ''' log.debug("Cargando barcos enemigos") self.tablero2.barcos = [] for dato in barcos: @@ -64,19 +65,25 @@ class PanelPrincipal(gtk.HBox): self.tablero2.agregar_barco(barco, False) log.debug("barco:%s, %s (%s, %s)" % (barco.name, barco.orientacion, barco.pos[0], barco.pos[1])) - # Cuando el enemigo juega sobre mi tablero, hago la judada y le respondo si fue tocado def jugada_red(self, x, y): + ''' Callback de colaboración para la señal Play. + Cuando el enemigo juega sobre mi tablero, reflejo la judada y le respondo si fue tocado ''' return self.tablero1.jugada(self.tablero1.filas[x-1][y-1]) - # Cuando yo mismo hice una jugada sobre el tablero enemigo, si hay colaboración actualizo según la respuesta def jugada_hecha(self, x, y): - # Si hay colaboración, indico al oponente la jugada que hice - if self.colaboracion: + ''' Cuando yo mismo hice una jugada sobre el tablero enemigo + si la actividad está compartida indico al oponente la jugada que hice, + en caso contrario me simulo una jugada random del enemigo. ''' + + # Si estoy compartiendo con alguien, indico al oponente la jugada que hice + if self.colaboracion and self.colaboracion.entered: + log.debug("Señalo jugada a los participantes") self.colaboracion.Play(x, y) return # Sinó, la computadora hace una jugada al azar sobre el tablero propio if len(self.jugadas_enemigas) == 100: + log.error("Alcanzó las 100 jugadas.") return ok = False @@ -86,14 +93,64 @@ class PanelPrincipal(gtk.HBox): ok = True self.jugadas_enemigas.append((x, y)) - self.tablero1.filas[x-1][y-1].clicked() + self.tablero1.jugada(self.tablero1.filas[x-1][y-1]) + +class Barco(gtk.Frame): + ''' Esta clase representa un barco, tiene nombre, largo, orientación y posición. + Como es un widget puede ser mostrado en la pantalla y tiene un texto con el nombre del barco ''' + horizontal = 'H' + vertical = 'V' + + def __init__(self, nombre, largo, pos, orientacion = horizontal): + gtk.Frame.__init__(self) + self.nombre = nombre + self.largo = largo + self.pos = pos + + # Agrega una etiqueta con el nombre del barco + self.label = gtk.Label(nombre) + self.add(self.label) + + self.set_orientacion(orientacion) # Graba la orientación y ajusta la etiqueta a dicha orientación. + + def set_orientacion(self, orientacion): + ''' Graba la orientación y ajusta la etiqueta a dicha orientación. ''' + self.orientacion = orientacion + if self.orientacion == Barco.horizontal: + self.label.set_angle(0) + else: + self.label.set_angle(90) + + def get_inicio(self): + return self.pos + + def get_fin(self): + if self.orientacion == Barco.horizontal: + return self.pos[0], self.pos[1] + self.largo - 1 + else: + return self.pos[0] + self.largo - 1, self.pos[1] + + def get_filas(self): + return range(self.get_inicio()[0], self.get_fin()[0]+1) + + def get_cols(self): + return range(self.get_inicio()[1], self.get_fin()[1]+1) + + def get_celdas(self): + return [(f, c) for f in self.get_filas() for c in self.get_cols()] + def crear_barcos(): - barcos = [Barco(b[0], b[1], None) for b in lista_barcos.items()] + ''' Parte de la lista_barcos para crear un conjunto de barcos en posiciones al azar. ''' - celdas_ocupadas = [] + # Convierte la lista de definición en una lista de objetos Barco sin posición definida + barcos = [Barco(nombre, largo, None) for nombre, largo in lista_barcos.items()] + + celdas_ocupadas = [] # Llevo una lista de las celdas ya ocupadas por los barcos for barco in barcos: + # Para cada barco me mantengo en un loop hasta que encuentre coordenadas al azar que no + # intersecten con ningún barco ya ubicado. ok = False while not ok: # Determino al azar si es horizontal o vertical @@ -107,41 +164,46 @@ def crear_barcos(): barco.set_orientacion(Barco.vertical) posx = random.randint(1, 10-barco.largo+1) posy = random.randint(1, 10) - barco.pos = (posx, posy) - ok = True - for celda in barco.get_celdas(): - if celda in celdas_ocupadas: - ok = False - if ok: + + # Verifico si la posición elegida no intersecciona con las celdas ya ocupadas por otros barcos + # Convierto las listas en sets y aplico intersección + interseccion = set(barco.get_celdas()) & set(celdas_ocupadas) + if not interseccion: + ok = True celdas_ocupadas.extend(barco.get_celdas()) return barcos class Celda(gtk.Button): - - def __init__(self, pos, clicked_cb): + ''' Esta clase representa una celda del tablero, como es subclase de button se le puede + conectar la señal "clicked". + También presenta funciones para ocultar y colorearse dependiendo de si tocó un barco o dió agua. ''' + + def __init__(self, pos): gtk.Button.__init__(self) self.pos = pos - - self.connect("clicked", clicked_cb) def ocultar(self): + ''' Oculta permanentemente la celda, de modo que show_all no la muestre ''' self.set_no_show_all(True) self.hide() - def tocado(self): - color = gtk.gdk.Color(65535,65535/2,0) + def colorear(self, color): self.modify_bg(gtk.STATE_NORMAL, color) self.modify_bg(gtk.STATE_PRELIGHT, color) self.show() # Por si está oculta atrás de un barco + + def tocado(self): + self.colorear( gtk.gdk.Color(65535,65535/2,0) ) def agua(self): - color = gtk.gdk.Color(0,0,65535/2) - self.modify_bg(gtk.STATE_NORMAL, color) - self.modify_bg(gtk.STATE_PRELIGHT, color) - self.show() # Por si está oculta atrás de un barco - + self.colorear( gtk.gdk.Color(0,0,65535/2) ) + + class Tablero(gtk.Frame): + ''' Define un tablero, el tablero está definido con una tabla exterior que permite poner + los títulos de las filas y las columnas (que a su vez son tablas) y una tabla interior + que tiene todas las celdas del tablero (tabla_celdas). ''' def __init__(self, llamada_jugada_hecha): gtk.Frame.__init__(self) @@ -159,62 +221,65 @@ class Tablero(gtk.Frame): label = gtk.Label(char) tabla_letras.attach(label, 0, 1, i-1, i) - # Se hace una tabla para ubicar las letras, los números y el tablero + # Se hace una tabla para ubicar las letras, los números y la tabla de celdas self.tabla = gtk.Table(2, 2, False) self.add(self.tabla) + # Opciones para las tablas de letras y números. opciones = gtk.SHRINK|gtk.FILL - label = gtk.Label(" ") + label = gtk.Label(" ") # Para dar más espacio a la columna de letras self.tabla.attach(label, 0, 1, 0, 1, xoptions=opciones, yoptions=opciones) - self.tabla.attach(tabla_numeros, 1, 2, 0, 1, xoptions=opciones, yoptions=opciones) self.tabla.attach(tabla_letras, 0, 1, 1, 2, xoptions=opciones, yoptions=opciones) - self.filas = [] - # El tablero es otra tabla self.tabla_celdas = gtk.Table(10, 10, True) self.tabla.attach(self.tabla_celdas, 1, 2, 1, 2, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL|gtk.EXPAND) - + + self.filas = [] + # Creo todas las celdas, las guardo en la colección de filas y las adjunto al tablero for i in range(1, 11): - row = [] + fila = [] for j in range(1, 11): - left = j - 1 - top = i - 1 - celda = Celda((i, j), self.celda_clickeada) - row.append(celda) - self.tabla_celdas.attach(celda, left, j, top, i) - #print label.get_text() - self.filas.append(row) + celda = Celda((i, j)) + celda.connect("clicked", self.celda_clickeada) + fila.append(celda) + self.tabla_celdas.attach(celda, j-1, j, i-1, i) + self.filas.append(fila) - self.barcos = [] # Los barcos que hay en el tablero + # Los barcos que hay en el tablero + self.barcos = [] + # Callback para cuando el jugador hace una jugada en el tablero self.llamada_jugada_hecha = llamada_jugada_hecha - def agregar_barco(self, barco, show): + def agregar_barco(self, barco, mostrar): + ''' Agrega un barco al tablero, si mostrar=True sustituye las celdas que ocupa por el barco. ''' self.barcos.append(barco) - if show: - for i in barco.get_filas(): - for j in barco.get_cols(): - self.ocultar_celda(i, j) - izq = barco.get_inicio()[1]-1 - der = barco.get_fin()[1] - arr = barco.get_inicio()[0]-1 - aba = barco.get_fin()[0] - self.tabla_celdas.attach(barco, izq, der, arr, aba) - + if mostrar: + # Oculta las celdas que ocupa el barco + for i, j in barco.get_celdas(): + self.ocultar_celda(i, j) + + # Obtiene los extremos del barco y lo adjunta a la tabla + arr, izq = barco.get_inicio() + aba, der = barco.get_fin() + self.tabla_celdas.attach(barco, izq-1, der, arr-1, aba) + def ocultar_celda(self, i, j): self.filas[i-1][j-1].ocultar() def celda_clickeada(self, celda): - # Cuando hay definido un callback de jugadas hechas, significa que es el tablero en el que puedo jugar + ''' Cuando hay definido un callback de jugadas hechas, significa que en este tablero puedo jugar. + Realizo la jugada y notifico al callback ''' if self.llamada_jugada_hecha: # Este es el callback para cuando clickean una celda self.jugada(celda) self.llamada_jugada_hecha(celda.pos[0], celda.pos[1]) def jugada(self, celda): + ''' verifica si la jugada da en algún barco o en el agua y manda la señal correcta a la celda ''' tocado = False for barco in self.barcos: if celda.pos in barco.get_celdas(): @@ -222,59 +287,16 @@ class Tablero(gtk.Frame): celda.tocado() if not tocado: celda.agua() - + + log.debug("Pos:%s Tocado:%s", str(celda.pos), tocado) return tocado -class Barco(gtk.Frame): - - horizontal = 'H' - vertical = 'V' - - def __init__(self, nombre, largo, pos, orientacion = horizontal): - #gtk.Label.__init__(self, nombre) - gtk.Frame.__init__(self) - self.nombre = nombre - self.largo = largo - self.pos = pos - self.label = gtk.Label(nombre) - self.add(self.label) - self.set_orientacion(orientacion) - - def set_orientacion(self, orientacion): - self.orientacion = orientacion - if self.orientacion == Barco.horizontal: - self.label.set_angle(0) - else: - self.label.set_angle(90) - - def get_inicio(self): - return self.pos - - def get_fin(self): - if self.orientacion == Barco.horizontal: - return self.pos[0], self.pos[1] + self.largo - 1 - else: - return self.pos[0] + self.largo - 1, self.pos[1] - - def get_filas(self): - return range(self.get_inicio()[0], self.get_fin()[0]+1) - - def get_cols(self): - return range(self.get_inicio()[1], self.get_fin()[1]+1) - - def get_celdas(self): - return [(f, c) for f in self.get_filas() for c in self.get_cols()] - -# Esta función es el punto de entrada común para sugar y modo standalone -# standalone es un boolean que indica si es Standalone o se ejecuta desde Sugar def init(standalone, ventana_principal): - + ''' Esta función es el punto de entrada común para sugar y modo standalone + standalone es un boolean que indica si es Standalone o se ejecuta desde Sugar ''' panel_principal = PanelPrincipal() if not standalone: - toolbox = ActivityToolbox(ventana_principal) - ventana_principal.set_toolbox(toolbox) - toolbox.show() ventana_principal.set_canvas(panel_principal) # Colaboración @@ -285,24 +307,19 @@ def init(standalone, ventana_principal): panel_principal.cargar_barcos, # World panel_principal.jugada_red, # Play panel_principal.tablero1.barcos)# Mis barcos - else: ventana_principal.add(panel_principal) panel_principal.colaboracion = None - + ventana_principal.set_title("Batalla Naval - ceibalJAM") ventana_principal.connect("destroy", lambda wid: gtk.main_quit()) ventana_principal.connect("delete_event", lambda a1, a2: gtk.main_quit()) ventana_principal.show() -# Este es el procedimiento principal en modo standalone -def main(): +# Este código se ejecuta sólo cuando se ejecuta directo ese módulo (no cuando se importa desde sugar) +if __name__ == "__main__": + log.addHandler(logging.StreamHandler()) ventana_principal = gtk.Window(gtk.WINDOW_TOPLEVEL) init(True, ventana_principal) gtk.main() - return 0 - -# Este código se ejecuta sólo cuando se ejecuta directo ese módulo (no cuando se importa desde sugar) -if __name__ == "__main__": - main() diff --git a/BatallaNaval.activity/BatallaNavalActivity.py b/BatallaNaval.activity/BatallaNavalActivity.py index 1a0f153..2e8db11 100644 --- a/BatallaNaval.activity/BatallaNavalActivity.py +++ b/BatallaNaval.activity/BatallaNavalActivity.py @@ -1,31 +1,25 @@ +# -*- coding: cp1252 -*- + from sugar.activity.activity import Activity, ActivityToolbox import BatallaNaval from Collaboration import CollaborationWrapper class BatallaNavalActivity(Activity): + ''' Clase llamada por sugar cuando se ejecuta la actividad. + El nombre de esta clase está señalada en el archivo activity/activity.info ''' + def __init__(self, handle): Activity.__init__(self, handle) - self.connect('destroy', self._cleanup_cb) self.gamename = 'BatallaNaval' - self.set_title("Batalla Naval") - - # connect to the in/out events - self.connect('focus_in_event', self._focus_in) - self.connect('focus_out_event', self._focus_out) + # Crea la barra de herramientas básica de Sugar + toolbox = ActivityToolbox(self) + self.set_toolbox(toolbox) + toolbox.show() + + # Crea una instancia de Colaboración por si se quiere compartir la actividad self.colaboracion = CollaborationWrapper(self) # The activity is a subclass of Window, so it passses itself to the init function BatallaNaval.init(False, self) - # It never returns, gtk.main() - - def _cleanup_cb(self, data=None): - return - - # We could use these methods to conserve power by having the activity stop processing when it is in the background. - def _focus_in(self, event, data=None): - return - - def _focus_out(self, event, data=None): - return diff --git a/BatallaNaval.activity/Collaboration.py b/BatallaNaval.activity/Collaboration.py index 5d5d79c..38ddda1 100644 --- a/BatallaNaval.activity/Collaboration.py +++ b/BatallaNaval.activity/Collaboration.py @@ -29,11 +29,19 @@ except: from sugar.presence.tubeconn import TubeConnection as SugarTubeConnection from dbus.gobject_service import ExportedGObject +''' En todas las actividades colaborativas Sugar nos matiene al tanto cuando entra o sale un Jugador + Para que todos conozcan el estado de la Actividad se maneja la técnica Hello World, + donde cuando un participante entra se emite una señal Hello que llega a todos los participantes + y los participantes responden directamente al nuevo el método "World", mediante la cual + se le pasa el estado actual de la actividad. + Luego las actualizaciones se dan con señal Play, mediante la cual cada participante comunica al + resto su jugada. -# Todas las actividades colaborativas de sugar deben tener implentadas las señales "Hello" y "World" -# Cuando alguien entra a la colaboración sugar automáticamente emite la señal Hello -# Este wrapper automáticamente responde con la señal World, que sirve para informarle al nuevo -# participante el estado actual. + En resumen en este módulo se encapsula la lógica de la "colaboración" con el siguiente funcionamiento: + - Cuando alguien entra a la colaboración se emite la señal Hello + - Quien recibe la señal automáticamente responde con la señal World + - Cada vez que alguien juega emite la señal Play +''' SERVICE = "org.ceibaljam.BatallaNaval" IFACE = SERVICE @@ -111,7 +119,7 @@ class CollaborationWrapper(ExportedGObject): for buddy in self.activity._shared_activity.get_joined_buddies(): logger.debug('Buddy %s is already in the activity', buddy.props.nick) - + def participant_change_cb(self, added, removed): logger.debug('Tube: Added participants: %r', added) logger.debug('Tube: Removed participants: %r', removed) @@ -126,8 +134,7 @@ class CollaborationWrapper(ExportedGObject): logger.debug('Buddy %s was removed' % buddy.props.nick) if not self.entered: if self.is_initiator: - logger.debug("I'm initiating the tube, will " - "watch for hellos.") + logger.debug("I'm initiating the tube, will watch for hellos.") self.add_hello_handler() else: logger.debug('Hello, everyone! What did I miss?') diff --git a/BatallaNaval.activity/activity/activity.info b/BatallaNaval.activity/activity/activity.info index 7cb17e8..fa8b0b2 100644 --- a/BatallaNaval.activity/activity/activity.info +++ b/BatallaNaval.activity/activity/activity.info @@ -3,7 +3,7 @@ name = BatallaNaval bundle_id = org.ceibaljam.BatallaNaval class = BatallaNavalActivity.BatallaNavalActivity icon = batalla-naval-icon -activity_version = 2 +activity_version = 1 host_version = 1 show_launcher = no license = GPLv2+ diff --git a/BatallaNaval.activity/activity/batalla-naval-icon.svg b/BatallaNaval.activity/activity/batalla-naval-icon.svg index 432bd56..3c288f8 100644 --- a/BatallaNaval.activity/activity/batalla-naval-icon.svg +++ b/BatallaNaval.activity/activity/batalla-naval-icon.svg @@ -12,8 +12,7 @@ height="55" id="svg4502" style="display:inline"> - <defs - id="defs4504" /> + <defs id="defs4504" /> <g transform="translate(-0.2226721,0.2016908)" @@ -21,21 +20,20 @@ style="opacity:0.5"> <g transform="translate(0,-1.8115502)" - id="barras_horizontales"> + id="barras_horizontales" + fill="&fill_color;"> <rect width="51.214573" height="3.7854252" x="2.4493928" y="22.482435" - id="rect2398" - style="opacity:1;fill:&stroke_color;fill-opacity:1;" /> + id="rect2398" /> <rect width="51.214573" height="3.7854252" x="2.4493928" y="39.06778" - id="rect2404" - style="opacity:1;fill:&stroke_color;fill-opacity:1;" /> + id="rect2404" /> </g> <use transform="matrix(0,0.9057751,-1.1040268,0,62.122828,5.4432283)" @@ -48,21 +46,20 @@ </g> <g id="terron"> <path - d="M 38.822128,44.108722 C 38.822128,44.108722 38.445765,44.108722 38.092819,44.108722 C 38.092819,42.747378 38.097001,38.459638 38.097001,37.325183 C 38.097001,37.325183 38.097001,37.325183 38.097001,37.323527 L 38.097001,24.562988 L 38.089474,16.811436 C 38.086128,15.932855 37.361837,15.224857 36.48031,15.228997 C 36.052928,15.228997 35.648965,15.396267 35.347873,15.696856 C 35.045946,15.999101 34.882019,16.399058 34.883691,16.823857 C 34.883691,16.863604 34.885364,19.358576 34.887873,21.45773 L 22.071438,21.45773 C 20.330965,21.45773 18.920019,22.854682 18.920019,24.575409 L 18.920019,26.300276 L 13.265364,26.303588 C 12.377982,26.309384 11.663728,27.024008 11.667074,27.896793 C 11.668746,28.321592 11.837691,28.719892 12.141291,29.017998 C 12.446565,29.316931 12.850528,29.479232 13.277073,29.477576 C 13.326419,29.477576 16.696965,29.47592 18.919182,29.474263 L 18.919182,37.014658 C 18.919182,37.02625 18.915837,37.036187 18.915837,37.046952 C 18.915837,37.104917 18.919182,42.545329 18.919182,44.107894 C 18.567073,44.107894 18.189873,44.107894 18.189873,44.107894 C 17.285765,44.125284 16.584055,44.849844 16.59911,45.724285 C 16.61751,46.601209 17.351837,47.296787 18.234201,47.279397 L 20.537546,47.277741 C 21.439146,47.26118 22.145037,46.535792 22.126637,45.661352 L 22.123292,40.442034 L 34.887873,40.442034 L 34.882019,45.661352 C 34.865292,46.53662 35.571182,47.262009 36.472783,47.277741 L 38.774455,47.279397 C 39.661,47.296787 40.393656,46.601209 40.411219,45.724285 C 40.428782,44.849844 39.723728,44.126112 38.822128,44.108722 z M 30.604855,25.673428 C 31.197837,25.590621 31.748164,25.999687 31.832637,26.587615 C 31.917946,27.174716 31.50311,27.720413 30.910128,27.804876 C 30.3138,27.887683 29.76431,27.476962 29.680673,26.890689 C 29.595365,26.301932 30.010201,25.756235 30.604855,25.673428 z M 24.950201,26.467545 C 25.542346,26.384739 26.09351,26.793805 26.177147,27.381734 C 26.262455,27.97049 25.847619,28.513703 25.255473,28.598995 C 24.659146,28.683458 24.109656,28.272735 24.026019,27.684807 C 23.941546,27.096049 24.353874,26.552009 24.950201,26.467545 z M 26.384565,35.548148 C 25.364201,34.827728 23.744165,32.814693 24.326273,31.447552 C 24.532019,30.966443 24.984492,31.265376 25.47711,31.509657 C 26.653037,32.10421 28.05311,32.180392 29.308492,31.805277 C 29.946637,31.614821 30.491946,31.305951 31.012165,30.893574 C 31.328309,30.641012 32.191437,29.636565 32.666491,30.090346 C 33.037837,30.445588 33.101401,30.886121 33.101401,30.890261 C 33.634164,34.258844 29.418891,37.688706 26.384565,35.548148 z" id="cuerpo" - style="fill:&stroke_color;fill-opacity:1;overflow:visible" /> + d="M 38.822128,44.108722 C 38.822128,44.108722 38.445765,44.108722 38.092819,44.108722 C 38.092819,42.747378 38.097001,38.459638 38.097001,37.325183 C 38.097001,37.325183 38.097001,37.325183 38.097001,37.323527 L 38.097001,24.562988 L 38.089474,16.811436 C 38.086128,15.932855 37.361837,15.224857 36.48031,15.228997 C 36.052928,15.228997 35.648965,15.396267 35.347873,15.696856 C 35.045946,15.999101 34.882019,16.399058 34.883691,16.823857 C 34.883691,16.863604 34.885364,19.358576 34.887873,21.45773 L 22.071438,21.45773 C 20.330965,21.45773 18.920019,22.854682 18.920019,24.575409 L 18.920019,26.300276 L 13.265364,26.303588 C 12.377982,26.309384 11.663728,27.024008 11.667074,27.896793 C 11.668746,28.321592 11.837691,28.719892 12.141291,29.017998 C 12.446565,29.316931 12.850528,29.479232 13.277073,29.477576 C 13.326419,29.477576 16.696965,29.47592 18.919182,29.474263 L 18.919182,37.014658 C 18.919182,37.02625 18.915837,37.036187 18.915837,37.046952 C 18.915837,37.104917 18.919182,42.545329 18.919182,44.107894 C 18.567073,44.107894 18.189873,44.107894 18.189873,44.107894 C 17.285765,44.125284 16.584055,44.849844 16.59911,45.724285 C 16.61751,46.601209 17.351837,47.296787 18.234201,47.279397 L 20.537546,47.277741 C 21.439146,47.26118 22.145037,46.535792 22.126637,45.661352 L 22.123292,40.442034 L 34.887873,40.442034 L 34.882019,45.661352 C 34.865292,46.53662 35.571182,47.262009 36.472783,47.277741 L 38.774455,47.279397 C 39.661,47.296787 40.393656,46.601209 40.411219,45.724285 C 40.428782,44.849844 39.723728,44.126112 38.822128,44.108722 z M 30.604855,25.673428 C 31.197837,25.590621 31.748164,25.999687 31.832637,26.587615 C 31.917946,27.174716 31.50311,27.720413 30.910128,27.804876 C 30.3138,27.887683 29.76431,27.476962 29.680673,26.890689 C 29.595365,26.301932 30.010201,25.756235 30.604855,25.673428 z M 24.950201,26.467545 C 25.542346,26.384739 26.09351,26.793805 26.177147,27.381734 C 26.262455,27.97049 25.847619,28.513703 25.255473,28.598995 C 24.659146,28.683458 24.109656,28.272735 24.026019,27.684807 C 23.941546,27.096049 24.353874,26.552009 24.950201,26.467545 z M 26.384565,35.548148 C 25.364201,34.827728 23.744165,32.814693 24.326273,31.447552 C 24.532019,30.966443 24.984492,31.265376 25.47711,31.509657 C 26.653037,32.10421 28.05311,32.180392 29.308492,31.805277 C 29.946637,31.614821 30.491946,31.305951 31.012165,30.893574 C 31.328309,30.641012 32.191437,29.636565 32.666491,30.090346 C 33.037837,30.445588 33.101401,30.886121 33.101401,30.890261 C 33.634164,34.258844 29.418891,37.688706 26.384565,35.548148 z" + fill="&stroke_color;"/> <path - d="M 17.233073,11.642631 C 18.971874,8.6971904 24.424965,8.6756607 25.411873,12.233044 C 25.743073,13.428775 25.717147,16.000757 24.39151,16.697991 C 23.925655,16.943099 23.764237,16.42804 23.540092,15.929543 C 23.003146,14.736296 21.969401,13.79975 20.755837,13.307049 C 20.139437,13.055317 19.519691,12.950152 18.853946,12.946839 C 18.446637,12.943527 17.137728,13.184495 17.060783,12.532805 C 17.000564,12.027683 17.233073,11.644287 17.233073,11.642631 z" id="pelo_oscuro" - style="fill:&stroke_color;fill-opacity:1;overflow:visible" /> + d="M 17.233073,11.642631 C 18.971874,8.6971904 24.424965,8.6756607 25.411873,12.233044 C 25.743073,13.428775 25.717147,16.000757 24.39151,16.697991 C 23.925655,16.943099 23.764237,16.42804 23.540092,15.929543 C 23.003146,14.736296 21.969401,13.79975 20.755837,13.307049 C 20.139437,13.055317 19.519691,12.950152 18.853946,12.946839 C 18.446637,12.943527 17.137728,13.184495 17.060783,12.532805 C 17.000564,12.027683 17.233073,11.644287 17.233073,11.642631 z" + fill="&stroke_color;"/> <g transform="matrix(0.8363636,0,0,0.8280687,4.3773279,7.643887)" - id="pelo_claro" - style="fill:&stroke_color;fill-opacity:1;overflow:visible"> + id="pelo_claro"> <path d="M 30.514,13.666 C 25.959,9.955 27.36,0.759 33.675,0.043 C 35.799,-0.198 40.171,0.537 41.006,2.954 C 41.299,3.802 40.382,3.936 39.473,4.18 C 37.299,4.765 35.434,6.261 34.273,8.172 C 33.681,9.144 33.342,10.161 33.16,11.281 C 33.047,11.964 33.108,14.236 31.982,14.194 C 31.107,14.162 30.516,13.668 30.514,13.666 z" id="path2674" - style="fill:&stroke_color;fill-opacity:1" /> + fill="&stroke_color;"/> </g> </g> </svg> diff --git a/taller/BatallaNaval-1.py b/taller/BatallaNaval-1.py new file mode 100644 index 0000000..7591e37 --- /dev/null +++ b/taller/BatallaNaval-1.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +# -*- coding: cp1252 -*- + +import pygtk +pygtk.require('2.0') +import gtk +import logging +import random + +# Permite definir un Log que filtra mensajes a la salida estándar dependiendo de nivel elegido. +log = logging.getLogger('BatallaNaval') +log.setLevel(logging.DEBUG) + +# Diccionario que contiene el nombre y largo de cada barco +lista_barcos = { + "Portaaviones": 5, + "Acorazado": 4, + "Crucero": 3, + "Submarino": 3, + "Destructor": 2} + +class PanelPrincipal(): + ''' Panel Principal es un Widget que contiene ambos tableros y se encarga + de crear los barcos en posiciones al azar para cada tablero ''' + + def __init__(self): + self.tablero = Tablero() + + log.debug("Carga barcos") + barcos = crear_barcos() + for barco in barcos: + self.tablero.agregar_barco(barco) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) + + def mostrar_informacion(self): + for fila in self.tablero.filas: + print "-".join([str(celda.pos) for celda in fila]) + + print "" + + print "barcos:" + for barco in self.tablero.barcos: + str_celdas = "-".join([str(celda) for celda in barco.get_celdas()]) + print "%s : %s" % (barco.nombre, str_celdas) + +class Barco(): + ''' Esta clase representa un barco, tiene nombre, largo, orientación y posición. + Como es un widget puede ser mostrado en la pantalla y tiene un texto con el nombre del barco ''' + + horizontal = 'H' + vertical = 'V' + + def __init__(self, nombre, largo, pos, orientacion = horizontal): + self.nombre = nombre + self.largo = largo + self.pos = pos + self.orientacion = orientacion + + def set_orientacion(self, orientacion): + ''' Graba la orientación ''' + + def get_inicio(self): + return self.pos + + def get_fin(self): + if self.orientacion == Barco.horizontal: + return self.pos[0], self.pos[1] + self.largo - 1 + else: + return self.pos[0] + self.largo - 1, self.pos[1] + + def get_filas(self): + return range(self.get_inicio()[0], self.get_fin()[0]+1) + + def get_cols(self): + return range(self.get_inicio()[1], self.get_fin()[1]+1) + + def get_celdas(self): + return [(f, c) for f in self.get_filas() for c in self.get_cols()] + +def crear_barcos(): + ''' Parte de la lista_barcos para crear un conjunto de barcos en posiciones al azar. ''' + + # Convierte la lista de definición en una lista de objetos Barco sin posición definida + barcos = [Barco(nombre, largo, None) for nombre, largo in lista_barcos.items()] + + celdas_ocupadas = [] # Llevo una lista de las celdas ya ocupadas por los barcos + + for barco in barcos: + # Para cada barco me mantengo en un loop hasta que encuentre coordenadas al azar que no + # intersecten con ningún barco ya ubicado. + ok = False + while not ok: + # Determino al azar si es horizontal o vertical + if random.randint(0, 1): + # Calculo coordenadas random - horizontal + barco.set_orientacion(Barco.horizontal) + posx = random.randint(1, 10) + posy = random.randint(1, 10-barco.largo+1) + else: + # Calculo coordenadas random - vertical + barco.set_orientacion(Barco.vertical) + posx = random.randint(1, 10-barco.largo+1) + posy = random.randint(1, 10) + barco.pos = (posx, posy) + + # Verifico si la posición elegida no intersecciona con las celdas ya ocupadas por otros barcos + # Convierto las listas en sets y aplico intersección + interseccion = set(barco.get_celdas()) & set(celdas_ocupadas) + if not interseccion: + ok = True + celdas_ocupadas.extend(barco.get_celdas()) + return barcos + +class Celda(): + ''' Esta clase representa una celda del tablero. ''' + + def __init__(self, pos): + self.pos = pos + +class Tablero(): + ''' Define un tablero con celdas y una función para agregar barcos ''' + + def __init__(self): + + self.filas = [] + # Creo todas las celdas, las guardo en la colección de filas y las adjunto al tablero + for i in range(1, 11): + fila = [] + for j in range(1, 11): + celda = Celda((i, j)) + fila.append(celda) + self.filas.append(fila) + + # Los barcos que hay en el tablero + self.barcos = [] + + def agregar_barco(self, barco): + ''' Agrega un barco al tablero, si mostrar=True sustituye las celdas que ocupa por el barco. ''' + self.barcos.append(barco) + + def ocultar_celda(self, i, j): + self.filas[i-1][j-1].ocultar() + +def init(): + panel_principal = PanelPrincipal() + panel_principal.mostrar_informacion() + +# Este código se ejecuta sólo cuando se ejecuta directo ese módulo (no cuando se importa desde sugar) +if __name__ == "__main__": + log.addHandler(logging.StreamHandler()) + init() diff --git a/taller/BatallaNaval-2.py b/taller/BatallaNaval-2.py new file mode 100644 index 0000000..365cfdc --- /dev/null +++ b/taller/BatallaNaval-2.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python +# -*- coding: cp1252 -*- + +import pygtk +pygtk.require('2.0') +import gtk +import logging +import random + +# Permite definir un Log que filtra mensajes a la salida estándar dependiendo de nivel elegido. +log = logging.getLogger('BatallaNaval') +log.setLevel(logging.DEBUG) + +# Diccionario que contiene el nombre y largo de cada barco +lista_barcos = { + "Portaaviones": 5, + "Acorazado": 4, + "Crucero": 3, + "Submarino": 3, + "Destructor": 2} + +class PanelPrincipal(gtk.HBox): + ''' Panel Principal es un Widget que contiene ambos tableros y se encarga + de crear los barcos en posiciones al azar para cada tablero ''' + + def __init__(self): + gtk.HBox.__init__(self, True) + + self.tablero1 = Tablero() # tablero propio + self.tablero2 = Tablero() # tablero enemigo + + log.debug("Barcos Propios") + barcos_propios = crear_barcos() + for barco in barcos_propios: + self.tablero1.agregar_barco(barco, True) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) + + log.debug("Barcos Enemigos") + self.barcos_enemigos = crear_barcos() + for barco in self.barcos_enemigos: + self.tablero2.agregar_barco(barco, False) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) + + self.add(self.tablero1) + self.add(self.tablero2) + + self.show_all() + +class Barco(gtk.Frame): + ''' Esta clase representa un barco, tiene nombre, largo, orientación y posición. + Como es un widget puede ser mostrado en la pantalla y tiene un texto con el nombre del barco ''' + + horizontal = 'H' + vertical = 'V' + + def __init__(self, nombre, largo, pos, orientacion = horizontal): + gtk.Frame.__init__(self) + self.nombre = nombre + self.largo = largo + self.pos = pos + + # Agrega una etiqueta con el nombre del barco + self.label = gtk.Label(nombre) + self.add(self.label) + + self.set_orientacion(orientacion) # Graba la orientación y ajusta la etiqueta a dicha orientación. + + def set_orientacion(self, orientacion): + ''' Graba la orientación y ajusta la etiqueta a dicha orientación. ''' + self.orientacion = orientacion + if self.orientacion == Barco.horizontal: + self.label.set_angle(0) + else: + self.label.set_angle(90) + + def get_inicio(self): + return self.pos + + def get_fin(self): + if self.orientacion == Barco.horizontal: + return self.pos[0], self.pos[1] + self.largo - 1 + else: + return self.pos[0] + self.largo - 1, self.pos[1] + + def get_filas(self): + return range(self.get_inicio()[0], self.get_fin()[0]+1) + + def get_cols(self): + return range(self.get_inicio()[1], self.get_fin()[1]+1) + + def get_celdas(self): + return [(f, c) for f in self.get_filas() for c in self.get_cols()] + +def crear_barcos(): + ''' Parte de la lista_barcos para crear un conjunto de barcos en posiciones al azar. ''' + + # Convierte la lista de definición en una lista de objetos Barco sin posición definida + barcos = [Barco(nombre, largo, None) for nombre, largo in lista_barcos.items()] + + celdas_ocupadas = [] # Llevo una lista de las celdas ya ocupadas por los barcos + + for barco in barcos: + # Para cada barco me mantengo en un loop hasta que encuentre coordenadas al azar que no + # intersecten con ningún barco ya ubicado. + ok = False + while not ok: + # Determino al azar si es horizontal o vertical + if random.randint(0, 1): + # Calculo coordenadas random - horizontal + barco.set_orientacion(Barco.horizontal) + posx = random.randint(1, 10) + posy = random.randint(1, 10-barco.largo+1) + else: + # Calculo coordenadas random - vertical + barco.set_orientacion(Barco.vertical) + posx = random.randint(1, 10-barco.largo+1) + posy = random.randint(1, 10) + barco.pos = (posx, posy) + + # Verifico si la posición elegida no intersecciona con las celdas ya ocupadas por otros barcos + # Convierto las listas en sets y aplico intersección + interseccion = set(barco.get_celdas()) & set(celdas_ocupadas) + if not interseccion: + ok = True + celdas_ocupadas.extend(barco.get_celdas()) + return barcos + +class Celda(gtk.Button): + ''' Esta clase representa una celda del tablero. ''' + + def __init__(self, pos): + gtk.Button.__init__(self) + self.pos = pos + + def ocultar(self): + ''' Oculta permanentemente la celda, de modo que show_all no la muestre ''' + self.set_no_show_all(True) + self.hide() + + +class Tablero(gtk.Frame): + ''' Define un tablero, el tablero está definido con una tabla exterior que permite poner + los títulos de las filas y las columnas (que a su vez son tablas) y una tabla interior + que tiene todas las celdas del tablero (tabla_celdas). ''' + + def __init__(self): + gtk.Frame.__init__(self) + + # Números + tabla_numeros = gtk.Table(1, 10, True) + for i in range(1, 11): + label = gtk.Label(str(i)) + tabla_numeros.attach(label, i-1, i, 0, 1) + + # Letras + tabla_letras = gtk.Table(10, 1, True) + for i in range(1, 11): + char = chr( ord('A') + i - 1 ) + label = gtk.Label(char) + tabla_letras.attach(label, 0, 1, i-1, i) + + # Se hace una tabla para ubicar las letras, los números y la tabla de celdas + self.tabla = gtk.Table(2, 2, False) + self.add(self.tabla) + + # Opciones para las tablas de letras y números. + opciones = gtk.SHRINK|gtk.FILL + + label = gtk.Label(" ") # Para dar más espacio a la columna de letras + self.tabla.attach(label, 0, 1, 0, 1, xoptions=opciones, yoptions=opciones) + self.tabla.attach(tabla_numeros, 1, 2, 0, 1, xoptions=opciones, yoptions=opciones) + self.tabla.attach(tabla_letras, 0, 1, 1, 2, xoptions=opciones, yoptions=opciones) + + # El tablero es otra tabla + self.tabla_celdas = gtk.Table(10, 10, True) + self.tabla.attach(self.tabla_celdas, 1, 2, 1, 2, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL|gtk.EXPAND) + + self.filas = [] + # Creo todas las celdas, las guardo en la colección de filas y las adjunto al tablero + for i in range(1, 11): + fila = [] + for j in range(1, 11): + celda = Celda((i, j)) + fila.append(celda) + self.tabla_celdas.attach(celda, j-1, j, i-1, i) + self.filas.append(fila) + + # Los barcos que hay en el tablero + self.barcos = [] + + def agregar_barco(self, barco, mostrar): + ''' Agrega un barco al tablero, si mostrar=True sustituye las celdas que ocupa por el barco. ''' + self.barcos.append(barco) + if mostrar: + # Oculta las celdas que ocupa el barco + for i, j in barco.get_celdas(): + self.ocultar_celda(i, j) + + # Obtiene los extremos del barco y lo adjunta a la tabla + arr, izq = barco.get_inicio() + aba, der = barco.get_fin() + self.tabla_celdas.attach(barco, izq-1, der, arr-1, aba) + + def ocultar_celda(self, i, j): + self.filas[i-1][j-1].ocultar() + +def init(ventana_principal): + ''' Esta función es el punto de entrada común para sugar y modo standalone + standalone es un boolean que indica si es Standalone o se ejecuta desde Sugar ''' + panel_principal = PanelPrincipal() + ventana_principal.add(panel_principal) + + ventana_principal.set_title("Batalla Naval - ceibalJAM") + ventana_principal.connect("destroy", lambda wid: gtk.main_quit()) + ventana_principal.connect("delete_event", lambda a1, a2: gtk.main_quit()) + + ventana_principal.show() + +# Este código se ejecuta sólo cuando se ejecuta directo ese módulo (no cuando se importa desde sugar) +if __name__ == "__main__": + log.addHandler(logging.StreamHandler()) + ventana_principal = gtk.Window(gtk.WINDOW_TOPLEVEL) + init(ventana_principal) + gtk.main() diff --git a/taller/BatallaNaval-3.py b/taller/BatallaNaval-3.py new file mode 100644 index 0000000..776a766 --- /dev/null +++ b/taller/BatallaNaval-3.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python +# -*- coding: cp1252 -*- + +import pygtk +pygtk.require('2.0') +import gtk +import logging +import random + +# Permite definir un Log que filtra mensajes a la salida estándar dependiendo de nivel elegido. +log = logging.getLogger('BatallaNaval') +log.setLevel(logging.DEBUG) + +# Diccionario que contiene el nombre y largo de cada barco +lista_barcos = { + "Portaaviones": 5, + "Acorazado": 4, + "Crucero": 3, + "Submarino": 3, + "Destructor": 2} + +class PanelPrincipal(gtk.HBox): + ''' Panel Principal es un Widget que contiene ambos tableros y se encarga + de crear los barcos en posiciones al azar para cada tablero ''' + + def __init__(self): + gtk.HBox.__init__(self, True) + + self.tablero1 = Tablero() # tablero propio + self.tablero2 = Tablero() # tablero enemigo + + log.debug("Barcos Propios") + barcos_propios = crear_barcos() + for barco in barcos_propios: + self.tablero1.agregar_barco(barco, True) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) + + log.debug("Barcos Enemigos") + self.barcos_enemigos = crear_barcos() + for barco in self.barcos_enemigos: + self.tablero2.agregar_barco(barco, False) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) + + self.add(self.tablero1) + self.add(self.tablero2) + + self.show_all() + +class Barco(gtk.Frame): + ''' Esta clase representa un barco, tiene nombre, largo, orientación y posición. + Como es un widget puede ser mostrado en la pantalla y tiene un texto con el nombre del barco ''' + + horizontal = 'H' + vertical = 'V' + + def __init__(self, nombre, largo, pos, orientacion = horizontal): + gtk.Frame.__init__(self) + self.nombre = nombre + self.largo = largo + self.pos = pos + + # Agrega una etiqueta con el nombre del barco + self.label = gtk.Label(nombre) + self.add(self.label) + + self.set_orientacion(orientacion) # Graba la orientación y ajusta la etiqueta a dicha orientación. + + def set_orientacion(self, orientacion): + ''' Graba la orientación y ajusta la etiqueta a dicha orientación. ''' + self.orientacion = orientacion + if self.orientacion == Barco.horizontal: + self.label.set_angle(0) + else: + self.label.set_angle(90) + + def get_inicio(self): + return self.pos + + def get_fin(self): + if self.orientacion == Barco.horizontal: + return self.pos[0], self.pos[1] + self.largo - 1 + else: + return self.pos[0] + self.largo - 1, self.pos[1] + + def get_filas(self): + return range(self.get_inicio()[0], self.get_fin()[0]+1) + + def get_cols(self): + return range(self.get_inicio()[1], self.get_fin()[1]+1) + + def get_celdas(self): + return [(f, c) for f in self.get_filas() for c in self.get_cols()] + +def crear_barcos(): + ''' Parte de la lista_barcos para crear un conjunto de barcos en posiciones al azar. ''' + + # Convierte la lista de definición en una lista de objetos Barco sin posición definida + barcos = [Barco(nombre, largo, None) for nombre, largo in lista_barcos.items()] + + celdas_ocupadas = [] # Llevo una lista de las celdas ya ocupadas por los barcos + + for barco in barcos: + # Para cada barco me mantengo en un loop hasta que encuentre coordenadas al azar que no + # intersecten con ningún barco ya ubicado. + ok = False + while not ok: + # Determino al azar si es horizontal o vertical + if random.randint(0, 1): + # Calculo coordenadas random - horizontal + barco.set_orientacion(Barco.horizontal) + posx = random.randint(1, 10) + posy = random.randint(1, 10-barco.largo+1) + else: + # Calculo coordenadas random - vertical + barco.set_orientacion(Barco.vertical) + posx = random.randint(1, 10-barco.largo+1) + posy = random.randint(1, 10) + barco.pos = (posx, posy) + + # Verifico si la posición elegida no intersecciona con las celdas ya ocupadas por otros barcos + # Convierto las listas en sets y aplico intersección + interseccion = set(barco.get_celdas()) & set(celdas_ocupadas) + if not interseccion: + ok = True + celdas_ocupadas.extend(barco.get_celdas()) + return barcos + +class Celda(gtk.Button): + ''' Esta clase representa una celda del tablero. ''' + + def __init__(self, pos): + gtk.Button.__init__(self) + self.pos = pos + + def ocultar(self): + ''' Oculta permanentemente la celda, de modo que show_all no la muestre ''' + self.set_no_show_all(True) + self.hide() + + +class Tablero(gtk.Frame): + ''' Define un tablero, el tablero está definido con una tabla exterior que permite poner + los títulos de las filas y las columnas (que a su vez son tablas) y una tabla interior + que tiene todas las celdas del tablero (tabla_celdas). ''' + + def __init__(self): + gtk.Frame.__init__(self) + + # Números + tabla_numeros = gtk.Table(1, 10, True) + for i in range(1, 11): + label = gtk.Label(str(i)) + tabla_numeros.attach(label, i-1, i, 0, 1) + + # Letras + tabla_letras = gtk.Table(10, 1, True) + for i in range(1, 11): + char = chr( ord('A') + i - 1 ) + label = gtk.Label(char) + tabla_letras.attach(label, 0, 1, i-1, i) + + # Se hace una tabla para ubicar las letras, los números y la tabla de celdas + self.tabla = gtk.Table(2, 2, False) + self.add(self.tabla) + + # Opciones para las tablas de letras y números. + opciones = gtk.SHRINK|gtk.FILL + + label = gtk.Label(" ") # Para dar más espacio a la columna de letras + self.tabla.attach(label, 0, 1, 0, 1, xoptions=opciones, yoptions=opciones) + self.tabla.attach(tabla_numeros, 1, 2, 0, 1, xoptions=opciones, yoptions=opciones) + self.tabla.attach(tabla_letras, 0, 1, 1, 2, xoptions=opciones, yoptions=opciones) + + # El tablero es otra tabla + self.tabla_celdas = gtk.Table(10, 10, True) + self.tabla.attach(self.tabla_celdas, 1, 2, 1, 2, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL|gtk.EXPAND) + + self.filas = [] + # Creo todas las celdas, las guardo en la colección de filas y las adjunto al tablero + for i in range(1, 11): + fila = [] + for j in range(1, 11): + celda = Celda((i, j)) + fila.append(celda) + self.tabla_celdas.attach(celda, j-1, j, i-1, i) + self.filas.append(fila) + + # Los barcos que hay en el tablero + self.barcos = [] + + def agregar_barco(self, barco, mostrar): + ''' Agrega un barco al tablero, si mostrar=True sustituye las celdas que ocupa por el barco. ''' + self.barcos.append(barco) + if mostrar: + # Oculta las celdas que ocupa el barco + for i, j in barco.get_celdas(): + self.ocultar_celda(i, j) + + # Obtiene los extremos del barco y lo adjunta a la tabla + arr, izq = barco.get_inicio() + aba, der = barco.get_fin() + self.tabla_celdas.attach(barco, izq-1, der, arr-1, aba) + + def ocultar_celda(self, i, j): + self.filas[i-1][j-1].ocultar() + +def init(standalone, ventana_principal): + ''' Esta función es el punto de entrada común para sugar y modo standalone + standalone es un boolean que indica si es Standalone o se ejecuta desde Sugar ''' + panel_principal = PanelPrincipal() + + if not standalone: + ventana_principal.set_canvas(panel_principal) + else: + ventana_principal.add(panel_principal) + + ventana_principal.set_title("Batalla Naval - ceibalJAM") + ventana_principal.connect("destroy", lambda wid: gtk.main_quit()) + ventana_principal.connect("delete_event", lambda a1, a2: gtk.main_quit()) + + ventana_principal.show() + +# Este código se ejecuta sólo cuando se ejecuta directo ese módulo (no cuando se importa desde sugar) +if __name__ == "__main__": + log.addHandler(logging.StreamHandler()) + ventana_principal = gtk.Window(gtk.WINDOW_TOPLEVEL) + init(True, ventana_principal) + gtk.main() diff --git a/taller/BatallaNaval-4.py b/taller/BatallaNaval-4.py new file mode 100644 index 0000000..a3b5a83 --- /dev/null +++ b/taller/BatallaNaval-4.py @@ -0,0 +1,284 @@ +#!/usr/bin/env python +# -*- coding: cp1252 -*- + +import pygtk +pygtk.require('2.0') +import gtk +import logging +import random + +# Permite definir un Log que filtra mensajes a la salida estándar dependiendo de nivel elegido. +log = logging.getLogger('BatallaNaval') +log.setLevel(logging.DEBUG) + +# Diccionario que contiene el nombre y largo de cada barco +lista_barcos = { + "Portaaviones": 5, + "Acorazado": 4, + "Crucero": 3, + "Submarino": 3, + "Destructor": 2} + +class PanelPrincipal(gtk.HBox): + ''' Panel Principal es un Widget que contiene ambos tableros y se encarga + de crear los barcos en posiciones al azar para cada tablero ''' + + def __init__(self): + gtk.HBox.__init__(self, True) + + self.tablero1 = Tablero(None) # tablero propio + self.tablero2 = Tablero(self.jugada_hecha) # tablero enemigo + + log.debug("Barcos Propios") + barcos_propios = crear_barcos() + for barco in barcos_propios: + self.tablero1.agregar_barco(barco, True) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) + + log.debug("Barcos Enemigos") + self.barcos_enemigos = crear_barcos() + for barco in self.barcos_enemigos: + self.tablero2.agregar_barco(barco, False) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) + + self.add(self.tablero1) + self.add(self.tablero2) + + self.jugadas_enemigas = [] # Lleva un registro de las jugadas hechas por la computadora + + self.show_all() + + def jugada_hecha(self, x, y): + ''' Cuando hice una jugada sobre el tablero enemigo, simulo una jugada random del enemigo. ''' + + if len(self.jugadas_enemigas) == 100: + log.error("Alcanzó las 100 jugadas.") + return + + ok = False + while not ok: + x, y = random.randint(1, 10), random.randint(1, 10) + if not (x, y) in self.jugadas_enemigas: + ok = True + + self.jugadas_enemigas.append((x, y)) + self.tablero1.jugada(self.tablero1.filas[x-1][y-1]) + +class Barco(gtk.Frame): + ''' Esta clase representa un barco, tiene nombre, largo, orientación y posición. + Como es un widget puede ser mostrado en la pantalla y tiene un texto con el nombre del barco ''' + + horizontal = 'H' + vertical = 'V' + + def __init__(self, nombre, largo, pos, orientacion = horizontal): + gtk.Frame.__init__(self) + self.nombre = nombre + self.largo = largo + self.pos = pos + + # Agrega una etiqueta con el nombre del barco + self.label = gtk.Label(nombre) + self.add(self.label) + + self.set_orientacion(orientacion) # Graba la orientación y ajusta la etiqueta a dicha orientación. + + def set_orientacion(self, orientacion): + ''' Graba la orientación y ajusta la etiqueta a dicha orientación. ''' + self.orientacion = orientacion + if self.orientacion == Barco.horizontal: + self.label.set_angle(0) + else: + self.label.set_angle(90) + + def get_inicio(self): + return self.pos + + def get_fin(self): + if self.orientacion == Barco.horizontal: + return self.pos[0], self.pos[1] + self.largo - 1 + else: + return self.pos[0] + self.largo - 1, self.pos[1] + + def get_filas(self): + return range(self.get_inicio()[0], self.get_fin()[0]+1) + + def get_cols(self): + return range(self.get_inicio()[1], self.get_fin()[1]+1) + + def get_celdas(self): + return [(f, c) for f in self.get_filas() for c in self.get_cols()] + +def crear_barcos(): + ''' Parte de la lista_barcos para crear un conjunto de barcos en posiciones al azar. ''' + + # Convierte la lista de definición en una lista de objetos Barco sin posición definida + barcos = [Barco(nombre, largo, None) for nombre, largo in lista_barcos.items()] + + celdas_ocupadas = [] # Llevo una lista de las celdas ya ocupadas por los barcos + + for barco in barcos: + # Para cada barco me mantengo en un loop hasta que encuentre coordenadas al azar que no + # intersecten con ningún barco ya ubicado. + ok = False + while not ok: + # Determino al azar si es horizontal o vertical + if random.randint(0, 1): + # Calculo coordenadas random - horizontal + barco.set_orientacion(Barco.horizontal) + posx = random.randint(1, 10) + posy = random.randint(1, 10-barco.largo+1) + else: + # Calculo coordenadas random - vertical + barco.set_orientacion(Barco.vertical) + posx = random.randint(1, 10-barco.largo+1) + posy = random.randint(1, 10) + barco.pos = (posx, posy) + + # Verifico si la posición elegida no intersecciona con las celdas ya ocupadas por otros barcos + # Convierto las listas en sets y aplico intersección + interseccion = set(barco.get_celdas()) & set(celdas_ocupadas) + if not interseccion: + ok = True + celdas_ocupadas.extend(barco.get_celdas()) + return barcos + +class Celda(gtk.Button): + ''' Esta clase representa una celda del tablero, como es subclase de button se le puede + conectar la señal "clicked". + También presenta funciones para ocultar y colorearse dependiendo de si tocó un barco o dió agua. ''' + + def __init__(self, pos): + gtk.Button.__init__(self) + self.pos = pos + + def ocultar(self): + ''' Oculta permanentemente la celda, de modo que show_all no la muestre ''' + self.set_no_show_all(True) + self.hide() + + def colorear(self, color): + self.modify_bg(gtk.STATE_NORMAL, color) + self.modify_bg(gtk.STATE_PRELIGHT, color) + self.show() # Por si está oculta atrás de un barco + + def tocado(self): + self.colorear( gtk.gdk.Color(65535,65535/2,0) ) + + def agua(self): + self.colorear( gtk.gdk.Color(0,0,65535/2) ) + + +class Tablero(gtk.Frame): + ''' Define un tablero, el tablero está definido con una tabla exterior que permite poner + los títulos de las filas y las columnas (que a su vez son tablas) y una tabla interior + que tiene todas las celdas del tablero (tabla_celdas). ''' + + def __init__(self, llamada_jugada_hecha): + gtk.Frame.__init__(self) + + # Números + tabla_numeros = gtk.Table(1, 10, True) + for i in range(1, 11): + label = gtk.Label(str(i)) + tabla_numeros.attach(label, i-1, i, 0, 1) + + # Letras + tabla_letras = gtk.Table(10, 1, True) + for i in range(1, 11): + char = chr( ord('A') + i - 1 ) + label = gtk.Label(char) + tabla_letras.attach(label, 0, 1, i-1, i) + + # Se hace una tabla para ubicar las letras, los números y la tabla de celdas + self.tabla = gtk.Table(2, 2, False) + self.add(self.tabla) + + # Opciones para las tablas de letras y números. + opciones = gtk.SHRINK|gtk.FILL + + label = gtk.Label(" ") # Para dar más espacio a la columna de letras + self.tabla.attach(label, 0, 1, 0, 1, xoptions=opciones, yoptions=opciones) + self.tabla.attach(tabla_numeros, 1, 2, 0, 1, xoptions=opciones, yoptions=opciones) + self.tabla.attach(tabla_letras, 0, 1, 1, 2, xoptions=opciones, yoptions=opciones) + + # El tablero es otra tabla + self.tabla_celdas = gtk.Table(10, 10, True) + self.tabla.attach(self.tabla_celdas, 1, 2, 1, 2, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL|gtk.EXPAND) + + self.filas = [] + # Creo todas las celdas, las guardo en la colección de filas y las adjunto al tablero + for i in range(1, 11): + fila = [] + for j in range(1, 11): + celda = Celda((i, j)) + celda.connect("clicked", self.celda_clickeada) + fila.append(celda) + self.tabla_celdas.attach(celda, j-1, j, i-1, i) + self.filas.append(fila) + + # Los barcos que hay en el tablero + self.barcos = [] + + # Callback para cuando el jugador hace una jugada en el tablero + self.llamada_jugada_hecha = llamada_jugada_hecha + + def agregar_barco(self, barco, mostrar): + ''' Agrega un barco al tablero, si mostrar=True sustituye las celdas que ocupa por el barco. ''' + self.barcos.append(barco) + if mostrar: + # Oculta las celdas que ocupa el barco + for i, j in barco.get_celdas(): + self.ocultar_celda(i, j) + + # Obtiene los extremos del barco y lo adjunta a la tabla + arr, izq = barco.get_inicio() + aba, der = barco.get_fin() + self.tabla_celdas.attach(barco, izq-1, der, arr-1, aba) + + def ocultar_celda(self, i, j): + self.filas[i-1][j-1].ocultar() + + def celda_clickeada(self, celda): + ''' Cuando hay definido un callback de jugadas hechas, significa que en este tablero puedo jugar. + Realizo la jugada y notifico al callback ''' + if self.llamada_jugada_hecha: + # Este es el callback para cuando clickean una celda + self.jugada(celda) + self.llamada_jugada_hecha(celda.pos[0], celda.pos[1]) + + def jugada(self, celda): + ''' verifica si la jugada da en algún barco o en el agua y manda la señal correcta a la celda ''' + tocado = False + for barco in self.barcos: + if celda.pos in barco.get_celdas(): + tocado = True + celda.tocado() + if not tocado: + celda.agua() + + log.debug("Pos:%s Tocado:%s", str(celda.pos), tocado) + return tocado + +def init(standalone, ventana_principal): + ''' Esta función es el punto de entrada común para sugar y modo standalone + standalone es un boolean que indica si es Standalone o se ejecuta desde Sugar ''' + panel_principal = PanelPrincipal() + + if not standalone: + ventana_principal.set_canvas(panel_principal) + else: + ventana_principal.add(panel_principal) + + ventana_principal.set_title("Batalla Naval - ceibalJAM") + ventana_principal.connect("destroy", lambda wid: gtk.main_quit()) + ventana_principal.connect("delete_event", lambda a1, a2: gtk.main_quit()) + + ventana_principal.show() + +# Este código se ejecuta sólo cuando se ejecuta directo ese módulo (no cuando se importa desde sugar) +if __name__ == "__main__": + log.addHandler(logging.StreamHandler()) + ventana_principal = gtk.Window(gtk.WINDOW_TOPLEVEL) + init(True, ventana_principal) + gtk.main() diff --git a/taller/BatallaNaval-5.py b/taller/BatallaNaval-5.py new file mode 100644 index 0000000..ea99a1d --- /dev/null +++ b/taller/BatallaNaval-5.py @@ -0,0 +1,325 @@ +#!/usr/bin/env python +# -*- coding: cp1252 -*- + +import pygtk +pygtk.require('2.0') +import gtk +import logging +import random + +# Permite definir un Log que filtra mensajes a la salida estándar dependiendo de nivel elegido. +log = logging.getLogger('BatallaNaval') +log.setLevel(logging.DEBUG) + +# Diccionario que contiene el nombre y largo de cada barco +lista_barcos = { + "Portaaviones": 5, + "Acorazado": 4, + "Crucero": 3, + "Submarino": 3, + "Destructor": 2} + +class PanelPrincipal(gtk.HBox): + ''' Panel Principal es un Widget que contiene ambos tableros y se encarga + de crear los barcos en posiciones al azar para cada tablero ''' + + def __init__(self): + gtk.HBox.__init__(self, True) + + self.tablero1 = Tablero(None) # tablero propio + self.tablero2 = Tablero(self.jugada_hecha) # tablero enemigo + + log.debug("Barcos Propios") + barcos_propios = crear_barcos() + for barco in barcos_propios: + self.tablero1.agregar_barco(barco, True) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) + + log.debug("Barcos Enemigos") + self.barcos_enemigos = crear_barcos() + for barco in self.barcos_enemigos: + self.tablero2.agregar_barco(barco, False) + log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1])) + + self.add(self.tablero1) + self.add(self.tablero2) + + self.jugadas_enemigas = [] # Lleva un registro de las jugadas hechas por la computadora + + self.show_all() + + # Carga barcos remotos + def cargar_barcos(self, barcos): + ''' Esta función es llamada cuando me conecto en red con otro usuario, recibo + una tupla con los datos de los barcos enemigos. ''' + log.debug("Cargando barcos enemigos") + self.tablero2.barcos = [] + for dato in barcos: + log.debug("Dato: %s" % str(dato)) + nombre = dato[0] + orientacion = dato[1] + largo = dato[2] + pos = dato[3:5] + + barco = Barco(nombre, largo, pos, orientacion) + self.tablero2.agregar_barco(barco, False) + log.debug("barco:%s, %s (%s, %s)" % (barco.name, barco.orientacion, barco.pos[0], barco.pos[1])) + + def jugada_red(self, x, y): + ''' Callback de colaboración para la señal Play. + Cuando el enemigo juega sobre mi tablero, reflejo la judada y le respondo si fue tocado ''' + return self.tablero1.jugada(self.tablero1.filas[x-1][y-1]) + + def jugada_hecha(self, x, y): + ''' Cuando yo mismo hice una jugada sobre el tablero enemigo + si la actividad está compartida indico al oponente la jugada que hice, + en caso contrario me simulo una jugada random del enemigo. ''' + + # Si estoy compartiendo con alguien, indico al oponente la jugada que hice + if self.colaboracion and self.colaboracion.entered: + log.debug("Señalo jugada a los participantes") + self.colaboracion.Play(x, y) + return + + # Sinó, la computadora hace una jugada al azar sobre el tablero propio + if len(self.jugadas_enemigas) == 100: + log.error("Alcanzó las 100 jugadas.") + return + + ok = False + while not ok: + x, y = random.randint(1, 10), random.randint(1, 10) + if not (x, y) in self.jugadas_enemigas: + ok = True + + self.jugadas_enemigas.append((x, y)) + self.tablero1.jugada(self.tablero1.filas[x-1][y-1]) + +class Barco(gtk.Frame): + ''' Esta clase representa un barco, tiene nombre, largo, orientación y posición. + Como es un widget puede ser mostrado en la pantalla y tiene un texto con el nombre del barco ''' + + horizontal = 'H' + vertical = 'V' + + def __init__(self, nombre, largo, pos, orientacion = horizontal): + gtk.Frame.__init__(self) + self.nombre = nombre + self.largo = largo + self.pos = pos + + # Agrega una etiqueta con el nombre del barco + self.label = gtk.Label(nombre) + self.add(self.label) + + self.set_orientacion(orientacion) # Graba la orientación y ajusta la etiqueta a dicha orientación. + + def set_orientacion(self, orientacion): + ''' Graba la orientación y ajusta la etiqueta a dicha orientación. ''' + self.orientacion = orientacion + if self.orientacion == Barco.horizontal: + self.label.set_angle(0) + else: + self.label.set_angle(90) + + def get_inicio(self): + return self.pos + + def get_fin(self): + if self.orientacion == Barco.horizontal: + return self.pos[0], self.pos[1] + self.largo - 1 + else: + return self.pos[0] + self.largo - 1, self.pos[1] + + def get_filas(self): + return range(self.get_inicio()[0], self.get_fin()[0]+1) + + def get_cols(self): + return range(self.get_inicio()[1], self.get_fin()[1]+1) + + def get_celdas(self): + return [(f, c) for f in self.get_filas() for c in self.get_cols()] + +def crear_barcos(): + ''' Parte de la lista_barcos para crear un conjunto de barcos en posiciones al azar. ''' + + # Convierte la lista de definición en una lista de objetos Barco sin posición definida + barcos = [Barco(nombre, largo, None) for nombre, largo in lista_barcos.items()] + + celdas_ocupadas = [] # Llevo una lista de las celdas ya ocupadas por los barcos + + for barco in barcos: + # Para cada barco me mantengo en un loop hasta que encuentre coordenadas al azar que no + # intersecten con ningún barco ya ubicado. + ok = False + while not ok: + # Determino al azar si es horizontal o vertical + if random.randint(0, 1): + # Calculo coordenadas random - horizontal + barco.set_orientacion(Barco.horizontal) + posx = random.randint(1, 10) + posy = random.randint(1, 10-barco.largo+1) + else: + # Calculo coordenadas random - vertical + barco.set_orientacion(Barco.vertical) + posx = random.randint(1, 10-barco.largo+1) + posy = random.randint(1, 10) + barco.pos = (posx, posy) + + # Verifico si la posición elegida no intersecciona con las celdas ya ocupadas por otros barcos + # Convierto las listas en sets y aplico intersección + interseccion = set(barco.get_celdas()) & set(celdas_ocupadas) + if not interseccion: + ok = True + celdas_ocupadas.extend(barco.get_celdas()) + return barcos + +class Celda(gtk.Button): + ''' Esta clase representa una celda del tablero, como es subclase de button se le puede + conectar la señal "clicked". + También presenta funciones para ocultar y colorearse dependiendo de si tocó un barco o dió agua. ''' + + def __init__(self, pos): + gtk.Button.__init__(self) + self.pos = pos + + def ocultar(self): + ''' Oculta permanentemente la celda, de modo que show_all no la muestre ''' + self.set_no_show_all(True) + self.hide() + + def colorear(self, color): + self.modify_bg(gtk.STATE_NORMAL, color) + self.modify_bg(gtk.STATE_PRELIGHT, color) + self.show() # Por si está oculta atrás de un barco + + def tocado(self): + self.colorear( gtk.gdk.Color(65535,65535/2,0) ) + + def agua(self): + self.colorear( gtk.gdk.Color(0,0,65535/2) ) + + +class Tablero(gtk.Frame): + ''' Define un tablero, el tablero está definido con una tabla exterior que permite poner + los títulos de las filas y las columnas (que a su vez son tablas) y una tabla interior + que tiene todas las celdas del tablero (tabla_celdas). ''' + + def __init__(self, llamada_jugada_hecha): + gtk.Frame.__init__(self) + + # Números + tabla_numeros = gtk.Table(1, 10, True) + for i in range(1, 11): + label = gtk.Label(str(i)) + tabla_numeros.attach(label, i-1, i, 0, 1) + + # Letras + tabla_letras = gtk.Table(10, 1, True) + for i in range(1, 11): + char = chr( ord('A') + i - 1 ) + label = gtk.Label(char) + tabla_letras.attach(label, 0, 1, i-1, i) + + # Se hace una tabla para ubicar las letras, los números y la tabla de celdas + self.tabla = gtk.Table(2, 2, False) + self.add(self.tabla) + + # Opciones para las tablas de letras y números. + opciones = gtk.SHRINK|gtk.FILL + + label = gtk.Label(" ") # Para dar más espacio a la columna de letras + self.tabla.attach(label, 0, 1, 0, 1, xoptions=opciones, yoptions=opciones) + self.tabla.attach(tabla_numeros, 1, 2, 0, 1, xoptions=opciones, yoptions=opciones) + self.tabla.attach(tabla_letras, 0, 1, 1, 2, xoptions=opciones, yoptions=opciones) + + # El tablero es otra tabla + self.tabla_celdas = gtk.Table(10, 10, True) + self.tabla.attach(self.tabla_celdas, 1, 2, 1, 2, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL|gtk.EXPAND) + + self.filas = [] + # Creo todas las celdas, las guardo en la colección de filas y las adjunto al tablero + for i in range(1, 11): + fila = [] + for j in range(1, 11): + celda = Celda((i, j)) + celda.connect("clicked", self.celda_clickeada) + fila.append(celda) + self.tabla_celdas.attach(celda, j-1, j, i-1, i) + self.filas.append(fila) + + # Los barcos que hay en el tablero + self.barcos = [] + + # Callback para cuando el jugador hace una jugada en el tablero + self.llamada_jugada_hecha = llamada_jugada_hecha + + def agregar_barco(self, barco, mostrar): + ''' Agrega un barco al tablero, si mostrar=True sustituye las celdas que ocupa por el barco. ''' + self.barcos.append(barco) + if mostrar: + # Oculta las celdas que ocupa el barco + for i, j in barco.get_celdas(): + self.ocultar_celda(i, j) + + # Obtiene los extremos del barco y lo adjunta a la tabla + arr, izq = barco.get_inicio() + aba, der = barco.get_fin() + self.tabla_celdas.attach(barco, izq-1, der, arr-1, aba) + + def ocultar_celda(self, i, j): + self.filas[i-1][j-1].ocultar() + + def celda_clickeada(self, celda): + ''' Cuando hay definido un callback de jugadas hechas, significa que en este tablero puedo jugar. + Realizo la jugada y notifico al callback ''' + if self.llamada_jugada_hecha: + # Este es el callback para cuando clickean una celda + self.jugada(celda) + self.llamada_jugada_hecha(celda.pos[0], celda.pos[1]) + + def jugada(self, celda): + ''' verifica si la jugada da en algún barco o en el agua y manda la señal correcta a la celda ''' + tocado = False + for barco in self.barcos: + if celda.pos in barco.get_celdas(): + tocado = True + celda.tocado() + if not tocado: + celda.agua() + + log.debug("Pos:%s Tocado:%s", str(celda.pos), tocado) + return tocado + +def init(standalone, ventana_principal): + ''' Esta función es el punto de entrada común para sugar y modo standalone + standalone es un boolean que indica si es Standalone o se ejecuta desde Sugar ''' + panel_principal = PanelPrincipal() + + if not standalone: + ventana_principal.set_canvas(panel_principal) + + # Colaboración + panel_principal.colaboracion = ventana_principal.colaboracion + panel_principal.colaboracion.set_up( + None, # Nuevo compañero + None, # Salió Compañero + panel_principal.cargar_barcos, # World + panel_principal.jugada_red, # Play + panel_principal.tablero1.barcos)# Mis barcos + else: + ventana_principal.add(panel_principal) + panel_principal.colaboracion = None + + ventana_principal.set_title("Batalla Naval - ceibalJAM") + ventana_principal.connect("destroy", lambda wid: gtk.main_quit()) + ventana_principal.connect("delete_event", lambda a1, a2: gtk.main_quit()) + + ventana_principal.show() + +# Este código se ejecuta sólo cuando se ejecuta directo ese módulo (no cuando se importa desde sugar) +if __name__ == "__main__": + log.addHandler(logging.StreamHandler()) + ventana_principal = gtk.Window(gtk.WINDOW_TOPLEVEL) + init(True, ventana_principal) + gtk.main() diff --git a/taller/pasos.txt b/taller/pasos.txt new file mode 100644 index 0000000..b4b3a7d --- /dev/null +++ b/taller/pasos.txt @@ -0,0 +1,55 @@ +''' +BatallaNaval-1 (python-básico): + * Main + * init + * PanelPrincipal + * Celda + * Tablero + * Barco + * crearBarcos + +BatallaNaval-2 (gtk-básico): + * Agregar código en main e init() y parámetro ventana_principal + * PanelPrincipal gtk.HBox (agregar init) + * Ambos tableros + * show_all + * comentar barcos + + * Celda gtk.Button (agregar init) + * Tablero gtk.Frame (agregar init) + * Nuevas tablas + * Atachar celdas al tablero + * MOSTRAR + + * Barco gtk.Frame (agregar init) + * Agrega set_orientacion + + * PanelPrincipal + * Agregar Ambos barcos + * Tablero + * Agregar código para mostrar barco + * MOSTRAR + +BatallaNaval-3 (Sugarizar): + * Agrega módulo de Actividad + * Agrega carpeta activity + * Agrega setup.py + * Agrega parámetro standalone + * Agrega código en el init + +BatallaNaval-4 (gtk-avanzado): + * Agrega jugadas_enemigas + * Agrega jugada_hecha + * Agrega callback de jugada_hecha al crear tableros + * Guarda el callback en el init del tablero + * Agrega funciones de colorear a celda + * Agrega connect a la celda + +BatallaNaval (colaboración): + * Agrega módulo de colaboración + * Crea colaboración en la Actividad + * Inicializa colaboración en el init + * Agrega código en jugada_hecha para manejar colaboración + * Agrega jugada_red para reflejar las jugadas que hace el oponente + * Agrega cargar_barcos +'''
\ No newline at end of file |