Versión preliminar de Tetris en Python

Con el tiempo me he dado cuenta que no soy nada bueno con los títulos, bueno tampoco soy bueno con los comentarios, y tampoco bueno con las entradas :P , pero bueno que vamos a hacer.

En esta ocasión les traigo mi versión ultra-hiper básica de un tetris implementado utilizando Python, Numpy y Pygame. Este es mi primer intento y puede que más adelante me de la rabia y lo vuelva a re-hacer de cero. Como les iba diciendo esta versión se encuentra aún en pañales pero hace lo básico.

Esta el tablero dibujado,  lanza piezas al azar que nosotros podemos ir rotando, permite acelerar la caída de la pieza, muestra siguiente pieza, reconoce otras piezas que están en el tablero, detecta fila completa y la procesa. Que faltaría, añadir un contador de tiempo, mostrar puntaje, permitir re-dimensionar el tablero, reiniciar juego y acelerar la caída de las piezas al cumplir n filas completadas; creo que eso es todo por el momento.

Espero tener pronto una versión más refinada, pero igual les dejo mi código para que lo prueben y utilicen con total libertad. Quedo dividido en 3 archivos: tetris.py(archivo principal), figure.py y board.py.

Para ejecutar: python tetris.py

tetris.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: tetris.py
# Developer by: @itrogeno
# Date: 29-03-2011
# Version: 0.4a

'''Programando una version personalizada de Tetris
   para Python 2.6. Utilizando las librerias
   Numpy y Pygame.'''

# Cargamos las librerias
import pygame
import numpy

from board  import Board
from figure import Figure

# Constantes
TITLE = 'Tetris'
VERSION = '0.2a'
WIDTH, HEIGHT = SIZE = (600, 420) # definimos el tamano de la ventana
CENTER_X = WIDTH/2
FRAMERATE = 30

# Tablero
ROWS, COLS = SHAPE = (20, 10)
PIXEL = 20

# No se utilizaran los colores Negro(0, 0, 0), ni blanco(255, 255, 255)
# que se utilizan respectivamente como color de fondo y para dibujar
# el tablero. Utilice el comando len(COLORS) para obtener el numero
# de colores disponibles.
BG_COLOR = (  0,   0,   0) # Negro
FG_COLOR = (255, 255, 255) # Blanco

COLORS = {
     0 : BG_COLOR,
     1 : (  0,   0, 255), # Azul
     2 : (  0, 255,   0), # Verde
     3 : (  0, 255, 255), # Aqua
     4 : (255,   0,   0), # Rojo
     5 : (255,   0, 255), # Magenta
     6 : (255, 255,   0), # Amarillo
     7 : (200, 200, 200), # Gris
     8 : FG_COLOR,
     9 : BG_COLOR,
    10 : FG_COLOR
}

# Variables
screen, clock, running, board, figure, row = None, None, None, None, None, None
lock, speed = False, 1.0

def events(events):
    '''Procesa todos los eventos producidos en el
       juego.'''
    global running, figure, row, lock, speed

    for event in events:
        if event.type == pygame.QUIT:
            # Finalizamos la ejecucion del juego
            # cuando el usuario cierra la ventana.
            running = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                # Finalizamos la ejecución del juego
                # cuando el usuario presiona la tecla
                # escape.
                running = False
            if event.key == pygame.K_DOWN and not lock:
                #Bloquear teclas
                speed = 10.0
                lock = True
            if event.key == pygame.K_UP and not lock:
                # Rotar la figura
                figure.rotate()
            if event.key == pygame.K_LEFT and not lock:
                # Mover la figura a la izquierda
                figure.move(-1)
            if event.key == pygame.K_RIGHT and not lock:
                # Mover la figura a la derecha
                figure.move(1)
            if event.key == pygame.K_c:
                # Limpiar tablero
                board.clear()
                del figure
                row = 0
                figure = Figure(board.get_board())

# Desde donde empezamos a dibujar el tablero
X, Y = CENTER_X - (PIXEL*COLS/2), 10

def get_xy(col, row, x=None, y=None):
    x = X if x is None else x
    y = Y if y is None else y
    return x + (col * PIXEL), y + (row * PIXEL)

def draw_line(screen, col, row, X=0, Y=0, x=None, y=None):
    x, y = get_xy(col, row, x, y)
    pygame.draw.line(screen, FG_COLOR, (x, y), (x+X, y+Y))

