34. Frontón (3): Raqueta simultánea

Dibujar una raqueta que se mueve a la vez que la pelota tampoco es especialmente difícil: no debemos usar directamente "ReadKey", o el juego se quedaría parado hasta que se pulse una tecla, pero podemos comprobar si hay una tecla pendiente con "KeyAvailable", y en ese caso sí leemos la tecla y vemos si es alguna de la que nos interesan:

if(Console.KeyAvailable)
{
    tecla=Console.ReadKey(false);
    if(tecla.Key == ConsoleKey.RightArrow
                && xRaqueta < 79 - raqueta.Length)
        xRaqueta += 2;
    if(tecla.Key == ConsoleKey.LeftArrow
                && xRaqueta > 2)
        xRaqueta -= 2;
}

En este ejemplo, nuestra raqueta se mueve de 2 en 2 y la pelota de en 1, para darnos alguna oportunidad de alcanzarla, y que así el juego sea un poco más jugable.

El resultado puede ser:

// Fronton - version 3: raqueta que se mueve de lado a lado
 
using System;
using System.Threading;
 
public class Fronton03
{
  public static void Main()
  {
    char pelota = 'O';
    int x = 40; // Posición de la pelota
    int y = 12;
    int xRaqueta = 39;  // Posición de la raqueta
    int yRaqueta = 22;
    int incrX = 1; // Incremento (velocidad) de la pelota
    int incrY = -1;
    int minX = 0, maxX = 79; // Límites horizontales
    int minY = 0, maxY = 23; // Límites verticales
    bool terminado = false;
 
    string raqueta = "________";
    ConsoleKeyInfo tecla;
 
    // Ladrillos del fondo
    string[] ladrillos =
      { 
        "-------=-------=-------=-------=----------------",
        "------=-=-----=-=-----=-=-----=-=---------------",
        "-----=---=---=---=---=---=---=---=--------------",
        "----=-----=-=-----=-=-----=-=-----=-------------",
        "---=-------=-------=-------=-------=------------"
      };
 
 
    do
    {
      // Dibujo los ladrillos y la pelota
      Console.Clear();
      foreach( string filaLadrillos in ladrillos)
        Console.WriteLine( filaLadrillos );
      Console.SetCursorPosition(x, y);
      Console.Write(pelota);
      Console.SetCursorPosition(xRaqueta, yRaqueta);
      Console.Write(raqueta);
 
      // Muevo la raqueta si se pulsa alguna tecla
      if(Console.KeyAvailable)
      {
          tecla=Console.ReadKey(false);
          if(tecla.Key == ConsoleKey.RightArrow
                      && xRaqueta < 79 - raqueta.Length)
              xRaqueta += 2;
          if(tecla.Key == ConsoleKey.LeftArrow
                      && xRaqueta > 2)
              xRaqueta -= 2;
      }
 
      // Compruebo colisiones con el fondo
      if ( ( y < ladrillos.Length)// Si estoy en vertical dentro del fondo
      && ( x < ladrillos[0].Length) // Y en horizontal
      && (ladrillos[y][x] != ' ')) // Y hay ladrillo
      {
        incrY = - incrY;
        // Borrar: no puedo hacer "ladrillos[y][x] = ' ';"
        ladrillos[y] = ladrillos[y].Remove(x, 1);
        ladrillos[y] = ladrillos[y].Insert(x, " ");
      }
 
      // Compruebo si llego al límite de la pantalla
      // Si se sale por abajo...
      if ( y >= maxY )
      {
        // Recolocar pelota y raqueta
        x = 40;
        y = 12;
        xRaqueta = 39;
        yRaqueta = 22;
        incrX = 1;
        incrY = -1;
      }
      // Si llega a un extremo sin salir por abajo: rebota
      if ( (x <= minX) || (x >= maxX) )
        incrX = -incrX;
      if ( (y <= minY) || (y >= maxY) )
        incrY = -incrY;
 
      // Y paso a la siguiente posición
      x += incrX;
      y += incrY;
 
      // Y espero un poco hasta el siguiente fotograma
      Thread.Sleep( 40 );
    }
    while (!terminado);
  }
}
 

Ejercicio propuesto: Este fuente puede fallar si la pelota rebota "hacia arriba" cuando está en la primera línea; corrígelo.