Juego ASCII de Pong

10

Ascii Pong

El desafío es recrear el clásico juego "pong" en caracteres ASCII en el código más corto posible.

Requisitos / especificaciones

  • La "pantalla" debe tener 45x25 caracteres.
  • El espacio en blanco debería ser en realidad un espacio en blanco.
  • Las paletas deben ser 9 signos iguales: =========y deben estar en las filas más altas y más bajas (sé que el original se juega de lado a lado en lugar de arriba a abajo, pero creo que esto funciona mejor para ascii pong )
  • La pelota puede ser minúscula o mayúscula oo cero.
  • Dos botones de entrada de cualquier tipo (está bien si el usuario presiona una tecla que hace que aparezca una letra en la entrada, eso también está bien) para mover la paleta del jugador de izquierda a derecha uno o dos caracteres a la vez.
  • La pelota necesita rebotar en el ángulo apropiado al golpear una paleta o una pared (pista: negar el valor de diferencia x o y).
  • La puntuación debe mostrarse en algún lugar de la salida. El puntaje es cuántas veces el jugador golpea con éxito la pelota.
  • Si la pelota pierde la paleta del jugador, finalice el programa.
  • Debería haber algún tipo de IA (incluso si la paleta de la IA solo coincide con el valor x de la bola).
  • La pelota no puede viajar en línea recta vertical u horizontalmente.

La pantalla de inicio / primer fotograma debería verse así:

                  =========                  











                      o                      











                  =========                  
score: 0

Puntuación Este es el , por lo que gana el código más corto ... sin embargo, hay algunas bonificaciones para disminuir el recuento de tu personaje:

  • -30 caracteres: cambia la trayectoria de la pelota dependiendo de dónde golpea la pala
  • -10 personajes: haz que el juego se acelere con el tiempo
  • -20 caracteres: haz que la IA sea superable
  • -20 caracteres: evita cualquier situación en la que el jugador se quede quieto y el juego continúe para siempre sin ganar o perder (causado por ciertas trayectorias y patrones de IA)
  • -20 caracteres: hacer que la pelota comience a moverse en una trayectoria (semi) aleatoria
  • -25 caracteres: agregue una opción de reinicio

Aquí hay un ejemplo sin golf sin bonos en JavaScript:

//init
var x = 22,
    y = 12,
    xd = Math.random() < 0.5 ? -1 : 1,
    yd = 1,
    player = opponent = 18,
    score = 0,

//interval that runs 10x per second (minus the runtimeof one cycle)
interval = setInterval(function() {
  //move ball
  x += xd;
  y += yd;

  //move opponent
  opponent = x - 4;

  //collision with walls
  if(x <= 0 || x >= 44) xd = -xd;

  //collision with paddles
  if(y == 1) {
    if(x >= opponent && x < opponent + 9) yd = -yd;
    else {
      //you win
      clearInterval(interval);
      document.body.innerHTML = "You win!<br>Your score was: " + score;
      return;
    }
  }
  else if(y == 23) {
    if(x >= player && x < player + 9) {
      yd = -yd;
      score++;
    }
    else {
      //you lose
      clearInterval(interval);
      document.body.innerHTML = "You lose!<br>Your score was: " + score;
      return;
    }
  }

  draw();
}, 100);

function draw() {
  var body = document.body;
  body.innerHTML = "";
  for(var i = 0; i < 25; i++) {
    for(var j = 0; j < 45; j++) {
      //white space is default
      var char = " ";
      
      //ball
      if(j == x && i == y) char = "o";
      
      //paddles
      if(i === 0) {
        if(j >= opponent && j < opponent + 9) char = "=";
      }
      else if(i == 24) {
        if(j >= player && j < player + 9) char = "=";
      }
      
      body.innerHTML += char;
    }
    body.innerHTML += "<br>";
  }
  body.innerHTML += "score: " + score;
}

//key press listener for left and right movement
window.onkeydown = function() {
  if (window.event.keyCode == 37) player -= 2;
  else if(window.event.keyCode == 39) player += 2;
};
<body style="font-family: monospace; white-space: pre">
  