def draw_rect(screen, color, col, row, x=None, y=None):
    x, y  = get_xy(col, row, x, y)
    pygame.draw.rect(screen, COLORS[color], (x, y, PIXEL, PIXEL))

def draw_board(board):
    rows, cols = board.shape
    '''Dibujamos el tablero'''
    for col in range(cols):
        for row in range(rows):
            draw_rect(screen, board[row, col], col, row)
            draw_line(screen, col, row, X=PIXEL)
            draw_line(screen, col, row, Y=PIXEL)
    draw_line(screen, 0, row+1, X=PIXEL*cols)
    draw_line(screen, col+1, 0, Y=PIXEL*rows)

def draw_figure(figure, color):
    x, y, = 450, 10
    rows, cols = figure.shape
    '''Dibujamos la figura'''
    for col in range(cols):
        for row in range(rows):
            if figure[row, col] != 0:
                draw_rect(screen, color, col, row, x=x, y=y)
            #draw_line(screen, col, row, X=PIXEL, x=x, y=y)
            #draw_line(screen, col, row, Y=PIXEL, x=x, y=y)
    #draw_line(screen, 0, row+1, X=PIXEL*cols, x=x, y=y)
    #Sdraw_line(screen, col+1, 0, Y=PIXEL*rows, x=x, y=y)

def refresh(board, framerate):
    draw_board(board.get_board())
    pygame.display.flip()
    clock.tick(framerate)

def init():
    '''Este metodo permite inicializar las librerias y
       variables del juegos.'''
    global screen, clock, running, board

    running = True
    board = Board(SHAPE)

    pygame.init()
    screen = pygame.display.set_mode(SIZE)
    clock = pygame.time.Clock()
    pygame.display.set_caption('%s v%s' % (TITLE, VERSION))

def main():
    global row, figure, lock, speed

    '''Metodo Principal'''
    init()
    row = 0
    completed = 0
    rows = 0
    figure = Figure(board.get_board())
    next   = Figure(board.get_board())
    while running:
        screen.fill(BG_COLOR)
        draw_figure(next.get_figure(), next.nro_figure)
        figure.clear(board.get_board())
        events(pygame.event.get())
        if not figure.forward(int(row)):
            figure.update(board.get_board())
            del figure
            figure = next
            row = 0
            while board.evaluate(8):
                completed += 1
                refresh(board, FRAMERATE/4)
                board.evaluate(9)
                refresh(board, FRAMERATE/4)
                board.evaluate(10)
                refresh(board, FRAMERATE/4)
                board.evaluate(0)
                refresh(board, FRAMERATE/4)
                board.update()
                refresh(board, FRAMERATE/4)
            next = Figure(board.get_board())
            figure.set_board(board.get_board())
            speed = 1.0
            lock = False
        figure.update(board.get_board())
        refresh(board, FRAMERATE)
        row += (speed/FRAMERATE) * 2.0
    print 'Fin del Juego.'

if __name__ == '__main__':
    main()

figure.py

# -*- coding: utf-8 -*-
# Filename: figure.py
# Developer by: @itrogeno
# Date: 29-03-2011
# Version: 0.4a
import random
import numpy

