Thursday, July 30, 2009

No quiero trabjar ni aprender, voy a reprobar!

El tema de hoy día es un tema muy importante y que hemos tocado en los comentarios de postes anteriores, alumnos que quieren aprobar sin trabajar y sin aprender. Pero, lamentable, no son tan bueno a la resolución de este problema tampoco.

Empezamos con un alumno desde este año en Lenguajes de Programación que ha entregado este código como su proyecto. ¿Cual es el problema de este código?



¿Nada, si? No hay comentarios, pero es bien programado. Incluye el uso de iterator. Que no he enseñado. Y que no creo que un alumno de segundo año va a utilizar. Este alumno recibió 1 para este proyecto. ¿Por qué? ¿Cómo podría saber? Primero, el alumno no supo cual es un iterator -- es demasiado avanzado por un alumno que no sabe C++. Además, yo se quien lo ha programado (no el alumno) y cuanto ha pagado ($7.000).

¿Muy mal, si? Yo se ningunos de ustedes harían esto..


La segunda programa viene desde Lenguajes de Programación el año pasado. Este programa no es tan mal tampoco, pero cuando lo revisé, encontré alguna cosa... familiar..



No tan mal... pero este es la pauta que di a mis ayudantes:



¡Si! Es un parte de la pauta (otra parte apreció en el proyecto de otro alumno) con los comentarios ingleses borrados! Muy bueno chicos, muy bueno. Profe no recordará su propio código.

¿Entonces, si un alumno está preparado para pagar por un proyecto, cómo pueden los profesores combatir este? Estos ejemplos son los que he detectado. ¿Que sobre los otros? Van a llegar a un punto donde encontrarán que necesitan estas capacidades, y no van a tenerlos... Y quizás van a aparecer aquí, como nuestra amigo de quinto año que no pudo programar un juego simple de gato.

Wednesday, July 22, 2009

Ciclos y arreglos

Este trocito de código viene desde mis chicos de Lenguajes de Programación este año, y no es solo un alumno, pero muchos en una prueba.

La tarea fue para escribir un método que cambia un elemento de un arreglo en C++.

void CD:modificarCancion(int elemento, string nueva)
{
for (int i=0; i<numCanciones; i++)
{
if (i==elemento)
cancion[i]=nueva;
}
}


¿Por qué este código es tan malo?

Saturday, July 18, 2009

Una respuesta (Parte B)

Ayer, vimos como podemos transformar 5 grandes secciones de código entre solo una sección. Deberían asegurar que entienden como el nuevo código funciona. No es tan difícil, sola una parte es complicado.. lo de verificar que los barcos no cruzan.

Hoy día vamos a ver como podemos utilizar los poderes de las clases (en Java, o cualquier otra lenguaje) a limpiar el código más.

Vamos a empezar con la sección del código mencionada arriba - la verificación del los barcos.

//verifcamos que el barco no cruza los barcos anteriores
for (int i=0; i<lista_barcos[barco_acutal].tamano; i++)
for (int j=barca_actual; j==0; j--)
{
//este es poquito sucio .. necesitamos verificar que ninguna de los coordenados en el barco actual son iguales a todos los coordenados de los barcos anteriores.

// asumimos que no cruzamos, si revisamos todos y todavia cruza es falso, bien.
boolean cruza=false;
for (int k=0; j<lista_barcos[j].posiciones.length; k++)
if (lista_barcos[j].posiciones[k].equals(lista_barcos[barco_acutal].posiciones[i]))
cruza=true;
}


¿Que hace este código? En pseudocódigo:

Para cada barco B antes el barco actual
Revisamos todos los posiciones en B y verifica que ninguna es la misma que nuestra barca actual.


Ayer, definimos una clase para representar un barco. Dijimos que esta clase es como un struct en C. Es verdad, pero no es todo. Clases son mucho mas poderosos que esta.. podemos definir métodos que operan a los datos al dentro la clase. Es como una paquete -- datos y métodos.

Entonces vamos a redefinir la clase a ser:

public class Barco
{
//los datos
public String nombre; // guardar el nombre del barco
public Point[] posiciones; // una lista de puntos donde el barco es ubicado
public int tamano; // El tamano del barco, i.e., el numero de espacios que tiene

//los metodos
public boolean esCruzado(Barco b1) //comparar el barco en este clase con otro barco b1.
{
boolean cruza=false;
for (int i=0; i<this.posiciones.length; ++i)
for (int k=0; j<b1.posiciones.length; ++k)
if(b1.posiciones[k].equals(this.posiciones[i]))
cruza=true;
return cruza;
}
}


Ahora cada barco que creamos tiene un método esCruzado que podemos utilizar para ver si otro barco se cruza.

Con este método definido, podemos mejorar el código poquito más. En vez del código complejo arriba, podemos escribir:


boolean cruza=false;
//verifcamos que el barco no cruza los barcos anteriores
for (int j=barca_actual; j==0; j--)
{
if (lista_barcos[barco_acutal].esCruzado(lista_barcos[j]))
cruza=true;
}


¿Mucho más entendible, si? El arte de programación es este proceso que acaba de hacer. Tomamos algoritmos complejos y intentamos a reducirlos a una forma simple y entendible.

Ahora.. preguntas para ustedes:

1) ¿Es un ciclo for la mejor manera para hacer esta? ¿Exista una forma más eficiente?

2) ¿Pueden identificar otra métodos que podemos agregar al código nuevo para limpiarlo más?

3) ¿Pueden identificar el error de lógica en el código que acabamos de escribir? ¿Exista en el código anterior? ¿Es más fácil para identificar ahora?

Friday, July 17, 2009

Una respuesta (Parte A)

La semana pasada, vimos un método mal escrito.. podemos aclarar que está haciendo este método?

Primero podemos identificar la estructura mas alta:


while (bandera==1)
{
} //fin del ciclo, termino de la creacion del barco portavion
while (bandera==2)
{
} //fin del ciclo while, termino de la creacion del barco acorazado
while (bandera==3)
{
} //fin del ciclo while para crear el barco crucero
while (bandera==4)
{
} //fin del ciclo, que crea el barco submarino
while (bandera==5)
{
} //fin del ciclo, creacion del barco destructor
while (bandera==6)
{
// colocar el barcos en un tablero
}

¡Aha! ¡Entonces, estamos creando 5 barcos y colocándolos en un tablero !

Bueno, dejamos esta estructura por el lado por un momento. ¿Que pasa al dentro cada uno de estos ciclos?

1: Ingresar las coordinados
2: Pregunta si queremos poner el barco vertical o horizontal
3: Pregunta si queremos poner el barco a lado izquierdo o derecha
4: Verificamos que podemos fiscalmente colocar el barco en el tablero a este punto
5: Verificamos que podemos colocar el barco sin tocando otro barco


¿Que sobre los barcos, donde guardamos la información sobre ellos? En los parámetros de método, entonces:

int columna_des,int columna_sub,int columna_cru,int columna_aco,int columna_por,int fila_des,int fila_sub,int fila_cru,int fila_aco,int fila_por,int aux_des,int aux_sub,int aux_cru,int aux_aco,int aux_por, int aux1_des,int aux1_sub,int aux1_cru,int aux1_aco,int aux1_por,int aux2_sub,int aux2_cru,int aux2_aco,int aux2_por,int aux3_sub,int aux3_cru,int aux3_aco,int aux3_por,int aux4_aco,int aux4_por,int aux5_aco, int aux5_por,int aux6_por,int aux7_por


Ok. Bien. ¿Como podemos limpiar está método?

Primero, sería ideal si podemos identificar las cosas comunes de los barcos y abstraerlos, con este podemos evitar mucha de la complejidad de el método viejo. ¿Cuales son los datos esenciales para un barco?

1: Su Nombre - Crucero, Submarino, Portaaviones, Destructor, Acorazado.
2: Su Posición o espacios ocupados - una lista de filas y columnas, o, podemos decir puntos.
3: Su Tamaño - el tamaño de la lista de puntos.

Bueno, si estamos programando en C, podemos usar un struct para guardar esta información. Pero este es Java y no tiene structs. Pero tiene classes..


