TEMA 2.1
DETECCIÓN DE TECLAS PULSADAS
CON LA FUNCIÓN INKEY$





2.1.1 - USO DE LA FUNCIÓN INKEY$

La función INKEY$ nos devuelve el contenido del buffer del teclado, es decir, cual es la última tecla o combinación de teclas que se ha pulsado. Esta función es más primitiva que INPUT, pero no la pudimos ver en el tema de entrada y salida básica porque todavía no sabíamos cómo usar los bucles, algo imprescindible para usar esta función ya que el programa no se detiene como ocurre con la instrucción INPUT. También hay que tener en cuenta que no es algo básico de la teoría de programación, ya que en otros lenguajes puede que funcione de formas muy distintas.

Para usar la función lo que haremos es almacenar su valor en una variable, ya que al leer el valor de INKEY$ el carácter que contenga se borra del buffer de teclado y ya no lo veremos más.
Vamos con el primer ejemplo:

CLS
tecla$ = INKEY$
PRINT tecla$

Este ejemplo funciona, aunque al ejecutarlo no lo parezca. Lo que hace es borrar la pantalla, almacenar la última tecla pulsada (durante el tiempo de vida del programa) en la variable tecla$ y a continuación escribirla en pantalla. Lo que pasa es que como el programa no se detiene no nos da tiempo a pulsar ninguna tecla y no aparece nada en pantalla, salvo el conocido rótulo "Presione cualquier tecla y continúe".

Para solucionar esto tenemos que recurrir a los bucles y programar lo que se conoce como "mecanismo de espera activa". Allá vamos, el siguiente fragmento de código será de los más usados en juegos y programas interactivos hechos con QBasic:

DO
	tecla$=INKEY$
LOOP WHILE tecla$=""

Al hacer esto se entra en un bucle que lee continuamente la entrada de teclado y la almacena en la variable tecla$. No salimos del bucle mientras no pulsemos nada y la variable tecla$ siga estando vacía. Una vez que pulsemos una tecla esta quedará almacenada en la variable para usarla más adenante donde haga falta.

Esto ya funciona bien, pero todavía no es infalible. Puede ocurrir que en el buffer del teclado quede alguna pulsación de tecla residual de alguna instrucción de entrada anterior y que al llegar aquí se salte la espera. Para que esto no ocurra tendremos que "limpiar el buffer del teclado" antes de entrar al bucle. Para hacerlo usaremos otro bucle que lee las posibles teclas (y las va borrando) del buffer hasta que se quede vacío. Vamos a ver un ejemplo completo que espera a que pulsemos una tecla y la saca por pantalla. El primer bucle, de tipo WHILE, corresponde a la limpieza del buffer y el segundo, de tipo DO..LOOP, a la espera activa.

CLS
WHILE INKEY$<>""
WEND
DO
	tecla$=INKEY$
LOOP WHILE INKEY$=""
PRINT tecla$

Como se puede ver, este bucle de limpieza es un bucle WHILE, es decir, un bucle rechazable. Si el buffer ya está vacío ni siquiera entramos, en caso contrario entramos y leemos y borramos la tecla que pudiera tener antes de ir al otro bucle de reconocimiento de teclas.





2.1.2 - RECONOCIMIENTO DE TECLAS ESPECIALES

Como hemos dado por supuesto en los ejemplos anteriores las teclas se almacenan en el buffer del teclado usando el código ASCII o la representación del carácter que llevan. Por ejemplo la "a minúscula" se almacena como "a" o su código ASCII que es el 97, la "a mayúscula" lo hace como "A" o 65, el número cinco como "5" o 53, el punto como "." o 46 , el espacio en blanco como " " o 32 y así con todos los caracteres que tenemos en la sección alfanumérica del teclado.

Para trabajar con los códigos ASCII usaremos la conocida función CHR$(), de esta forma es lo mismo decir...

IF tecla$ = "A" THEN

...que...

IF tecla$ = CHR$(65) THEN

De esta forma también podemos identificar otras teclas solo con conocer su código ASCII. Estos son algunos de los más usados:

Escape.....: 27
Enter......: 13
Tabulador..: 9
Retroceso..: 8

También es posible identificar las teclas especiales de flechas (Imprescindible para los juegos), las teclas de función y las otras como Inicio, Fin, Insertar, etc.
Al pulsar estas teclas se almacenan en el buffer del teclado dos caracteres, siendo el primero el CHR$(0). Para identificar estas teclas no hay más que usar en las comprobaciones CHR$(0)+El carácter que tengan asignado, aquí va una lista de los más usados:

Flecha arriba......: CHR$(0)+"H"
Flecha abajo.......: CHR$(0)+"P"
Flecha izquierda...: CHR$(0)+"K"
Flecha derecha.....: CHR$(0)+"M"

F1.................: CHR$(0)+";"
F2.................: CHR$(0)+"<"
F3.................: CHR$(0)+"="
F4.................: CHR$(0)+">"

