오늘은 방향키를 통해
콘솔 창에서 방향키 인식 및 이동하는 방법에 대해서
알려드리겠습니다.
+ 깜빡깜빡거리는 커서 숨기는 함수까지!!
- _kbhit() 함수
방향키를 인식하기 전에
conio.h 헤더 파일에 들어있는,
_kbhit()함수를 사용해야 합니다.
_kbhit 이 함수는 키를 누른 경우 0이 아닌 값을 반환합니다.
따라서 키보드에 key를 누른 경우 0이 아닌 해당 key 값을
버퍼로 저장합니다.
(버퍼란 scanf()함수 등 을 통해 입력을 받으면, 화면에 출력되기 전까지 임시적으로 입력한 값들을 저장하는 메모리 상의 공간!!이라고 생각하시면 편합니다^..^)
따라서 버퍼에 저장된 key 값을 _getch()함수를 통해서 받아야 합니다.
이때 _getch()함수는
콘솔에서 단일 문자를 읽습니다!!
이때의 단일 문자는 _kbhit()함수에서 반환된 ,
사용자가 누른 key 값입니다.
이 key값을 _getch()함수를 통해 한 글자 읽어서
int 형으로 반환합니다.
#include <stdio.h>
#include <conio.h>
int main(void){
if(_kbhit()){ // Key를 누르면 0이아닌 int형의 값을 반환한다!! 따라서 if문이 실행된다!!
int nkey=_getch(); //반환된값을 _getch()를 통해 캣치!후 nkey값에 return 한다!!
}
}
이때의 nkey 값을 printf("%d", nkey);
를 할 경우 해당 key의 아스키 코드 값을 알 수 있습니다.
여기서 잠깐!!!!
방향키의 경우에는 특수키로 간주되어서 _khbit()함수는 2개의 정수 값을 return 합니다
첫 번째로 반환한 값의 경우에는
224로 어떤 방향키를 누르든 동일한 값을 반환합니다.
두 번째로 반환한 값에 따라서 상, 하, 좌, 우로 나뉘게 됩니다.
if (_kbhit()) {
int nkey = _getch(); //방향키의 경우 nkey값은 224!
if (nkey == 224) { //만약 nkey가 224, 공통적인 뱡향키의 첫번째 반환 값 이라면?
nkey = _getch(); //두번째 nkey 값을 받는다. 이때의 nkey 값에 따라 방향키가 결정된다.
}
}
UP키 아스키코드 값 = 72;
DOWN키 아스키 코드 값 = 80;
LEFT키 아스키 코드 값 = 75;
RIGHT키 아스키 코드 값 = 77;
이들의 공통적인 첫 번째 반환 값
ARROW 아스키코드 값 = 224;
기본적으로 C언어로 게임을 만들 때는 위의 아스키코드값들을
모두 #define 처리를 합니다. (있어 보이잖나~)
그래야 사용하기 편리합니다!!
또한 방향키로 물체를 이동시킬 때는
한번 누르고 끝이 아니라, 연속적이기 때문에
while문과, switch() 문을 사용해서 표현합니다.
만약에 추가적으로 한 개의 key값을 반환하는
SPACE 바 key 또한 인식시키고 싶을 때는 어떻게 해야 할까요?
(SPACE BAR 아스키코드 값 = 32)
요론 식으로!!
#include <stdio.h>
#include <conio.h>
#define LEFT 75
#define RIGHT 77
#define UP 72
#define DOWN 80
#define ARROW 224
#define SPACEBAR 32
int main(void) {
while (1) {
if (_kbhit()) {
int nkey = _getch();
if(nkey==SPACEBAR){
printf("space bar");
}
if (nkey == ARROW) {
nkey = _getch();
switch (nkey) {
case UP:
printf("up key");
break;
case LEFT:
printf("left Key");
break;
case RIGHT:
printf("right key");
break;
case DOWN:
printf("down key");
break;
}
}
}
}
return 0;
}
사용을 할 수 있습니다.
그렇다면 맨 처음의 동영상처럼
★ 별 모양을 콘솔 창에 방향키가 눌리는 방향으로
이동하는 방법은??
바로
GotoXY() 함수를 사용하여 이동시키면 되는 것입니다.
(GotoXY함수를 다룰 줄 모른다면?
아래 링크 정독 필수!!)
2021.09.06 - [C언어] - [C언어] GotoXY()함수로 콘솔 창의 커서를 내 마음대로 이동하기!
1. GotoXY()로 임의의 x, y좌표 값을 넣은 후, 별을 출력합니다.
2. UP키를 누를 경우, 임의의 x,y좌표 값에서 --y 한 값을 GotoXY(x,--y)로 대입 후,
3. system("cls"); 콘솔 창의 출력된 모든 내용을 지우는 함수. 을 통해
4. 콘솔 창을 비운 후 다시 printf("★");를 하면 되는 것입니다.
#include <stdio.h>
#include <Windows.h >
#include <conio.h>
#define LEFT 75
#define RIGHT 77
#define UP 72
#define DOWN 80
#define ARROW 224
void GotoXY(int x, int y) {
COORD Pos;
Pos.X = x;
Pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);
}
void CursorView(char show)
{
CONSOLE_CURSOR_INFO ConsoleCursor;
ConsoleCursor.bVisible = show;
ConsoleCursor.dwSize = 1;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ConsoleCursor);
}
int x = 30;
int y = 7;
int main(void) {
CursorView(0);
GotoXY(x, y);
printf("★");
while (1) {
if (_kbhit()) {
int nkey = _getch();
if (nkey == ARROW) {
nkey = _getch();
switch (nkey) {
case UP:
system("cls");
GotoXY(x, --y);
printf("★");
break;
case LEFT:
system("cls");
GotoXY(x=x-2, y);
printf("★");
break;
case RIGHT:
system("cls");
GotoXY(x=x+2, y);
printf("★");
break;
case DOWN:
system("cls");
GotoXY(x, ++y);
printf("★");
break;
}
}
}
}
return 0;
}
이때 CursorView(char show) 함수를 사용하였는데,
간략하게 이 함수를 설명하자면,
CONSOLE_CURSOR_INFO 구조체입니다.
dwSize( 단순히 커서의 크기를 정하는 변수입니다.)
bVisible(true일 경우 커서 값이 보이고, false 일 경우 커서 값을 숨깁니다.)
이 구조체를 ConsoleCursor로 선언 후, 구조체의 변수 값들, dwsize 크기 조정, bVisible 패널에 커서 보이기 true, 숨기기 false를 지정해 준 후, SetConsoleCursorPosition(지정된 콘솔 화면 버퍼에서 커서 위치를 설정해주는 함수)의 매개변수로 대입하면 커서의 크기, 콘솔에 커서 보이기, 숨기기 가 활성화되는 것입니다!
커서를 숨기고 싶다면
CursorView(false);
커서를 보이고 싶다면
CursorView(true);를 선언하면 됩니다!!
제 코드를 본 후 몇 번 따라서 nkey =_getch() 아래에
printf("% d", nkey);를 선언하여 키가 눌렸을 때 무슨 값을 반환하는가? 에 대해
몇 번 반복적으로 연습하시다 보면 자연스레 Key값을 받는 것은 익숙해지실 거예요.
질문은 환영합니다!!
'C언어 > 테트리스' 카테고리의 다른 글
[C언어] 초보자도 쉽게? 구현한 테트리스 게임 완성! (2) | 2021.09.13 |
---|---|
[C언어] 초보자도 구현할 수 있는 테트리스 게임 만드는법 ep.2 커서다루기, 블럭 응용 실전편 (0) | 2021.09.11 |
[C언어] GotoXY()함수로 콘솔 창의 커서를 내 마음대로 이동하는 방법 (0) | 2021.09.06 |
[C언어] 콘솔창에 출력되는 글자색 바꾸는 방법 (2) | 2021.09.05 |