class Figure():
    # Definimos las diferentes figuras
    FIGURES = {
        1: ('0 0 0 0; 0 1 1 0; 0 1 1 0; 0 0 0 0',),

        2: ('0 0 0 0; 1 1 1 1; 0 0 0 0; 0 0 0 0',
            '0 0 1 0; 0 0 1 0; 0 0 1 0; 0 0 1 0'),

        3: ('0 0 0 0; 0 0 1 1; 0 1 1 0; 0 0 0 0',
            '0 0 1 0; 0 0 1 1; 0 0 0 1; 0 0 0 0'),

        4: ('0 0 0 0; 0 1 1 0; 0 0 1 1; 0 0 0 0',
            '0 0 0 1; 0 0 1 1; 0 0 1 0; 0 0 0 0'),

        5: ('0 0 0 0; 0 1 1 1; 0 1 0 0; 0 0 0 0',
            '0 0 1 0; 0 0 1 0; 0 0 1 1; 0 0 0 0',
            '0 0 0 1; 0 1 1 1; 0 0 0 0; 0 0 0 0',
            '0 1 1 0; 0 0 1 0; 0 0 1 0; 0 0 0 0'),

        6: ('0 0 0 0; 0 1 1 1; 0 0 0 1; 0 0 0 0',
            '0 0 1 1; 0 0 1 0; 0 0 1 0; 0 0 0 0',
            '0 1 0 0; 0 1 1 1; 0 0 0 0; 0 0 0 0',
            '0 0 1 0; 0 0 1 0; 0 1 1 0; 0 0 0 0'),

        7: ('0 0 0 0; 0 1 1 1; 0 0 1 0; 0 0 0 0',
            '0 0 1 0; 0 0 1 1; 0 0 1 0; 0 0 0 0',
            '0 0 1 0; 0 1 1 1; 0 0 0 0; 0 0 0 0',
            '0 0 1 0; 0 1 1 0; 0 0 1 0; 0 0 0 0')
    }

    ROWS_FIGURE = 4
    COLS_FIGURE = 4
    CLS_FIGURE  = 0

    angle = 0 # angulo inicial

    def __init__(self, board):
        self.set_board(board)
        self.rows, self.cols = self.shape = self.board.shape
        self.nro_row = -1
        self.nro_col = (self.cols / 2) -1
        self.nro_figure = random.randint(1, len(self.FIGURES))
        print 'Figura: %i' % self.nro_figure

    def set_board(self, board):
        self.board = board.copy()

    def get_figure(self, angle=None):
        angle = self.angle if angle is None else angle
        figure = numpy.matrix(self.FIGURES[self.nro_figure][angle])
        return figure

    def forward(self, mov):
        if self.nro_row == mov or\
           self.__evaluate(mov, self.nro_col, self.get_figure()):
            self.nro_row = mov
            return True
        else:
            return False

    def move(self, mov):
        if self.__evaluate(self.nro_row, self.nro_col+mov, self.get_figure()):
            self.nro_col += mov

    def rotate(self):
        nro_col = self.nro_col
        angle = self.__next_angle()

        i = 3
        while i >= 0:
            if self.__evaluate(self.nro_row, nro_col, self.get_figure(angle)):
                self.angle = angle
                self.nro_col = nro_col
                i = 0
            else:
                nro_col = self.nro_col -1 if i == 1 else nro_col + 1
            i -= 1

    def update(self, board, clear=False):
        figure = self.get_figure()
        nro_row, nro_col = self.nro_row, self.nro_col
        for x in range(self.ROWS_FIGURE):
            tmp_col = nro_col
            for y in range(self.COLS_FIGURE):
                if self.__is_valid(nro_row, tmp_col) and\
                   figure[(self.ROWS_FIGURE - x)-1, y] != 0:
                    if nro_row >= 0:
                        board[nro_row, tmp_col] = self.CLS_FIGURE if clear else self.nro_figure
                tmp_col += 1
            nro_row -= 1

    def clear(self, board):
        self.update(board, True)

    def __is_valid(self, nro_row, nro_col):
        return nro_row < self.rows and\
               nro_col >= 0 and nro_col < self.cols

    def __evaluate(self, nro_row, nro_col, figure):
        for x in range(self.ROWS_FIGURE):
            tmp_col = nro_col
            for y in range(self.COLS_FIGURE):
                if not self.__is_valid(nro_row, tmp_col) and\
                   figure[(self.ROWS_FIGURE - x)-1, y] != 0:
                    return False

                if self.__is_valid(nro_row, tmp_col) and nro_row >= 0 and\
                   figure[(self.ROWS_FIGURE - x)-1, y] != 0 and\
                   self.board[nro_row, tmp_col] != 0:
                    return False
                tmp_col += 1
            nro_row -= 1
        return True

    def __next_angle(self):
        angle = self.angle + 1
        return 0 if angle >= len(self.FIGURES[self.nro_figure]) else angle

board.py

# -*- coding: utf-8 -*-
# Filename: board.py
# Developer by: @itrogeno
# Date: 29-03-2011
# Version: 0.4a

import numpy

class Board():

    def __init__(self, shape):
        self.array = numpy.zeros(shape, numpy.int)

    def clear(self):
        self.array.fill(0)

    def get_board(self):
        return self.array

    def evaluate(self, color):
        rows, cols = self.array.shape
        for y in range(rows):
            row = self.array[(rows-y)-1]
            complete = True
            for x in range(len(row)):
                if row[x] == 0:
                    complete = False
                    break
            if complete:
                for x in range(len(row)):
                    row[x] = color
                return True
        return False

    def update(self):
        rows, cols = self.array.shape
        for y in range(rows):
            row = self.array[(rows-y)-1]
            if row.sum() == 0:
                if (rows-(y+1))-1 >= 0:
                    self.array[(rows-y)-1] = self.array[(rows-(y+1))-1]
                    self.array[(rows-(y+1))-1] = numpy.zeros(cols, numpy.int)