public class Barco
{
public String nombre; // guardar el nombre del barco
public Point[] posiciones; // una lista de puntos donde el barco es ubicado
public int tamano; // El tamano del barco, i.e., el numero de espacios que tiene
}


Este es equivalente a un struct en C, y con este podemos guardar toda la información de un barco.

Ahora, reescribimos el método como así:




¿Poquito mejor, si? Pero todavía podemos limpiar mas. Vamos a ver como en Parte B de este post.

Friday, July 10, 2009

El ganador para lo más parametros es:

El código para esta semana es desde un programa que debería jugar un juego de batalla naval. Sorprendentemente este código realmente funciona. ¿Podemos identificar su faltas numerosas? ¿O mejor, podemos descifrar como funciona? ¿Si encuentras este código en un programa que necesitas mantener, que harías?

The code from this week is from a program that should play a game of Battleship. Surprisingly, this code really works. Can we identify its numerous problems? Or better, can we decipher how it works? If you found this code in a program that you needed to maintain, what would you do?

Friday, July 3, 2009

Malo Gato

Esta entrada vinó desde un alumno de mi clase de Inteligencia Artificial, un curso de quinto año. Debería ser un programa que puede jugar un juego perfecto de gato (Tic-Tac-Toe). Como este alumno ha llegado al quinto año sin usar funciones, no se...




#include <stdio.h>
#include <stdlib.h>

