Pues eso, ¿me podriais decir que está mal en esta linea?
y1=y1+(int)cos(x)*rand()%(-((int)sin(x)*rand()%5))+((int)sin(x)*rand()%5);
La compilo y todo bien, pero luego me da error al ejecutar el programa. y1 y x son enteros. Gracias
¿Qué error te da?
¿Qué lenguaje/herramienta estás usando para compilar?
Lo más seguro es que esté dándote un error "división por cero" (esto es una suposición). Declara una variable para el divisor y comprueba que no sea cero (o un número muy próximo a cero) antes de dividir.
Saludos
Offtopic: ¡Vaya firmita! :huh: Haber->A ver (Powered by MarsCorrector)
Uso Visual C++ 6. Y si, creo que casi podria ser lo que tu dices, ya que esto da valores muy bajos (a proposito, claro), 800 veces, asi que va a ser eso.¿Como podria arreglarlo? Porque nesesito que me de cero de vez en cuando.
Gracias.
Offtopic:
Lo tendré en cuenta :rolleyes: .
Te aconsejo que no pongas tantas cosas en una misma línea. No te preocupes por usar variables intermedias (de todas formas el compilador va a usar temporales anónimos).
Probablemente el fallo sea la división por cero entera en el primer %. Además, es extraño hacer el % usando un número negativo como denominador... no sé si habrá fallo conceptual por lo que la pregunta sería ¿qué quieres hacer?
El objetivo era hacer un generador de terrenos 2d en plan worms. Pero visto lo visto, casi que mejor lo dejo :P .
Sin mirar los otros replies:
Citar(-((int)sin(x)*rand()%5))+((int)sin(x)*rand()%5)
puede es cero si x=0 y si haces % 0 da error de division.
Ademas te anuncio que no es en la complejidad donde obtengo aleatoriedad.
Saludos
Una cosa pogancha. Yo con lo que sé de 4º de ESO supongo que no debería llevarte la contraria ( por tener una base matemática menor ). Pero si no me equivoco, el seno y el coseno devuelven un numero entre -1 y 1, por lo tanto la enorme mayoría de veces es decimal, y si lo conviertes en int...
¿ Me equivoco ?
Al convertirlo en int, por truncamiento te da 0 si 0 <= sin(x) < 1, es decir, para todos los valores positivos excepto el 1. Aunque por redondeo te daria igualmente 0 para -0.5 < sin(x) < 0.5.
CitarPero si no me equivoco, el seno y el coseno devuelven un numero entre -1 y 1, por lo tanto la enorme mayoría de veces es decimal, y si lo conviertes en int...
Si aceptas esta suposición, deberías especificar en la documentación de tu programa que éste petará aleatoriamente (me remito a la Ley de Murphy: si algo puede ir mal irá mal... aunque en realidad acaba yendo peor)
sync
Si lo conviertes en int se transforma en 0, y basta que una vez te de 0 para que Crash!!!.
Viendo mas en detalle tu ecuacion encuentro que tienes muchas mas posibilidades de que te de error de division, con los Rand%5 te da un numero de 0 a 4 con lo cual es un desastre tambien.
Mi consejo es que no debes usar tantos rand ni funciones tan rebuscadas, si te fijas, la mayoria de las funciones de aleatoriedad son muy sencillas para cualquier caso que represente.
CitarEl objetivo era hacer un generador de terrenos 2d en plan worms. Pero visto lo visto, casi que mejor lo dejo
Si lo dejas, mejor deja la programación, es la perceberancia lo unico que te puede llevar al exito.
Saludos y suerte.
Edit: Sync, se adelanto, y te respondió mas elegantemente, no es que no lo halla visto es que posteo a la vez, estabamos fuera de sync.
Cita de: "Pogacha"Si lo dejas, mejor deja la programación, es la perceberancia lo unico que te puede llevar al exito.
Hasta cierto limite. Si me tiro toda la tarde para hacer esto por gusto, que ni si quiera voy a usarlo y no sale, pues esperaré a saber más para hacerlo. Seguro que todos han dejado algo sin hacer alguna vez.
Yo lo que no entiendo de dónde sale una fórmula tan complicada para lo que dices. Es decir, no veo porqué no puedes hacer algo del estilo:
y1 = ( int )( rand() * ALTURA_MAXIMA );
Creo que con eso ya tienes de sobra para generar un terreno aleatorio. Luego podrias complicarlo un poco más usando interpolaciones, splines, fractales, etc... para obtener un terreno más realista.
sync
Cita de: "Sacrifai"Hasta cierto limite. Si me tiro toda la tarde para hacer esto por gusto, que ni si quiera voy a usarlo y no sale, pues esperaré a saber más para hacerlo. Seguro que todos han dejado algo sin hacer alguna vez.
Si cada vez que me encontrase con alguna complicacion tuviese ke abandonar mis proyectos no tendria nada en absoluto. 4 años me llevo desarrollar la
dx_lib32 entre que tuve aprender el uso de
directX y corregir multitud de fallos ilogicos que me generaba
Visual Basic pero ahi lo tienes, un proyecto terminado y que funciona.
Por muy complicado ke se te haga llevar a cabo algo nunca tires la toalla y sigue insistiendo por ke al final siempre encontraras la forma de seguir adelante, y si has dejar algo sin hacer que sea para retomarlo dentro de un tiempo, nunca para abandonarlo. Y aunque eso que estas haciendo no llegues a usarlo siempre aprenderas algo por poco que sea.
Momentos de falqueza los tenemos todos ;)
Salu2...
(ole) En fin, lo intentaré con formulas mas sencillas como la que dice synchrnzr. Si sale, ya os comentaré.
(ole)
pienso igual que los demas.
yo antes tambien dejaba los proyectos a medias, pero cuando has dejado unos cuantos descubres que si no lo acabas resolviendo, nunca sabras como hacerlo.
animo y que la sabiduria te acompañe.
si estas en 4to ESO y ya sabes programar, ole tus huevos, la mayoria de gente en 4to de ESO solo piensa en ****** si mismos en otro sentido, y culturizarse siempre es positivo.
hay un chaval de 16 años que desarrollo un videojuego de politica muy complicado, tanto IA com SIMULADOR y lo dicho, ole sus huevos
si kieres un terreno que sea conexo
yi = y(i-1) * ((-1)*(int)Rand(0,1)) * Rand(0,1);
hay otras formas de hacerlo, pero es una forma clara y concisa, no hay divisiones, no hay excepciones xD
Citaryi = y(i-1) * ((-1)*(int)Rand(0,1)) * Rand(0,1);
Buena idea, pero lo vuelve negativo, supongo que los * eran +:
Citaryi = y(i-1) + ((-1)*(int)Rand(0,1)) + Rand(0,1);
Siguiendo tu idea:
yi = y(i-1) + Rand(0,AMPLITUD) - AMPLITUD/2;
con AMPLITUD 1, 2 o 3 dependiendo de la pendiente maxima que quieras darle!
Conexo pero muy escabroso.
Siempre puedes usar una LUT (una tabla) para moldear la función de densidad (qué valores salen con más frecuencia que otros).
Un ejemplo muy muy sencillito
int Genera(void)
{
static int const LUT[8]={-2,-1,0,0,0,0,1,2};
return LUT[rand_int(0,7)];//Me he inventado rand_int(), pero está claro lo que hace ¿no?
}
Esta función te devuelve números enteros del -2 al 2, pero uno de cada dos números que devuelve es un cero.
Que quieres que salgan menos ceros, pues pones
{-2,-1,-1,0,0,1,1,2}
Que quieres más positivos que negativos
{-2,-1,0,0,1,1,2,2}
Y así vas moldeando.
A propósito, el orden da igual: {-2,-1,-1,0,0,1,1,2}
hace lo mismo que {0,1,-2,-1,0,2,1,-1}
Dos cosas:
- Adecúa el tamaño de tu tabla con lo que necesites/quieras
- Puedes precalcular los valores de la tabla y no tener que escribirlos a mano
- Con algo de paciencia se puede extender este método para flotantes mediante interpolación, aunque en este caso la tabla tiene que estar ordenada
Saludos
Con esto lo completa, como vez, con un solo rand puedes hacer todo lo que quieras, no necesitas funciones complejas, el tema de la derivacion numerica te vendria bien para entender el tema de las pendientes y la continuidad pero puedes pasarte esto por alto e inventar tus metodos matematicos simples para que la funcion quede adecuada a tus necesidades.
Debes ver ademas el tema de los filtros, para redondear las puntas.
Saludos.
Muchas gracias por las respuestas :D, por cierto, ¿sabeis alguna pagina con filtros para rendondear las puntas?
Para redondear las puntas escarpadas del terreno hay que pasar lo que en teoría de la señal se llama un filtro paso bajo o en procesamiento de imágenes un filtro de máscara con lo que se consigue un suavizado. Es una cosa muy tonta de hacer si las especificaciones no son muy estrictas (como en este caso). ;)
Basta con promediar cada valor v[x,y] con los valores vecinos:
nuevo_v[x,y]=0.5*v[x,y]+0.125*v[x-1,y]+0.125*v[x+1,y]+0.125*v[x,y-1]+0.125*v[x,y+1]
¡Y ya está! (uoh)
Notas:
- No uses v[x,y] como destino (nada de v[x,y]=0.5*....) Porque entonces vas a mezclar los valores nuevos con los viejos y se lía. Usa nuevo_v[] como un temporal y luego lo copias a v[]
- Ya imaginaras que esto de v[x,y] no es C++ (a no ser que sobrecargues el operador coma). Probablemente necesitaras algo como v[x+ANCHURA*y] aunque depende de cómo implementes el terreno.
- Por supuesto, hay que tener cuidado en los bordes del terreno.
- Puedes usar los valores v[x+1,y+1], v[x-1,y+1], etc.. pero tampoco es tan interesante. Icluso se pueden usar valores más lejanos, pero sin dejar huecos. Si usas v[x+3,y+1] deberías usar también v[x+2,y+1], v[x+1,y+1], v[x+1,y], etc. De todas las maneras, si lo pruebas, verás que no hay muchos cambios.
- Si te fijas la suma de los coeficientes es uno, eso mantendrá el nivel global del terreno. Aunque puedes hacer experimentos.
- Para que sea un paso bajo: Intenta que los coeficientes más cercanos al centro sean más grandes que los que estén más lejanos. No uses valores negativos en los coeficientes (nada de restas). No varíes los coeficientes bruscamente.
Espero que te sirva para empezar a suavizar esos terrenos. Luego pasaremos a las páginas de tratamiento de señal (es que son durillas de digerir). (nooo)
Saludos.
ostia si que eran + y no * xDDDD ya lo dije, tenia un examen en 10 minutos y contesté muy a saco ;)