Bueno, esto es todo por hoy y no olviden si tienen cualquier duda o comentario no duden en Realizar.

Adiós.

Python: Arból Binario

A pasado 1 año 10 meses desde mi última publicación que en tiempo informático debe ser como un siglo :P . Lo que hace más de un año una idea, un código era aceptado; puede que ahora este en retirada (esto solo es una apreciación  personal y puede que este equivocado) y del poco código que había llegado a publicar alguno haya quedado obsoleto.

Y dado el tiempo trascurrido y de mucho reflexionar creo que ha llegado el momento de ponerme serio y retribuir todo lo que he aprendido durante estos años gracias a Internet y poder transformarme en un aporte más.

Bueno y de que mejor forma que volver a partir con un viejo conocido, el Árbol Binario, pero esta vez implementado con Python, que se ha convertido en uno de mis lenguajes favoritos en la actualidad (el otro es Javascript).

¿Y qué trae esta versión?
Esta versión permite hacer las siguientes tareas: Añadir, Eliminar, Buscar y Listar.

# -*- coding: utf-8 -*-
#
# Python version: 2.6.6
# Developer by: @itrogeno
# Date: 24-05-2011
# Description: Implementacion de un Arbol Binario en Python.

class Tree():
    '''Arbol Binario'''

    left  = None
    right = None
    data  = []

    def __init__(self, value):
        self.value = value

    def append(self, value):
        '''Metodo recursivo que permite anadir nuevos valores al
           arbol binario.
           Si el nuevo valor es mayor que el valor actual se
           inserta en la rama derecha, si es menor se inserta en
           la rama izquierda.'''
        self.__append(['left', 'right'][value > self.value],
                      value)

    def __append(self, name, value):
        '''Metodo privado que anade un nuevo nodo'''
        node = getattr(self, name, value)

        if node is None:
            node = Tree(value)
        else:
            node.append(value)
        setattr(self, name, node)

    def get_data(self):
        '''Devuelve una lista ordernada en forma ascendente
           con todos los valores ingresados.'''
        self.data[:] = []
        self.__order_data(self)
        return self.data

    def get_data_inverse(self):
        '''Devuelve una lista ordenada en forma descendente
           con todos los valores ingresados.'''
        return self.get_data()[::-1]

    def __order_data(self, node):
        '''Metodo recursivo privado'''
        def a(n):
            if n is not None: self.__order_data(n)

        a(node.left)
        self.data.append(node.value)
        a(node.right)

    def search(self, value):
        '''Permite buscar valores existentes en el arbol.
           Devuelve un objeto Tree() si encuentra el valor, de
           lo contrario devuelve un None.'''
        parent, node = self.__search(None, self, value)
        return node

    def __search(self, parent, node, value):
        '''Metodo recursivo privado que permite buscar valores
           existentes en el arbol.'''
        if node is None: return None, None

        if value == node.value:
            return parent, node

        parent, result = self.__search(node, node.left, value)
        if result is not None:
            return parent, result

        parent, result = self.__search(node, node.right, value)
        if result is not None:
            return parent, result

        return None, None

    def delete(self, value):
        '''Permite eliminar valores del arbol binario.'''

        parent, node = self.__search(None, self, value)
        if node is None:
            return
        # Seleccionamos uno de los dos nodos hijos, por defecto
        # siempre se utiliza el nodo derecho, pero si no existe
        # se utiliza el nodo izquierdo.
        child = getattr(node, ['left', 'right'][node.right
                                                is not None])
        if parent is not None:
            # Si el nodo tiene padre, quiere decir que no es el
            # nodo raiz.
            # Reemplazamos el nodo con su nodo hijo, por defecto
            # se utiliza el nodo derecho si no tiene se utiliza
            # el nodo izquierdo.
            direction = ['left', 'right'][parent.right is node]
            setattr(parent, direction, child)

            # Si se reemplazo por el nodo hijo derecho y tenia
            # hijos en el nodo izquierdo estos son heredados al
            # nodo hijo derecho, insertandolos al nivel mas bajo
            # de la rama izquierda.
            if node.left is not None and node.right is not None:
                root.__insert_left(node.right, node.left)

            del node
        else:
            # En esta implementacion es imposible eliminar el
            # nodo padre, para ello en vez de reemplazarlo con
            # el nodo hijo, solo heredamos los valores del hijo.
            # Una vez hecho eso eliminamos el nodo hijo.
            if node.left is not None and node.right is not None:
                child.__insert_left(node.right, node.left)

            node.value = child.value
            node.left  = child.left
            node.right = child.right

            del child

    def __insert_left(self, parent, node):
        if parent.left is None:
            parent.left = node
        else:
            self.__insert_left(parent.left, node)

    def __str__(self):
        return 'Value: %i' % self.value