main()
{
int t,i,x,y;
char tablero[3][3];

for(t=0; t<3; ++t){
for(i=0; i<3; ++i){
tablero[t][i]='-';
}
}
for(t=0; t<3; ++t)
{
for(i=0; i<3; ++i)
printf("%c",tablero[t][i]);
printf("\n");
}

printf("seleccione posicion x:");
scanf("%d", &x);
printf("seleccione posicion y:");
scanf("%d", &y);

tablero[x][y] = 'x';
for(t=0; t<3; ++t)
{
for(i=0; i<3; ++i)
printf("%c",tablero[t][i]);
printf("\n");
}
printf("\n");

if(tablero[1][1]!='-')
{
tablero[0][0] = 'o';
}
else{
tablero[1][1]='o';
}
for(t=0; t<3; ++t)
{
for(i=0; i<3; ++i)
printf("%c",tablero[t][i]);
printf("\n");
}
printf("seleccione posicion x:");
scanf("%d", &x);
printf("seleccione posicion y:");
scanf("%d", &y);
printf("\n");

tablero[x][y]='x';

for(t=0; t<3; ++t)
{
for(i=0; i<3; ++i)
printf("%c",tablero[t][i]);
printf("\n");
}

if((tablero[1][1]=='x'){
if( (tablero[2][2]=='x')||(tablero[2][0]=='x'){
tablero[2][0]='o';
}
//if(tablero[][]){

//}
}
printf("seleccione posicion x:");
scanf("%d", &x);
printf("seleccione posicion y:");
scanf("%d", &y);
printf("\n");

tablero[x][y]='x';



}

Thursday, June 25, 2009

¿Que son ciclos?

Esta primera entrada es en Java y es desde mi curso de Lenguajes de Programación en 2009. ¿Pueden identificar porque es tan mala? Personalmente yo puedo pensar de otra forma para hacer lo mismo sin ciclos, y será mas elegante. ¿Algunas Sugerencias?

public void cantidad_jugadores( ActionEvent e) {
if(valor_nulojug[0]==0){
System.out.println("Primero Establezca La Cantidad de Jugadores en la \n Partida haciendo click en el Boton de jugadores \n mas abajo ");
}else{
int valor = valor_nulo[0];
if(valor==0){
if(cantidad_jug[0]==8){
System.out.println("Nombre del Jugador 1");
linea = in.readLine();
Nombre_jug1[1] = linea;
System.out.println("Nombre del Jugador 2");
linea = in.readLine();
Nombre_jug1[2] = linea;
System.out.println("Nombre del Jugador 3");
linea = in.readLine();
Nombre_jug1[3] = linea;
System.out.println("Nombre del Jugador 4");
linea = in.readLine();
Nombre_jug1[4] = linea;
System.out.println("Nombre del Jugador 5");
linea = in.readLine();
Nombre_jug1[5] = linea;
System.out.println("Nombre del Jugador 6");
linea = in.readLine();
Nombre_jug1[6] = linea;
System.out.println("Nombre del Jugador 7");
linea = in.readLine();
Nombre_jug1[7] = linea;
System.out.println("Nombre del Jugador 8");
linea = in.readLine();
Nombre_jug1[8] = linea;
valor_nulo[0]=1;
}

if(cantidad_jug[0]==7){
System.out.println("Nombre del Jugador 1");
linea = in.readLine();
Nombre_jug1[1] = linea;
System.out.println("Nombre del Jugador 2");
linea = in.readLine();
Nombre_jug1[2] = linea;
System.out.println("Nombre del Jugador 3");
linea = in.readLine();
Nombre_jug1[3] = linea;
System.out.println("Nombre del Jugador 4");
linea = in.readLine();
Nombre_jug1[4] = linea;
System.out.println("Nombre del Jugador 5");
linea = in.readLine();
Nombre_jug1[5] = linea;
System.out.println("Nombre del Jugador 6");
linea = in.readLine();
Nombre_jug1[6] = linea;
System.out.println("Nombre del Jugador 7");
linea = in.readLine();
Nombre_jug1[7] = linea;
valor_nulo[0]=1;
}


if(cantidad_jug[0]==6){
System.out.println("Nombre del Jugador 1");
linea = in.readLine();
Nombre_jug1[1] = linea;
System.out.println("Nombre del Jugador 2");
linea = in.readLine();
Nombre_jug1[2] = linea;
System.out.println("Nombre del Jugador 3");
linea = in.readLine();
Nombre_jug1[3] = linea;
System.out.println("Nombre del Jugador 4");
linea = in.readLine();
Nombre_jug1[4] = linea;
System.out.println("Nombre del Jugador 5");
linea = in.readLine();
Nombre_jug1[5] = linea;
System.out.println("Nombre del Jugador 6");
linea = in.readLine();
Nombre_jug1[6] = linea;

valor_nulo[0]=1;
}

if(cantidad_jug[0]==5){
System.out.println("Nombre del Jugador 1");
linea = in.readLine();
Nombre_jug1[1] = linea;
System.out.println("Nombre del Jugador 2");
linea = in.readLine();
Nombre_jug1[2] = linea;
System.out.println("Nombre del Jugador 3");
linea = in.readLine();
Nombre_jug1[3] = linea;
System.out.println("Nombre del Jugador 4");
linea = in.readLine();
Nombre_jug1[4] = linea;
System.out.println("Nombre del Jugador 5");
linea = in.readLine();
Nombre_jug1[5] = linea;


valor_nulo[0]=1;
}


if(cantidad_jug[0]==4){
System.out.println("Nombre del Jugador 1");
linea = in.readLine();
Nombre_jug1[1] = linea;
System.out.println("Nombre del Jugador 2");
linea = in.readLine();
Nombre_jug1[2] = linea;
System.out.println("Nombre del Jugador 3");
linea = in.readLine();
Nombre_jug1[3] = linea;
System.out.println("Nombre del Jugador 4");
linea = in.readLine();
Nombre_jug1[4] = linea;


valor_nulo[0]=1;
}

if(cantidad_jug[0]==3){
System.out.println("Nombre del Jugador 1");
linea = in.readLine();
Nombre_jug1[1] = linea;
System.out.println("Nombre del Jugador 2");
linea = in.readLine();
Nombre_jug1[2] = linea;
System.out.println("Nombre del Jugador 3");
linea = in.readLine();
Nombre_jug1[3] = linea;

valor_nulo[0]=1;
}

if(cantidad_jug[0]==2){
System.out.println("Nombre del Jugador 1");
linea = in.readLine();
Nombre_jug1[1] = linea;
System.out.println("Nombre del Jugador 2");
linea = in.readLine();
Nombre_jug1[2] = linea;

valor_nulo[0]=1;
}

}