elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.
 
Inicio Ayuda Ingresar Registrarse
31 Julio 2010, 07:47  


Temas destacados: Últimos eventos sobre seguridad/inseguridad



+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET
| | | |-+  [APORTE] Usando consola con Threads (aka: consola estilo quake) :D
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Imprimir
Autor Tema: [APORTE] Usando consola con Threads (aka: consola estilo quake) :D  (Leído 527 veces)
raul338
Grupo de Trabajo
*
Desconectado Desconectado

Mensajes: 751


Mister .net


Ver Perfil WWW
[APORTE] Usando consola con Threads (aka: consola estilo quake) :D
« en: 06 Marzo 2010, 17:27 »

 :D Hoola!

Venia preparando esto desde hace tiempo, pero siempre aparecian algun problema de "cuentas" y se desfiguraba todo jaja  :laugh:

En fin, Tuve que usar threads para una aplicacion que hice, y decidi hacerlo en consola (uff... para que  :xD)

En fin, el programa hacia lo que queria que haga, peeero...  necesitaba ejecutar "comandos" introducidos por el usuario, y a la vez el programa debia reportar algunos  datos al usuario. Como era de suponerse hacia un ReadLine y en otro thread usaba WriteLine cuando era necesario. Ahi surgio un problema, se cruzaba todo haciendo todo ilegible al volver a leer, les pongo un ejemplo grafico:

Escenario: Un servidor de juegos... Al estilo Half-Life  :xD

Código:
Log:
Nivel 1 iniciado
esperando respuesta....
_

si yo pongo un comando ("agregar bot 1") pero en medio de la escritura entra un jugador .... se reporta como "Nuevo jugador: -xDMan-", se pone justo apenas terminamos de escribir la letra en la que estabamos, se escribe el reporte y despues nosotros seguimos escribiendo. Queda horrible!!!

Empezamos a escribir el comando:
Código:
Log:
Nivel 1 iniciado
esperando respuesta....
agregar b_

Entra el usuario, interrumpiendo nuestro comando
Código:
Log:
Nivel 1 iniciado
esperando respuesta....
agregar bNuevo jugador: -xDMan-_

Si seguimos escribiendo (supongamos que no nos dimos cuenta que salio eso)
Código:
Log:
Nivel 1 iniciado
esperando respuesta....
agregar bNuevo jugador: -xDMan-ot 1_

y el ReadLine devuelve bien: agregar bot 1

pero cuando lees la consola directa, es total mente ilegible, todo mezclado  :¬¬


y aca idee los metodos necesarios para resolverlo  ;)

Son dos funciones que reemplazan a Console.WriteLine y Console.ReadLine

ReadLine: es muy similar al Console.ReadLine, pero tiene un buffer en el que se guarda el string escrito
WriteLine: lo que hace es "borrar" de la consola lo escrito y poner lo que se quiere introducir, y luego abajo poner exactamente lo que habiamos puesto (desde el buffer :P) y todo haciendo parecer que no paso nada.

Usando mis metodos ReadLine y WriteLine, quedaria asi

Empezamos a escribir el comando:
Código:
Log:
Nivel 1 iniciado
esperando respuesta....
agregar b_

Entra el usuario, interrumpiendo nuestro comando
Código:
Log:
Nivel 1 iniciado
esperando respuesta....
Nuevo jugador: -xDMan-
agregar b_

seguimos escribiendo como si nada hubiera pasado
Código:
Log:
Nivel 1 iniciado
esperando respuesta....
Nuevo jugador: -xDMan-
agregar bot 1_

y el ReadLine devuelve bien (como era de esperarse): agregar bot 1


Como les dije, es una consola al estilo quake (porque en quake se vio la primera consola asi, de ahi el nombre)


Sin mas, aca esta el codigo, A mas de uno le puede servir  ;-)
(no se necesita ninguna referencia, nada, esta todo listo para servir  :laugh:)