def main():
    print "1° Insertamos datos al arbol"

    tree = Tree(2)
    tree.append(3)
    tree.append(1)
    tree.append(5)
    tree.append(4)
    tree.append(0)
    tree.append(-1)
    tree.append(-4)
    tree.append(-3)
    tree.append(-2)
    tree.append(-5)
    print ''
    print '2° Listamos los datos ordenados'
    print tree.get_data()
    print ''
    print '3° Listamos los datos inversos'
    print tree.get_data_inverse()
    print ''
    print '4° Buscamos los datos en forma individual'
    print '5 %s' % tree.search(5)
    print '1 %s' % tree.search(1)
    print '3 %s' % tree.search(3)
    print '4 %s' % tree.search(4)
    print '2 %s' % tree.search(2)
    print '6 %s' % tree.search(6)
    print ''
    print '5° Eliminamos el numero 2'
    tree.delete(2)
    print ''
    print '6° Volvemos a listar los datos'
    print tree.get_data()
    print tree.get_data_inverse()
    print ''
    print '7° Añadimos el numero 6 y -6'
    tree.append(6)
    tree.append(-6)
    print ''
    print '8° Volvemos a listar los datos'
    print tree.get_data()
    print tree.get_data_inverse()
    print ''
    print '9° Eliminamos el numero 4'
    tree.delete(4)
    print ''
    print '10° Volvemos a listar los datos'
    print tree.get_data()
    print tree.get_data_inverse()

if __name__ == '__main__':
    main()

Bueno creo que eso es todo por hoy y si alguien tiene alguna sugerencia o duda con el código no dude en preguntar que estaré encantado en responder.

Gracias

Categorías:Programación, python

C#: Bosquejo de un ActiveRecord con Insert y Select

Aburrido en una noche de primavera comence a escribir un pequeño programa que era el bosquejo básico pero bien básico un ActiveRecord llegando sólo a implementar las funciones Insert y Select, aun tengo pendiente las funciones Update y Delete.

Este código se conecta a un base de datos Postgres a la tabla test con los campos id, nombre, apellidos y edad, primero inserta y luego lista el dato ingresado.

Antes de probar el código, deben crear la tabla y las columnas en minuscula.

Program.cs

using System;
using System.Collections.Generic;

namespace MiActiveRecord
{
    public class Program
    {
        static void Main(string[] args)
        {
            Test test = new Test() {Nombre="Alexis",
                                    Apellidos="Nuñez Riquelme"};
            test.Save();

            IList<Test> tests = Test.GetAll();

            foreach (Test item in tests)
            {
                Console.WriteLine("{0,2} - {1, 10} - {2, 15} - {3, 2}",
                item.Id, item.Nombre, item.Apellidos, item.Edad);
            }
        }

        public class Test : Base<Test>
        {
            public string Nombre { get ; set; }
            public string Apellidos { get; set; }
            public int? Edad { get; set; }
        }
    }
}

Base.cs


using System;
using System.Collections.Generic;
using System.Configuration;
using System.Reflection;
using System.Text;
using Npgsql;

namespace MiActiveRecord
{
 public class Base<T> : BaseSQL<T>
 {
 public long Id { get; set; }

 public static IList<T> GetAll()
 {
 IList<T> lst = new List<T>();

 using (NpgsqlConnection sqlCnn = new NpgsqlConnection("User ID=postgres; Password=postgres; Host=localhost; Port=5432; Database=MiActiveRecord"))
 {
 sqlCnn.Open();

 StringBuilder sql = GetSelect();

 NpgsqlDataReader reader = new NpgsqlCommand(sql.ToString(), sqlCnn).ExecuteReader();

 while (reader.Read())
 {
 T item = (T)typeof(T).Assembly.CreateInstance(typeof(T).FullName);

 (item as Base<T>).LoadValues(reader);

 lst.Add(item);
 }

 reader.Close();
 sqlCnn.Close();
 }

 return lst;
 }