F5.................: CHR$(0)+"?"
F6.................: CHR$(0)+"@"
F7.................: CHR$(0)+"A"
F8.................: CHR$(0)+"B"

F9.................: CHR$(0)+"C"
F10................: CHR$(0)+"D"
F11................: CHR$(0)+CHR$(133)
F12................: CHR$(0)+CHR$(134)

Insertar...........: CHR$(0)+"R"
suprimir...........: CHR$(0)+"S"
Inicio.............: CHR$(0)+"G"
Fin................: CHR$(0)+"O" (Letra o mayúscula)
Retroceder página..: CHR$(0)+"I" (Letra i mayúscula)
Avanzar página.....: CHR$(0)+"Q"

Podemos ver una lista completa en la ayuda en pantalla de QBasic en el apartado llamado "Códigos de exploración del teclado". Aquí también aparecen los códigos de teclas combinadas como por ejemplo CONTROL+Z.

Vamos a ver un ejemplo final de un programa que reconozca todas las teclas alfanuméricas normales además de Enter, Escape y las flechas que son especiales. En temas siguientes cuando hagamos programas más "bonitos" usaremos ampliamente el reconocimiento de teclas.

CLS
PRINT "Pulsa las teclas que quieras, escape para salir"
PRINT
DO
   WHILE INKEY$ <> "": WEND 'Limpia buffer de entrada
   DO
      tecla$ = INKEY$
   LOOP WHILE tecla$ = ""
   SELECT CASE tecla$
      CASE CHR$(0) + "H": PRINT "Has pulsado la flecha arriba"
      CASE CHR$(0) + "P": PRINT "Has pulsado la flecha abajo"
      CASE CHR$(0) + "K": PRINT "Has pulsado la flecha izquierda"
      CASE CHR$(0) + "M": PRINT "Has pulsado la flecha derecha"
      CASE CHR$(13): PRINT "Has pulsado Enter"
      CASE CHR$(27): PRINT "Has pulsado Escape, adios"
      CASE " ": PRINT "Has pulsado la barra de espacio"
      CASE ELSE: PRINT "Has pulsado la tecla " + tecla$
   END SELECT
LOOP UNTIL tecla$ = CHR$(27)

Observa que este programa no reconoce las teclas de función, entre otras, para hacerlo no hay más que añadir las instrucciones CASE con los códigos correspondientes.





2.1.3 - HACER PAUSAS EN LOS PROGRAMAS

Una forma muy sencilla de detener la ejecución de un programa, por ejemplo para que el usuario pueda leer algo es usar la instrucción SLEEP. Al usar esta instrucción el programa se detiene hasta que el usuario pulse una tecla. Si añadimos un número a continuación, por ejemplo:

SLEEP 10

Ocurrirá que el programa se detendrá por un máximo de 10 segundos, continuando pasado este tiempo automáticamente aunque el usuario no pulse ninguna tecla.

Esta instrucción funcionará en la mayoría de los casos, pero puede ocurrir que alguna vez no llegue a detener el programa porque hay datos residuales en el buffer de entrada, en estos casos podremos usar lo que hemos visto en el apartado anterior: Limpieza del buffer+Espera activa, es decir esto:

WHILE INKEY$<>"":WEND
DO:LOOP WHILE INKEY$=""

Esta estructura la podemos ampliar para hacer una pregunta al usuario y dejarle responder Sí o No pulsando S o N, por ejemplo.

WHILE INKEY$<>"":WEND
DO
	tecla$=INKEY$
LOOP UNTIL tecla$="S" OR tecla$="N"

Aquí entramos en el bucle de espera activa y no salimos hasta que el usuario pulse la S o la N, y después más adelante en el programa viendo el valor de tecla$ ya decidiríamos entre hacer algo o no. Pero todavía hay un problema, este ejemplo tal como está sólo reconoce la S y la N mayúsculas, por lo que si el usuario tiene el "Bloqueo de mayúsculas" desactivado puede que no se le ocurra como seguir. Para arreglar el problema usaremos la función UCASE$ que convierte todas las letras (Menos la Ñ y las vocales acentuadas) a mayúsculas. Vamos con el ejemplo completo:

CLS
PRINT "¿Quieres hacer no se qué? S/N: "
WHILE INKEY$<>"":WEND
DO
	tecla$=UCASE$(INKEY$)
LOOP UNTIL tecla$="S" OR tecla$="N"

IF tecla$="S" THEN
	PRINT "Has dicho que sí"
ELSE
	PRINT "Has dicho que no"
END IF

Ampliando más este ejemplo podríamos construir un menú "cutre". Si dejamos al usuario la posibilidad de pulsar más teclas, normalmente números, y después los comprobamos con un SELECT CASE podríamos decidir entre hacer varias cosas. Es una estructura similar a la usada en el ejemplo de reconocer teclas del apartado anterior.













CuRSo De iNTRoDuCCióN a La PRoGRaMaCióN CoN QBaSiC
© 2004 Juan M. González