Código
// Si uno hace un WriteLine mientras se espera un ReadLine pasa esto:
// "probando              // Si antes de que ponga la ultima comilla pongo un Console.WriteLine("Hola") queda asi
// "progandoHola
// "
//
// La siguentes funciones estan hechas para evitar eso
// By Raul338 (proximamente: raul338.com.ar)
static string buffer = "";
/// <summary>Escribe un texto sin "cortar" o interrumpir un Console.ReadLine()</summary>
/// <param name="Text">Texto a escribir</param>
static void WriteLine(string Text)
{
   // Guarda la ubicacion actual (la linea se le suma 1, porque es la que sigue)
   int lastLeftPos = Console.CursorLeft;
   int lastTopPos = Console.CursorTop +1;
 
   // Lineas de lo que se va a escribir y lo escrito a mano
   int lineas = ObtenerLineas(Text);
   int lineasEscritas = ObtenerLineas(buffer);
 
   // Esto equilibra algunas cuentas
   if (lastTopPos != 0)
       if (lineasEscritas < 1)
           lastTopPos -= 1;
 
   // Ponemos el cursor al principio de la linea que empezamos a escribir y borramos lo escrito
   Console.SetCursorPosition(0, lastTopPos - lineasEscritas);
   Console.Write("".PadLeft(buffer.Length)); // Aca vaciamos todo :P
   Console.SetCursorPosition(0, lastTopPos - lineasEscritas);
 
   // Escribimos el texto
   Console.WriteLine(Text);
 
   // Ponemos en el cursor en el nuevo lugar (lugarAnterior + las nuevas lineas)
   Console.SetCursorPosition(0, lastTopPos + lineas - lineasEscritas);
 
   // Ponemos lo que el usuario habia escrito anteriormente
   Console.Write(buffer);
}
 
/// <summary>Obtienes las lineas que ocupa el texto introducido en consola</summary>
/// <param name="input">Texto a contar las lineas</param>
/// <returns>Lineas que ocupa en consola</returns>
/// <!-- By Raul338 -->
static int ObtenerLineas(string input)
{
   int lineas = 0;
   // Separamos el texto en lineas
   System.Text.RegularExpressions.Match matchResult = System.Text.RegularExpressions.Regex.Match(input, @"[^\r\n]*(?:\r\n)?");
   while (matchResult.Success)
   {
       // Por alguna razon se incluyen capturas vacias o_O
       if (matchResult.Value != "")
       {
           // La expreision regular tambien cuenta los cierre de lineas, asi que los separamos
           int enter = matchResult.Value.IndexOf(System.Environment.NewLine);
 
           string final = matchResult.Value;
           if (enter >= 0)
               final = matchResult.Value.Substring(0, enter);
 
           // Hacemos la division, sera una linea, pero en consola no entra como tal y se dividen en lineas
           lineas += Convert.ToInt32(final.Length / Console.WindowWidth) + 1;
       }
       matchResult = matchResult.NextMatch();
   }
   return lineas;
}
 
/// <summary>ReadLine 2.0 para poder Escribir a la vez</summary>
/// <returns>El texto escrito</returns>
static string ReadLine()
{
   string result = "";
   // Lee cada tecla presionada
   ConsoleKeyInfo t = Console.ReadKey(false);
   while (t.Key != ConsoleKey.Enter)
   {
       // En caso de que borre, se quita el ultimo caracter
       if (t.Key == ConsoleKey.Backspace && buffer.Length > 0)
       {
           Console.Write(" ");
           Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
           buffer = buffer.Substring(0, buffer.Length - 1);
       }
       else
       {
           // Es un caracter cualquiera, se agrega al string
           buffer += t.KeyChar.ToString();
       }
       t = Console.ReadKey(false);
   }
   Console.WriteLine();
   // Se vacia el buffer y se devuelve lo escrito
   result = buffer;
   buffer = "";
   return result;
}
 


Y aca un pequeño ejemplo: Un thread con un bucle infinito que muestra numeros sucesivos en la pantalla, y ustedes pueden escribir lo que sea

Código
static void Main(string[] args)
{
   // Empezamos el relleno
   Thread t = new Thread(Rellena);
   t.Start();
 
   string comando;
   do
   {
       // Al mismo tiempo que escribimos se separa lo que se va a mostrar de lo que escribimos
       comando = ReadLine();
       WriteLine(DateTime.Now.ToString("HH:mm:ss") + System.Environment.NewLine +" - " + comando);
   } while (comando != "salir");
 
   t.Abort();
}
 
 
// Iteracion infinita para rellenar la consola
static void Rellena()
{
   int i = 0;
   while (true) {
       WriteLine(i.ToString());
       if (i == int.MaxValue) i = 0;
       i++;
       Thread.Sleep(1000);
   }
}
 


Espero que lo prueben, y les guste  :)

Cualquier critica (constructiva) es recibida   ;)
En línea

Páginas: [1] Ir Arriba Imprimir 
Ir a:  





Consolas     La Web de Goku     MilW0rm     MundoDivx

Hispabyte     Truzone     TodoReviews     ZonaPhotoshop

Yashira.org    Videojuegos    indetectables.net    Seguridad Informatica Colombia    Indejuegos    Internet móvil    Juegos de Mario

Noticias Informatica    Seguridad Informática    ADSL    eNYe Sec    Seguridad Wireless    Underground México    Biblioteca de Seguridad

Todas las webs afiliadas están libres de publicidad engañosa.

Powered by SMF 1.1.11 | SMF © 2006-2008, Simple Machines LLC