 public void LoadValues(NpgsqlDataReader reader)
 {
 for (int i = 0; i < reader.FieldCount; i++)
 {
 foreach (PropertyInfo property in (this).GetType().GetProperties())
 {
 if (property.Name.ToUpper() == reader.GetName(i).ToUpper())
 {
 if (reader[reader.GetName(i).ToUpper()] is DBNull)
 property.SetValue(this, null, null);
 else
 property.SetValue(this, reader[reader.GetName(i).ToUpper()], null);

 break;
 }
 }
 }
 }

 public void Save()
 {
 using (NpgsqlConnection sqlCnn = new NpgsqlConnection("User ID=postgres; Password=postgres; Host=localhost; Port=5432; Database=MiActiveRecord"))
 {
 StringBuilder strSQL = GetInsert();

 sqlCnn.Open();

 NpgsqlCommand sqlcmd = new NpgsqlCommand(strSQL.ToString(), sqlCnn);

 sqlcmd.ExecuteNonQuery();

 sqlCnn.Close();
 }
 }
 }
}

BaseSQL.cs


using System.Text;
using System.Reflection;
using System.Collections.Generic;
using System;

namespace MiActiveRecord
{
 public class BaseSQL<T>
 {
 internal StringBuilder GetInsert()
 {
 StringBuilder sql = new StringBuilder("INSERT INTO ")
 .AppendFormat("{0} (", this.GetType().Name);

 foreach (PropertyInfo property in Base<T>.GetProperties(this.GetType(), true))
 {
 if (property.GetValue(this, null) != null)
 sql.AppendFormat("{0}, ", property.Name);
 }

 sql.Remove(sql.Length - 2, 2);

 sql.Append(") VALUES (");

 foreach (PropertyInfo property in Base<T>.GetProperties(this.GetType(), true))
 {
 if (property.GetValue(this, null) != null)
 {
 if (property.PropertyType == typeof(string) || property.PropertyType == typeof(char))
 sql.AppendFormat("'{0}', ", property.GetValue(this, null));
 else
 sql.AppendFormat("{0}, ", property.GetValue(this, null));
 }
 }

 sql.Remove(sql.Length - 2, 2);

 sql.Append(")");

 return sql;
 }

 internal static StringBuilder GetSelect()
 {
 StringBuilder sql = new StringBuilder("SELECT ");

 foreach (PropertyInfo property in Base<T>.GetProperties(typeof(T), false))
 {
 sql.AppendFormat("{0}, ", property.Name);
 }

 sql.Remove(sql.Length - 2, 2);

 sql.AppendFormat(" FROM {0}", typeof(T).Name);
 return sql;
 }

 private static IList<PropertyInfo> GetProperties(Type type, bool skipBase)
 {
 IList<PropertyInfo> properties = new List<PropertyInfo>();

 bool exist;

 foreach (PropertyInfo proItem in type.GetProperties())
 {
 exist = false;

 if (skipBase)
 {
 foreach (PropertyInfo proBase in typeof(Base<T>).GetProperties())
 {
 if (proBase.Name == proItem.Name)
 {
 exist = true;
 break;
 }
 }
 }

 if (!exist)
 properties.Add(proItem);
 }

 return properties;
 }
 }
}

C#: Añandiendo descripciones a un Enum

Este código muy simple y nos permite añadir descripciones a nuestros Enum:

using System;
using System.Reflection;