</body>

¡Que empiecen los juegos!

Eric Vincent
fuente
3
De acuerdo, ¿alguien puede al menos explicar por qué rechazaron esto? Tengo curiosidad porque pensé que sería divertido, pero no tengo mucha experiencia.
Eric Vincent
3
Imprimir cosas ASCII está bien, pero con la interacción del teclado tendríamos que construir una aplicación completa. Ese tipo de desafíos están mal vistos porque muchos idiomas no admiten E / S de esa manera. Implementando una IA, física. Casi como una aplicación a gran escala. Si observa otros desafíos, tienen una tarea que toma una entrada (o no) y produce una salida relevante. Agregar una interacción de inteligencia artificial, física y teclado es demasiado para un desafío
Downgoat
1
@vihan la IA para pong es extremadamente simple, solo tiene que seguir el valor x de la pelota. Incluso hacer que sea vencible no es tan difícil, solo limite la velocidad desde la pala. El único problema real con el concepto es la interacción del teclado, que se puede gestionar en una variedad razonable de idiomas. Sin embargo, el informe es bastante vago y abierto (dado que somos rigurosos por la inequívoca y la imparcialidad por aquí), y la gran variedad de bonos no ayuda.
Level River St
1
relevante: meta.codegolf.stackexchange.com/q/5521/15599
Level River St
2
La interacción del teclado también tuvo que resolverse en (Re) Implementación de Tetris , pero eso no disminuyó la popularidad de la tarea. (Sí, lo sé, eso fue realmente un concurso de popularidad , esto no lo es). Lo único que personalmente encuentro inquietante es la cantidad de bonos. Pero ciertamente no tiene que estar a mi gusto.
manatwork

Respuestas:

4

Perl, 760611592 535 515 (640-30-10-20-20-20-25-25)

Una solución de consola con todas las bonificaciones.
Debería funcionar en cualquier terminal que entienda los códigos de escape ANSI (\ e [...]). Probado en cygwin.

Controles del teclado:
Izquierda: 4
Derecha: 6
Restablecer: 8

use Term::ReadKey;ReadMode 4;END{ReadMode 0}$|++;$a=$d=45;$b=25;$h=1;$j=$l=17;$p='='x9;sub P{print"\e[@_"}sub L{$%=$l+pop;if($%>0&$%+7<$a){P"25H\e[K\e[25;$%H$p ";$l=$%}}sub U{$%=$j+pop;if($%>0&$%+7<$a){P"1H\e[K\e[1;$%H$p ";$j=$%}}sub I{$}=int rand 42;$g=8;$i=1;P"2J\ec";L}I;while(1){if($c>0){$c--}else{$c=98;$d-=$d>6}if($c%9==0){U -1if$}<$j+4;U 1if$}>$j+6};if($c%$d==0){$m=$}+$h;$n=$g+$i;$h*=-1if$m<1||$m>$a;if($n>24&$}>=$l&$}<$l+9){$i*=-1;$h=-1if$m<$l+5;$h=1if$m>$l+5;$s++}if($n<2&$}>=$j&$}<$j+9){$i*=-1}P"$g;1H\e[K";$}+=$h;$g+=$i;P"$g;$}HO"}if($k=ReadKey -1){I,if$k>6;L$k<=>5}P"26;0Hscore:$s";exit,if$g>=$b;select($\,$\,$\,0.01);I,if$g<2}
LukStorms
fuente
1
¡Hola Luk, me encanta esto! Pensé que compartiría algunas formas en que podría guardar algunos caracteres más ... Ya que está usando printmás de 4 veces, debería ser más barato configurar un nuevo sub y llamar a eso sub p{print@_}. Si no le importa que se usen otras teclas además de las que usted especifica, puede reemplazarlas if(defined($k=ReadKey(-1))){L(-1)if's'eq$k;L(1)if'd'eq$k;I,if'r'eq$k}por L 114<=>ord$k if$k=ReadKey -1;. Esto solo convierte <r: -1, r: 0,> r: 1, que podría no ser lo que buscas. Si está satisfecho con esto, se podía utilizar [4] [5] [6] como las claves con: L$k<=>5 if$k=ReadKey -1;.
Dom Hastings
1
También parece que puede reemplazar algunos bloques if con una ifcomprobación de postfix o reemplazar con ternary para obtener más ahorros, pero eso podría resultar complicado con la anidación ... Tiene otro bloque al $d--if$d>6que puede cambiar $d-=$d>6para un ahorro de 2 bytes que podría funcionar en algunos lugares más también y otro pequeño ahorro es en ;$p=H.'='x9 .$"lugar de $p="H========= ". ¡Espero que algunos de estos sean útiles!
Dom Hastings
1
Gracias, me alegro de que te guste. ¡Tus consejos ayudaron a jugar más golf con 50 bytes! Ese truco con los ord es perverso. El truco $ d - = $ d> 6 se veía tan extraño. También descubrí que cuando imprimir algo como "$ aH" es un problema, que "$ {a} H" funciona como lo haría en bash. :)
LukStorms
1
¡Ah sí! Un par de formas de evitar eso usando nombres de variables no alfabéticos ( $}o algo así) o usando palabras vacías ( $a.H), no estoy seguro de si eso lo ayudará en este caso o no. Algo que noté es que sub P si alguna vez tiene un argumento, podría tenerlo en print"\e[@_"lugar de hacerlo, .popya que no habrá un separador de campo por el que preocuparse. Además, si está usando el teclado numérico en lugar de letras, no necesita usarlo ord, como $ksería 4o 6podría hacerlo en su 5<=>$klugar.
Dom Hastings
1
Gracias de nuevo. No pensé que Perl aceptaría variables como esa O_o. Pero funciona y algunos bytes fueron rescatados por eso. ¡Pero no intentes usar un $! variable. Cosas extrañas suceden entonces.
LukStorms
1

