Hola, no me sale hacer una cosa, necesito hacer que mi programa recorra 5 casilleros para detectar si hay algun obstaculo en medio o si el casillero esta ocupado partiendo de una posicion inicial que se encuentra dentro de una matriz hasta un destino que tambien se encuentra en la matriz..., quiero que se cumpla que si hay obstaculo no deje que se mueva el grafico y no se realiza el movimiento, si no hay obstaculo, que realice el movimiento.
Gracias.
Pues suena muy sencillo pero a ver:
1) ¿Usas BennuGD?
2) ¿Cómo has definido la matriz? ¿Por ejemplo te vale con una matriz de enteros en la que 1 indica "ocupada" y 0 "libre"?
Uso fenix, la matriz la he definido asi: CASILLAS[5][5]; osea que es un pequeño tablero de 6x6, mm, si, 0 seria libre y 1 seria ocupada..., necesito mover un grafico de una posicion a otra, pero esto sera posible solo si desde la posicion inicial hasta la posicion final o destino no se detecta obstaculo, de lo contrario no se realiza el movimiento.
Como hago esto?
http://es.wikipedia.org/wiki/Algoritmo_de_b%C3%BAsqueda_A*
Bueno, el link no se de que es, entro en la pagina pero no me dice nada, igual ya busque en google 'algoritmo de busqueda' y entre en una pagina que decia mas o menos como hacerlo, pero no me funciona..., tengo hecho esto:
//si el valor de la posicion inicial seleccionada es igual a 2
IF(TABLA[POSX][POSY]==2)
//y si la posicion destino es igual a la posicion inicial mas dos posiciones arriba...
IF(DESX==POSX AND DESY==POSY+2)
//recorre casilleros desde la posicion inicial hasta la posicion destino en busca de obstaculos,
o numeros que no sean 0
[b] (*)[/b]
//si encuentra un '1' en el camino...
IF(TABLA[POSX][VY]==1)
//deja de recorrer y no se realiza el movimiento de posicion inicial- a destino
BREAK;
END
END
//si no encuentra obstaculos o numeros distintos de 0, se realiza el movimiento..
ELSE
TABLA[DESX][DESY]=2; //ocupa la posicion destino con el nuevo valor
TABLA[POSX][POSY]=0; //la posicion inicial la deja libre
END
END
Pero esto no me funciona, aunque haya obstaculo (numero distinto de cero), realiza el movimiento igual, traspasandolo..., alguien puede ayudarme?
gracias..
(*) FOR(VY=POSY; VY<DESY; VY++) este for, va donde esta el asterisco arriba en el code
lo puse ahi abajo porque me salia mal el codigo.
ups, que raro, el asterísco no se queda dentro del enlace.
bueno, prueba con este otro
Algorito de búsqueda A* (http://es.wikipedia.org/wiki/Algoritmo_de_b%C3%BAsqueda_A*)
La cosa es que hay miles de algoritmos para hacer lo que quieres, incluso bennugd tiene una funcion para ello, path_find (http://forum.bennugd.org/index.php?topic=667.0).
Ah...xD, creo que no se me entendio lo que realmente quiero hacer jeje ,aver..., mejor lo muestro con imagenes.
Las posiciones se ordenan por x e y, numero antes de la coma es la x, numero despues de la coma es la y.
Ok, lo que quiero hacer es esto:
(http://img291.imageshack.us/img291/5776/imagen1wn.png)
En esa imagen, la casilla 0,2 esta ocupada, supongamos que quiero mover la bolita azul desde la posicion inicial en la que se encuentra (0,0) hasta la posicion destino que seria por ejemplo 0,3..., yo quiero que esto no sea posible, ya que estaria atravezando un obstaculo (la bolita roja, es decir la casilla 0,2, que se encuentra ocupada), casilla libre es 0, casilla ocupada vale 1, supongamos que la bolita azul vale 2, la roja vale 1 y las casillas vacias o libres valen 0.
Ok, supongo que ya se entiende mejor o no¿
en esta otra imagen:
(http://img139.imageshack.us/img139/3589/imagen2do.png)
si, es lo mismo, pero la casilla 0,2 esta libre, esa casilla valdria 0, entonces si quiero mover la bolita azul que vale 2 desde 0,0 (su posicion inicial) hasta 0,3 (destino), lo tiene que hacer sin problemas porque no hay obstaculo en medio.
A ver ahora si me podeis ayudar mejor...
Aclaracion: uso Fenix, no bennu.
Bueno, he hecho este ejemplo en bennu usando path_find, pruébalo y mira a ver si se ajusta a tus necesidades.
Program caminoCorto;
import "mod_path"
import "mod_map"
import "mod_video"
import "mod_key"
import "mod_mouse"
import "mod_proc"
import "mod_draw"
#define CASILLAS_WIDTH 16
#define CASILLAS_HEIGHT 16
Global
mapa, durezas;
jugador;
casillas[CASILLAS_WIDTH][CASILLAS_HEIGHT];
End
Begin
scale_resolution=m640x480;
set_mode(16,16,16);
set_fps(10,0);
// creamos puntero cuadrado
mouse.graph = new_map(1,1,16);
map_clear(0,mouse.graph,rgb(255,0,0));
// Creamos un mapa a recorrer, por defecto está todo a 0
casillas[2][2] = 1; //ponemos algunos obstáculsos
casillas[2][3] = 1;
casillas[2][5] = 1;
casillas[2][6] = 1;
casillas[6][1] = 1;
casillas[6][2] = 1;
// creamos un mapa con la información de casillas para pasar a path_find
durezas = new_map(CASILLAS_WIDTH,CASILLAS_HEIGHT,8); // la imagen de entrada a path_find solo puede ser de 8 bits
mapa = new_map(CASILLAS_WIDTH,CASILLAS_HEIGHT,16); // la imagen a mostrar
for (y = 0 ; y < CASILLAS_HEIGHT;y++)
for (x = 0 ; x < CASILLAS_WIDTH;x++)
if (casillas[x][y]==1)
map_put_pixel(0,durezas,x,y,255);
map_put_pixel(0,mapa,x,y,RGB(120,120,120));
else
map_put_pixel(0,durezas,x,y,0);
map_put_pixel(0,mapa,x,y,RGB(240,240,240));
end
end
end
//lo ponemos en la esquina superior izquierda
point_set(0,mapa,0,0,0);
p_mapa(mapa); //mostramos en pantalla
jugador = player(1,1); // ponemos al jugador
while (!key(_esc))
if (mouse.left)
while (mouse.left); frame; end
// Si la casilla en la que se encuentra el ratón es distinta de 1 y hay camino para llegar
if ((casillas[mouse.x][mouse.y]!=1) && (path_find(0, durezas, jugador.x, jugador.y , mouse.x , mouse.y ,1 )))
while ( path_getxy(&jugador.x, &jugador.y) AND not mouse.left )
frame;
end
end
end
frame;
end
let_me_alone();
unload_map(0,mouse.graph);
unload_map(0,mapa);
end
process player (x,y)
begin
z = -255;
graph = new_map(1,1,16);
map_clear(0,graph,rgb(0,0,255));
while (!key(_esc))
Frame;
end;
unload_map(0,mouse);
end
process p_mapa (graph)
begin
while (!key(_esc))
Frame;
end;
end
El ratón en un pixel gigante rojo, el objeto a mover es un pixel gigante azul, las casillas libres son pixeles blancos, y las casillas ocupadas son pixeles grises. Apunta con el ratón a cualquier lado del mapa y a ver si funciona como tu quieres.
El mapa lo he agrandado a 16,16 para ver más posibilidades pero puedes encogerlo a lo que necesites cambiando las constantes.
Yo creo que busca algo más sencillo que path_find, simplemente para mover las fichas a lo largo de una columna o de una fila, ¿Es así?
En ese caso puedes hacer:
FROM x = x_inicial TO x_final;
IF ( matriz [ x ] [ y ] != 0 )
RETURN FALSE;
ELSE
RETURN TRUE;
END
END
El código anterior sirve para cuando se quiere mover en una fila y siempre y cuando la x final sea mayor que la inicial, pero a partir de él es trivial construir los 4 casos posibles.
:D, pues si.
Quote from: Windgate on October 13, 2010, 07:25:35 PM
Yo creo que busca algo más sencillo que path_find, simplemente para mover las fichas a lo largo de una columna o de una fila, ¿Es así?
En ese caso puedes hacer:
FROM x = x_inicial TO x_final;
IF ( matriz [ x ] [ y ] != 0 )
RETURN FALSE;
ELSE
RETURN TRUE;
END
END
El código anterior sirve para cuando se quiere mover en una fila y siempre y cuando la x final sea mayor que la inicial, pero a partir de él es trivial construir los 4 casos posibles.
Gracias por eso..., mm, ya tengo hecho que se mueven las fichas y eso..., mas bien lo que busco es que, el movimiento o desplazamiento a lo largo de la fila o columna desde una posicion inicial a una posicion final sea posible solo si no se encuentran casillas ocupadas en medio de este desplazamiento, osea entre punto A y punto B (punto A seria posicion inicial, no hablo de path find ni nada de eso, punto B seria posicion final o destino) para que el movimiento sea valido, tienen que haber todas casillas que por valor tengan cero, osea, estan libres..., si se encuentra un 1, el movimiento no se realiza.
Entonces con mi solución te sobra, el path find es para movimientos más complejos, en plan laberintos y cosas así xD
-.- xD, me dices que con tu solucion me sobra pero donde esta la solucion? xd, osea, con ese codigo que me has puesto lo que se logra es que el objeto o lo que sea se mueva a traves de las filas, columnas o lo que sea..., pero a ver nose si es que no me leen bien..., el movimiento esta muy bien, se mueve y todo pero no se como agregarle a ese codigo que me has puesto o directamente no se como hacer para que solo se mueva (de pos inicial a pos final) si comprueba que desde la pos inicial hasta la pos final no encuentra ningun obstaculo! me falta esa comprobacion, que compruebe si desde la casilla inicio hasta la final hay o no hay un obstaculo, si encuentra una casilla de valor 1 hay obstaculo entonces se cancela el movimiento y no puedes moverte hasta alli..., de lo contrario si desde pos inicial hasta pos final solo se ven ceros (casilleros libres), entonces puedes trasladarte tranquilamente hasta alli, hasta esa casilla..., porque significaria que no hay nada, no hay obstaculos.
Quote from: Windgate on October 13, 2010, 07:25:35 PM
Yo creo que busca algo más sencillo que path_find, simplemente para mover las fichas a lo largo de una columna o de una fila, ¿Es así?
En ese caso puedes hacer:
FROM x = x_inicial TO x_final;
IF ( matriz [ x ] [ y ] != 0 )
RETURN FALSE;
ELSE
RETURN TRUE;
END
END
El código anterior sirve para cuando se quiere mover en una fila y siempre y cuando la x final sea mayor que la inicial, pero a partir de él es trivial construir los 4 casos posibles.
Creo que te pasaste un pequeño error: el from no va a avanzar nunca al pillar un return si o si. En su lugar yo pondría:
FROM x = x_inicial TO x_final;
IF ( matriz [ x ] [ y ] != 0 )
RETURN FALSE; //si pilla un obstaculo, devuelve false, osea que no se puede realizar el movimiento
END
END
RETURN TRUE; //si llega a este punto es por que el camino está libre, es decir puede realizar el movimiento
END
Me refería a un FROM dentro de una FUNCTION, para que la función retorne el valor indicando si el movimiento es posible o no.
Hola, sube el proyecto tal cual lo tienes y le echo un vistazo, si es medianamente legible te lo dejo listo y comentado.
A ver si esto te vale. Son dos funciones. dados dos puntos que comparten una misma coordenada "Y" comprueba que no hay obstaculos en la matriz casillas. Y la segunda hace lo mismo pero con dos puntos que comparten una misma coordenada "X"
Function sepuedellegar_en_x(x_inicial,x_final,y)
private
origen, destino;
begin
if (x_inicial < x_final)
origen=x_inicial;
destino = x_final;
else
origen = x_final;
destino =x_inicial;
end
FROM x = origen TO destino;
IF ( casillas [ x ] [ y ] != 0 )
RETURN FALSE; //si pilla un obstaculo, devuelve false, osea que no se puede realizar el movimiento
END
END
RETURN TRUE; //si llega a este punto es por que el camino está libre, es decir puede realizar el movimiento
end
Function sepuedellegar_en_y(y_inicial,y_final,x)
private
origen, destino;
begin
if (y_inicial < y_final)
origen=y_inicial;
destino = y_final;
else
origen = y_final;
destino =y_inicial;
end
FROM y = origen TO destino;
IF ( casillas [ x ] [ y ] != 0 )
RETURN FALSE; //si pilla un obstaculo, devuelve false, osea que no se puede realizar el movimiento
END
END
RETURN TRUE; //si llega a este punto es por que el camino está libre, es decir puede realizar el movimiento
end
Como llamo a esa funcion? if(sepuedellegar_en_y(x_inicial,x_final,x)==1) etc.,?
PD: Windgate, te he enviado un mensaje privado.
Lo siento... Ese código me hace saltar las lágrimas, todo mayúsculas, sin comentarios, sin tabulados, sin espaciado, comprobaciones que pueden resumirse en una instrucción...
IF(BOARD[DESX][DESY]<>12 AND BOARD[DESX][DESY]<>1 AND BOARD[DESX][DESY]<>2 AND BOARD[DESX][DESY]<>3 AND BOARD[DESX][DESY]<>4 AND BOARD[DESX][DESY]<>5 AND BOARD[DESX][DESY]<>6)
IF(BOARD[DESX][DESY]<>7 AND BOARD[DESX][DESY]<>8 AND BOARD[DESX][DESY]<>9 AND BOARD[DESX][DESY]<>10 AND BOARD[DESX][DESY]<>11)
No me atrevo a meter mano, ¿Lo estás haciendo por tu cuenta o para un trabajo?, te lo digo por pedir ayuda a tu profesor personalmente... La solución está en usar un FROM, lo de DCelso sería perfecto.
Quote from: Hola on October 14, 2010, 04:28:14 PM
Como llamo a esa funcion? if(sepuedellegar_en_y(x_inicial,x_final,x)==1) etc.,?
PD: Windgate, te he enviado un mensaje privado.
Pues mas o menos.
A ver, con ejemplo práctico, te encuentras en la casilla (2,1), hay un obstáculo en la casilla (4,1), y quieres llegar a la (5,1)
pues como ves la "y" permanece fija entonces estás buscando en la "x", así que llamarias a sepuedellegar_en_x.
La llamada sería la siguiente:
if (sepuede_llegar_en_x(2,5,1))
// me muevo a la casilla (5,1)
else
// muestro mensaje de error
end
Quote from: Windgate on October 14, 2010, 07:17:25 PM
Lo siento... Ese código me hace saltar las lágrimas, todo mayúsculas, sin comentarios, sin tabulados, sin espaciado, comprobaciones que pueden resumirse en una instrucción...
IF(BOARD[DESX][DESY]<>12 AND BOARD[DESX][DESY]<>1 AND BOARD[DESX][DESY]<>2 AND BOARD[DESX][DESY]<>3 AND BOARD[DESX][DESY]<>4 AND BOARD[DESX][DESY]<>5 AND BOARD[DESX][DESY]<>6)
IF(BOARD[DESX][DESY]<>7 AND BOARD[DESX][DESY]<>8 AND BOARD[DESX][DESY]<>9 AND BOARD[DESX][DESY]<>10 AND BOARD[DESX][DESY]<>11)
No me atrevo a meter mano, ¿Lo estás haciendo por tu cuenta o para un trabajo?, te lo digo por pedir ayuda a tu profesor personalmente... La solución está en usar un FROM, lo de DCelso sería perfecto.
ostia, que guapo el código, :D, Hola te recomiendo que le pases el bennuindent mío o de splinter. :D
Bueno, lo hice como dijo DCelso, hice la funcion y la llamada a la funcion, al principio no me funcionaba, tenia un problema con la variable del FROM, que siempre permanecia en cero, no realizaba comprobaciones y ya estaba escribiendo aqui el proximo mensaje preguntando como solucionarlo jeje, pero antes de enviar el mensaje me puse a probar una ultima cosa y me salio xD
if (x_inicial < x_final)
origen=x_inicial;
destino = x_final;
else
origen = x_final;
destino =x_inicial;
end
Eso en realidad yo lo habia cambiado por:
ORIGEN=x_inicial;
DESTINO=x_final;
Dejandolo asi, no me realizaba comprobaciones, lo unico que tuve que hacer para solucionar el problema es poner ORIGEN=x_inicial+1; y ahi funciono xd
Gracias a todos por su ayuda! ;D me ha servido mucho.
Prueba el siguiente código:
TAMANOX = tamaño tablaX;
TAMANOY = tamaño tablaY;
PROCESS movimiento (int vector, int x,int y)
PRIVATE
int indiceX;
int indiceY;
int bloqueado;
BEGIN
//RESET variables
bloqueado = 0;
//Comprobamos si el movimiento es horizontal
if (vector == 1)
//Recorremos toda la tabla en horizontal desde la posicion indicada.
for (indiceX = x; indiceX < TAMANOX; indiceX++)
if (tabla[indiceX][indiceY] != 0)
bloqueado++;
END
//El movimiento es vertical
ELSE
//Recorremos toda la tabla en vertical desde la posicion indicada.
for (indiceY = y; indiceY < TAMANOY; indiceY++)
if (tabla[indiceX][indiceY] != 0)
bloqueado++;
END
END
return bloqueado;
END
* Esta funcion retorna 0 en caso de no encontrar casillas ocupadas en dicho vector, y en caso de encontrar casillas ocupadas, el numero de estas.
* Si te interesa limitar el final del vector, pasa por parametros X1, y Y1 y cambias en el "FOR" TAMANO* por X1 o Y1, según te convenga.
* Si te interesa que se pueda hacer la comprobación al reves (descendente) tienes varias maneras de hacerlo. La más facil es añadir una nueva variable de control que ejecute el mismo código que el anterior, sustituyendo > por < y VARIABLE++ por VARIABLE--.
No lo he probado, pero en esencia es lo más sencillo que necesitas para poder hacer la verificación que pides.
También añado que deberías hechar un ojo a los distintos sistemas de bucles (for, while y loop) y entender en que casos se utilizan cada uno de ellos, es básico.
Espero haber servido de ayuda.
Saludos!
Quote from: Hola on October 15, 2010, 02:19:57 PM
Bueno, lo hice como dijo DCelso, hice la funcion y la llamada a la funcion, al principio no me funcionaba, tenia un problema con la variable del FROM, que siempre permanecia en cero, no realizaba comprobaciones y ya estaba escribiendo aqui el proximo mensaje preguntando como solucionarlo jeje, pero antes de enviar el mensaje me puse a probar una ultima cosa y me salio xD
if (x_inicial < x_final)
origen=x_inicial;
destino = x_final;
else
origen = x_final;
destino =x_inicial;
end
Eso en realidad yo lo habia cambiado por:
ORIGEN=x_inicial;
DESTINO=x_final;
Dejandolo asi, no me realizaba comprobaciones, lo unico que tuve que hacer para solucionar el problema es poner ORIGEN=x_inicial+1; y ahi funciono xd
Gracias a todos por su ayuda! ;D me ha servido mucho.
:), mucha razón tienes se me saltó el detallito de esquivar la casilla donde te encuentras :D,
Entonces para que el código funcione de izquierda a derecha y de derecha a izquierda debería quedar así
if (x_inicial < x_final)
origen=x_inicial+1;
destino = x_final;
else
origen = x_final;
destino =x_inicial+1;
end
Revivo el tema, tengo problemas con la comprobacion de casillas en diagonal.., esta bien puesto esto?
Function sepuedellegar_en_xy(POSX,DESX,POSY,VALOR,DESY)
private
origen, destino;
ORIGEN2, DESTINO2;
begin
ORIGEN=POSX+VALOR;
DESTINO=DESX;
ORIGEN2=POSY+VALOR;
DESTINO2=DESY;
FROM VX=ORIGEN TO DESTINO;
FROM VY=ORIGEN2 TO DESTINO2;
IF ( BOARD [ VX ] [ VY ] != 0 )
RETURN FALSE; //si pilla un obstaculo, devuelve false, osea que no se puede realizar el movimiento
END
END
END
RETURN TRUE; //si llega a este punto es por que el camino está libre, es decir puede realizar el movimiento
end
Para comprobar las diagonales, esta bien hecho ese codigo¿
Function sepuedellegar_en_xy(x1,y1,x2,y2)
private
origenx, destinox;
origeny, destinoy;
incremento;
vx,vy;
begin
if ( x1 < x2 )
origenx =x1;
origeny =y1;
destinox =x2;
destinoy =y2;
else
origenx =x2;
origeny =y2;
destinox =x1;
destinoy =y1;
end
if (origeny < destinoy )
incremento = 1;
else
incremento = -1;
end
vy = origeny;
FROM VX=ORIGENx TO DESTINOx;
IF ( BOARD [ VX ] [ VY ] != 0 )
RETURN FALSE; //si pilla un obstaculo, devuelve false, osea que no se puede realizar el movimiento
END
vy=vy+incremento;
END
RETURN TRUE; //si llega a este punto es por que el camino está libre, es decir puede realizar el movimiento
end
DCelso, a lo tuyo le falta algún paréntesis, lo de Hola aisladamente lo veo bien, siempre y cuando no haya nombres de privadas/globales/procesos iguales o algo así se ve correcto.
sip, es verdad, puto mayor que y menor que, que se creía el editor que eran inicio y o fin de secciones html :D.
En cuanto al código de hola, no está nada bien, no puedes hacer un from anidado porque recorres n*m veces la matriz.
Gracias DCelso, funciono de maravilla.
de na, ahora te falta entenderlo :D
Dale un karma, ¿No ves que está abriendo el pico para comérselo?
::)