namespace Enum
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(EnumDes.Descripcion<Navegadores>(Navegadores.Firefox));
            Console.WriteLine(EnumDes.Nombre<Navegadores>("Mozilla Firefox"));

            Navegadores valor = (Navegadores)EnumDes.Valor<Navegadores>("Mozilla Firefox");

            if (valor == Navegadores.Firefox)
            {
                Console.WriteLine("Es Firefox... :)");
            }
        }
    }

    public enum Navegadores
    {
        [EnumDes("Mozilla Firefox")]
        Firefox,
        [EnumDes("Opera Browser")]
        Opera
    }

    // Esta clase se crea como Atributo para insentar descripciones en cualquier enum
    public class EnumDes : Attribute
    {
        private string _descripcion;

        // Constructor
        public EnumDes(string descripcion)
        {
            _descripcion = descripcion;
        }

        // Este método recupera la descripción del enum utilizando Reflection.
        public static string Descripcion<T>(T _enum)
        {
            FieldInfo info = typeof(T).GetField(_enum.ToString(), BindingFlags.Public |
                                                                  BindingFlags.Static);

            foreach (object obj in info.GetCustomAttributes(false))
            {
                if (obj.GetType() == typeof(EnumDes))
                {
                    return obj.ToString();
                }
            }

            return "No se encontró la descripción";
        }

        public static FieldInfo Buscar<T>(string descripcion)
        {
            FieldInfo[] infos = typeof(T).GetFields(BindingFlags.Public |
                                                    BindingFlags.Static);

            foreach (FieldInfo item in infos)
            {
                foreach (object attribute in item.GetCustomAttributes(false))
                {
                    if (attribute.ToString() == descripcion)
                    {
                        return item;
                    }
                }
            }

            return null;
        }

        public static string Nombre<T>(string descripcion)
        {
            FieldInfo info = Buscar<T>(descripcion);

            return (info == null ? "No se encontró el valor" : info.Name);
        }

        public static object Valor<T>(string descripcion)
        {
            FieldInfo info = Buscar<T>(descripcion);

            return (info == null ? null : info.GetValue(typeof(T)));
        }

        /* Se sobrescribe el método ToString() para retornar la descripción
         * ingresada a través de su constructor.
         */
        public override string ToString()
        {
            return _descripcion;
        }
    }
}

Categorías:C#, Enum, Programación, Reflection

Cuando no aceptar un Proyecto

En mi poca experiencia como desarrollador puedo rescatar algunos puntos que uno debe analizar para no aceptar un proyecto:

  1. Es la herencia de alguien más (Persona o Empresa), si es la herencia de otra empresa atente a las consecuencias.
  2. El sistema tiene un framework propietario/cerrado con nula documentación. Peor es si el framework pertenece a la empresa que anteriormente desarrollaba el proyecto.
  3. El sistema no tiene documentación/auto-documentación.
  4. El sistema tiene abundante código spaguetti.
  5. No tengas contacto con la persona o empresa que desarrollaba el proyecto.
  6. O si tienes contacto no sepan lo que hicieron.
  7. El proyecto venga con el regalo de un Jefe de Proyecto y/o Analista(s) incompetente(s).
  8. Al aceptar el proyecto puedas quedar amarrado eternamente a este.
Categorías:General, Programación

Python: Mi propia versión de Mario Bros.

Quede con gusto a poco después de realizar mi primer juego en python y pygame, así pasaron varias semanas hasta que navegando por Internet me entere que alguien había desarrollado un Mario Bros. en javascript, el cuál lo había encontrado genial, con este hecho encontré mi inspiración para crear mi propia versión de Mario Bros.

Durante 3 semanas me dedique a programar mi propia versión. Obtuve los sprites desde Internet y con lo aprendido programando mi primer juego empece mi odisea.

Al finalizar las 3 semanas pude realizar lo siguiente:

  1. Crear una parte del primer nivel.
  2. Añadir un tipo de enemigo.
  3. Logre mover el fondo, lo cuál me costo mucho trabajo.
  4. Realizar los movimientos de Mario.
  5. Lograr que Mario aplaste a su enemigo
  6. Hacer que Mario interactue con su ambiente.

No es mucho lo que pude hacer pero trabajando sólo de noche y cansado. Bueno acá les dejo una imagen de como quedo el juego y un enlace con los fuentes.

Mario Bros. en Python

Fuente Mario Bros.

P.D.: Si tienen algún problema para descar el código fuente me avisan.

Python: Mi primer juego

19/01/2009 1 Comentario