JavaScript, 618 bytes + HTML, 99 bytes

Bueno, aquí está mi respuesta JavaScript de golf, incluso si no es factible en otros idiomas:

var x,y,xd,yd,p,o,s,n,i,j,c,k;function a(){x=22;y=12;xd=Math.random()<.5?-1:1;yd=1;p=o=18;s=0;n=setInterval(function(){x+=xd;y+=yd;o=x-4;if(x<=0||x>=44)xd=-xd;if(y==1){if(x>=o&&x<o+9)yd=-yd;else{clearInterval(n);b.innerHTML="You Win!<br>Score: "+s;return}}else if(y==23){if(x>=p&&x<p+9){yd=-yd;s++;}else{clearInterval(n);b.innerHTML="You Lose!<br>Score: "+s;return}}d();},100);}function d(){b.innerHTML="";for(i=0;i<25;i++){for(j=0;j<45;j++){c=" ";if(j==x&&i==y)c="o"; if(i==0&&j>=o&&j<o+9)c="=";if(i==24&&j>=p&&j<p+9)c="=";b.innerHTML+=c;} b.innerHTML+="<br>";}b.innerHTML+="score: "+s;}onkeydown=function(){ k=window.event.keyCode;if(k==37)p-=2;if(k==39)p+=2;};
<button onclick="a()">start</button><div id="b"style="font-family:monospace;white-space:pre"></div>

-20 y -25 por bonificaciones

Eric Vincent
fuente
Hm, esto no me parece muy golfista. Todavía podría deshacerse de los nombres de variables de dos letras, sustituir algunos &&tokens &, eliminar muchos ;tokens, deshacerse de espacios innecesarios después {e incluso deshacerse de algunos caracteres de comillas en el HTML. Y probablemente mucho más, incluso. Esto es solo una suposición, pero es posible que desee intentar evitar UglifyJS y minificar a mano. :)
Chiru
66
Muy críptico publicado de esta manera. El lector tiene que buscar el código de 663 caracteres para el manejo de teclas, luego posiblemente STFW para averiguar qué teclas tienen los códigos 37 y 39. (De todos modos, no hay reacción en la tecla de flecha izquierda y derecha en el último Firefox que uso). al no poder probarlo, nunca sabré para cuál de los 3 bonos disponibles ganaste -20.
manatwork