Programar Minecraft desde Python

En este sitio web se alojan algunos apuntes para programar Minecraft desde Python

Download as .zip Download as .tar.gz View on GitHub

6. Funciones

Una función es un fragmento de código con un nombre asociado que realiza una serie de tareas y devuelve un valor. A los fragmentos de código que tienen un nombre asociado y no devuelven valores se les suele llamar procedimientos. En Python no existen los procedimientos, ya que cuando el programador no especifica un valor de retorno la función devuelve el valor None (nada), equivalente al null de Java. Además de ayudarnos a programar y depurar dividiendo el programa en partes, las funciones también permiten reutilizar código.

En Python las funciones se declaran de la siguiente forma:

    def mi_funcion(param1, param2):
       print param1
       print param2 

Es decir, la palabra clave def seguida del nombre de la función y entre paréntesis los argumentos separados por comas. A continuación, en otra línea, indentado y después de los dos puntos tendríamos las líneas de código que conforman el código a ejecutar por la función.

A la hora de escribir estas líneas no se ejecuta la función. Para llamar a la función (ejecutar su código) se escribiría:

    mi_funcion("hola", 2)

Es decir, el nombre de la función a la que queremos llamar seguido de los valores que queramos pasar como parámetros entre paréntesis. La asociación de los parámetros y los valores pasados a la función se hace normalmente de izquierda a derecha: como a param1 le hemos dado un valor “hola” y param2 vale 2, mi_funcion imprimiría hola en una línea, y a continuación 2. Sin embargo también es posible modificar el orden de los parámetros si indicamos el nombre del parámetro al que asociar el valor a la hora de llamar a la función:

mi_funcion(param2 = 2, param1 = "hola")

El número de valores que se pasan como parámetro al llamar a la función tiene que coincidir con el número de parámetros que la función acepta según la declaración de la función. En caso contrario Python dará un error.

También es posible, no obstante, definir funciones con un número variable de argumentos, o bien asignar valores por defecto a los parámetros para el caso de que no se indique ningún valor para ese parámetro al llamar a la función.

Los valores por defecto para los parámetros se definen situando un signo igual después del nombre del parámetro y a continuación el valor por defecto:

    def imprimir(texto, veces = 1):
       print veces * texto 

En el ejemplo anterior si no indicamos un valor para el segundo parámetro se imprimirá una sola vez la cadena que le pasamos como primer parámetro:

    >>> imprimir("hola")
    hola

si se le indica otro valor, será este el que se utilice:

    >>> imprimir("hola", 2)
    holahola

Para definir funciones con un número variable de argumentos colocamos un último parámetro para la función cuyo nombre debe precederse de un signo *:

    def varios(param1, param2, *otros):
       for val in otros:
         print val

    varios(1, 2)
    varios(1, 2, 3)
    varios(1, 2, 3, 4)

Esta sintaxis funciona creando una tupla (de nombre otros en el ejemplo) en la que se almacenan los valores de todos los parámetros extra pasados como argumento. Para la primera llamada, varios(1, 2), la tupla otros estaría vacía dado que no se han pasado más parámetros que los dos definidos por defecto, por lo tanto no se imprimiría nada. En la segunda llamada otros valdría (3, ), y en la tercera (3, 4). También se puede preceder el nombre del último parámetro con **, en cuyo caso en lugar de una tupla se utilizaría un diccionario. Las claves de este diccionario serían los nombres de los parámetros indicados al llamar a la función y los valores del diccionario, los valores asociados a estos parámetros. En el siguiente ejemplo se utiliza la función items de los diccionarios, que devuelve una lista con sus elementos, para imprimir los parámetros que contiene el diccionario.

    def varios(param1, param2, **otros):
       for i in otros.items():
         print i

    varios(1, 2, tercero = 3) 

6.1. Variables locales / globales

Distinguiremos dos tipos de variables:

def suma_digitos(num):
  suma = 0
  while num > 0		# suma y num son variables locales	
    suma += num%10
    num /= 10
  return suma

numero = 123  		# numero es una variable global
print suma_digitos(numero)

print suma 		# ERROR  porque suma es una variable local a la función suma_digitos()

Si necesitamos modificar variables globales desde el cuerpo de una función:

def funcion (param1, param2, ...)
   global  var1, var2
   ...

6.3. Práctica con Minecraft

6.3.1. Duplica una construcción

Copia el siguiente código en un archivo nuevo desde IDLE y guárdalo con el nombre duplicaContruccion.py Prueba a ejecutarlo y trata de entenderlo.

from mcpi import minecraft
mc = minecraft.Minecraft.create()

def ordenaPar(val1, val2):
    if val1 > val2:
        return val2, val1
    else:
        return val1, val2


def copiaEstructura(x1, y1, z1, x2, y2, z2):
    x1, x2 = ordenaPar(x1, x2)
    y1, y2 = ordenaPar(y1, y2)
    z1, z2 = ordenaPar(z1, z2)

    anchura = x2 - x1
    altura = y2 - y1
    longitud = z2 - z1

    estructura = []

    print("Por favor, espera...")

    # Copia la estructura
    for fila in range(altura):
        estructura.append([])
        for columna in range(anchura):
            estructura[fila].append([])
            for profundidad in range(longitud):
                bloque = mc.getBlock(x1 + columna, y1 + fila, z1 + profundidad)
                estructura[fila][columna].append(bloque)

    return estructura


def construyeEstructura(x, y, z, estructura):
    xInicial = x
    yInicial = y
    for fila in estructura:
        for columna in fila:
            for bloque in columna:
                mc.setBlock(x, y, z, bloque)
                z += 1
            x += 1
            z = yInicial
        y += 1
        x = xInicial


# obtén la posición de la primera esquina
input("Muévete a la primera esquina y pulsa Intro en esta ventana")
pos = mc.player.getTilePos()
x1, y1, z1 = pos.x, pos.y, pos.z

# obtén lla posición de la segunda esquina
input("Muévete a la esquina opuesta y pulsa Intro en esta ventana")
pos = mc.player.getTilePos()
x2, y2, z2 = pos.x, pos.y, pos.z

# copia la estructura
estructura = copiaEstructura(x1, y1, z1, x2, y2, z2)

# obtén la posición para la copia
input("Muévete a la posición donde quieres crear la estructura y pulsa Intro en esta ventana")
pos = mc.player.getTilePos()
x, y, z = pos.x, pos.y, pos.z
construyeEstructura(x, y, z, estructura)

Vuelve al índice