Mi primer acercamiento a la informática fue hace unos 17 años aproximadamente, en esa época sólo tenía un computador atari con el Basic como lenguaje de programación. Lo único que me interesaba más que jugar con los juegos que tenía era programar mis propios juegos, pasaba días enteros programando mis juegos, mientras soñaba con trabajar como programador de juegos, pero la realidad fue otra y termine haciendo aburridos sistemas para empresas.  :(

Pero no fue hasta hace unos meses atrás que empece a interesarme en Python y toda su filosofía de vida, y leyendo algunos blogs mostraban la simplicidad que tenia el lenguaje para desarrollar juegos, sólo debía instalar la librería pygame y manos a la obra.

Así que le dedique varias noches a programar mi primer juego y al cabo de 2 semanas ya lo tenía armado. Es un  simple juego de naves donde uno se puede mover por toda la pantalla disparando y tratando de matar a las naves enemigas mientras van apareciendo desde arriba de la pantalla.

shipspace1

Si lo quieren probar acá les dejo el código fuente comprimido.

ShipSpace.rar

Categorías:juego, Programación, pygame, python

C#: Ordenando una lista genérica

El siguiente código muestra el ordenamiento de una lista genérica, siendo necesario que los objetos implementen la interfaz Icomparable.

using System;
using System.Collections.Generic;

namespace nitrogeno
{
    class Program
    {
        static void Main(string[] args)
        {
            IList<string> list1 = new List<string>();

            list1.Add("Casa");  // 1
            list1.Add("Auto");  // 2
            list1.Add("Arbol"); // 3
            list1.Add("Sapo");  // 4
            list1.Add("Nuevo"); // 5

            SortList.Bubble<string>(list1);

            foreach (string item in list1)
                Console.WriteLine("{0}", item);

            Console.WriteLine();

            IList<int> list2 = new List<int>();

            list2.Add(5);  // 1
            list2.Add(2);  // 2
            list2.Add(3);  // 3
            list2.Add(1);  // 4
            list2.Add(4);  // 5

            SortList.Bubble<int>(list2);

            foreach (int item in list2)
                Console.WriteLine("{0}", item);
        }
    }

    public class SortList
    {
        public static IList<T> Bubble<T>(IList<T> list)
               where T : IComparable
        {
            T tmp;

            for (int i = 0; i < list.Count; i++)
            {
                for (int x = 0; x < list.Count - (i + 1); x++)
                {
                    if (list[x].CompareTo(list[x + 1]) > 0)
                    {
                        tmp = list[x + 1];
                        list[x + 1] = list[x];
                        list[x] = tmp;
                    }
                }
            }

            return list;
        }
    }
}

C#: Árbol Binario Genérico

19/01/2009 1 Comentario

Este árbol binario lo desarrolle en un momento de aburrimiento  en el trabajo y nunca lo temine, por eso me faltó implementar el método eliminar, asi que espero añadirlo en un futuro próximo.

Lo interesante de este código es que permite utilizar los tipos de datos char, string, datetime, int, decimal, o cual  otro objeto que tenga implementado la interfaz Icomparable. Porque el árbol binario hace uso del método CompareTo de la interfaz Icomparable, para ir comparando el nuevo nodo con los nodos existentes y asi saber que camino debe tomar.

using System.Collections.Generic;

namespace ArbolBinarioGenerico
{
    class Program
    {
        static void Main(string[] args)
        {
            ArbolBinario<int> arbol = new ArbolBinario<int>(8); //1

            arbol.Insertar(ref arbol, 7); //2
            arbol.Insertar(ref arbol, 5); //3
            arbol.Insertar(ref arbol, 3); //4
            arbol.Insertar(ref arbol, 4); //5
            arbol.Insertar(ref arbol, 0); //6
            arbol.Insertar(ref arbol, 2); //7
            arbol.Insertar(ref arbol, 6); //8
            arbol.Insertar(ref arbol, 9); //9
            arbol.Insertar(ref arbol, 1); //10

            foreach(int valor in arbol.Listar(arbol, new List&ltint&lt()))
                Console.WriteLine(valor);
        }
    }

    public class ArbolBinario<T> where T : IComparable
    {
        private T valor;
        private ArbolBinario<T> nodoIzq = null; // nodo derecho
        private ArbolBinario<T> nodoDer = null; // nodo izquierdo

        public ArbolBinario(T valor) // constructor
        {
            this.valor = valor;
        }

        public void Insertar(ref ArbolBinario<T> nodo, T valor)
        {
            if (nodo == null)
                nodo = new ArbolBinario<T>(valor);
            else
            {
                if (nodo.valor.CompareTo(valor) > 0)
                    Insertar(ref nodo.nodoIzq, valor);
                else
                    Insertar(ref nodo.nodoDer, valor);
            }
        }

        public List<T> Listar(ArbolBinario<T> nodo, List<T> arbol)
        {
            if (nodo.nodoIzq != null)
                Listar(nodo.nodoIzq, arbol);

            arbol.Add(nodo.valor);

            if (nodo.nodoDer != null)
                Listar(nodo.nodoDer, arbol);

            return arbol;
        }
    }
}

Seguir

Get every new post delivered to your Inbox.