How to 'enter' as soon as you press a key? [duplicate] - c++

This question already has answers here:
Capture characters from standard input without waiting for enter to be pressed
(21 answers)
Closed 4 years ago.
I have a program where a certain sound is played corresponding to a key pressed on the keyboard. But every time I press a key, I have to press Enter for the sound to be played. What I actually want to do is to press the key without having to press Enter and a sound should be played. How can I do this?
I'm using Windows 10. Here is my code:
while(1)
{
cin>>button;
switch (button)
{
case 'q':
PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\ardha chapu.wav"),NULL,SND_SYNC );
break;
case 'w':
PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\chapu"),NULL,SND_SYNC );
break;
case 'e':
PlaySound( TEXT("C:\\Users\\Gumm\\Downloads\\real sound of notes\\dheem"),NULL,SND_SYNC );
break;
default:
printf("No sound");
}
}

Assuming you already have a working program (except mandatory pressing of return key), here is a solution specific to your problem:
#include <ncurses.h>
int kbhit(void)
{
int ch = getch();
if (ch != ERR) {
ungetch(ch);
return 1;
}
else
return 0;
}
int main(void)
{
initscr();
cbreak();
noecho();
while (true) {
if (kbhit()) {
switch(getch())
{
case 10:
printw("Return key pressed!\n");
// your code to play a sound when `return` key pressed
break;
case 110: // for small `n`
case 78: // for capital `N`
printw("N or n key pressed!\n");
// your code to play sound when `n` or `N` key pressed
break;
// ...
}
refresh();
}
}
return 0;
}

Related

i cant know how two values return at same time from one variable in cpp [duplicate]

I'm writing a programm that's using getch() to scan for arrow keys. My code so far is:
switch(getch()) {
case 65: // key up
break;
case 66: // key down
break;
case 67: // key right
break;
case 68: // key left
break;
}
Problem is that when I press 'A', 'B', 'C' or 'D' the code will also executed, because 65 is the decimal code for 'A', etc...
Is there a way to check for an arrow key without call others?
Thanks!
By pressing one arrow key getch will push three values into the buffer:
'\033'
'['
'A', 'B', 'C' or 'D'
So the code will be something like this:
if (getch() == '\033') { // if the first value is esc
getch(); // skip the [
switch(getch()) { // the real value
case 'A':
// code for arrow up
break;
case 'B':
// code for arrow down
break;
case 'C':
// code for arrow right
break;
case 'D':
// code for arrow left
break;
}
}
getch () function returns two keycodes for arrow keys (and some other special keys), as mentioned in the comment by FatalError. It returns either 0 (0x00) or 224 (0xE0) first, and then returns a code identifying the key that was pressed.
For the arrow keys, it returns 224 first followed by 72 (up), 80 (down), 75 (left) and 77 (right). If the num-pad arrow keys (with NumLock off) are pressed, getch () returns 0 first instead of 224.
Please note that getch () is not standardized in any way, and these codes might vary from compiler to compiler. These codes are returned by MinGW and Visual C++ on Windows.
A handy program to see the action of getch () for various keys is:
#include <stdio.h>
#include <conio.h>
int main ()
{
int ch;
while ((ch = _getch()) != 27) /* 27 = Esc key */
{
printf("%d", ch);
if (ch == 0 || ch == 224)
printf (", %d", _getch ());
printf("\n");
}
printf("ESC %d\n", ch);
return (0);
}
This works for MinGW and Visual C++. These compilers use the name _getch () instead of getch () to indicate that it is a non-standard function.
So, you may do something like:
ch = _getch ();
if (ch == 0 || ch == 224)
{
switch (_getch ())
{
case 72:
/* Code for up arrow handling */
break;
case 80:
/* Code for down arrow handling */
break;
/* ... etc ... */
}
}
So, after alot of struggle, I miraculously solved this everannoying issue !
I was trying to mimic a linux terminal and got stuck at the part where it keeps a command history which can be accessed by pressing up or down arrow keys. I found ncurses lib to be painfuly hard to comprehend and slow to learn.
char ch = 0, k = 0;
while(1)
{
ch = getch();
if(ch == 27) // if ch is the escape sequence with num code 27, k turns 1 to signal the next
k = 1;
if(ch == 91 && k == 1) // if the previous char was 27, and the current 91, k turns 2 for further use
k = 2;
if(ch == 65 && k == 2) // finally, if the last char of the sequence matches, you've got a key !
printf("You pressed the up arrow key !!\n");
if(ch == 66 && k == 2)
printf("You pressed the down arrow key !!\n");
if(ch != 27 && ch != 91) // if ch isn't either of the two, the key pressed isn't up/down so reset k
k = 0;
printf("%c - %d", ch, ch); // prints out the char and it's int code
It's kind of bold but it explains alot. Good luck !
The keypad will allow the keyboard of the user's terminal to allow for function keys to be interpreted as a single value (i.e. no escape sequence).
As stated in the man page:
The keypad option enables the keypad of the user's terminal. If
enabled (bf is TRUE), the user can press a function key (such as an
arrow key) and wgetch returns a single value representing the function
key, as in KEY_LEFT. If disabled (bf is FALSE), curses does not treat
function keys specially and the program has to interpret the escape
sequences itself. If the keypad in the terminal can be turned on (made
to transmit) and off (made to work locally), turning on this option
causes the terminal keypad to be turned on when wgetch is called. The
default value for keypad is false.
Actually, to read arrow keys one need to read its scan code.
Following are the scan code generated by arrow keys press (not key release)
When num Lock is off
Left E0 4B
Right E0 4D
Up E0 48
Down E0 50
When Num Lock is on these keys get preceded with E0 2A
Byte E0 is -32
Byte 48 is 72 UP
Byte 50 is 80 DOWN
user_var=getch();
if(user_var == -32)
{
user_var=getch();
switch(user_var)
{
case 72:
cur_sel--;
if (cur_sel==0)
cur_sel=4;
break;
case 80:
cur_sel++;
if(cur_sel==5)
cur_sel=1;
break;
}
}
In the above code I have assumed programmer wants to move 4 lines only.
how about trying this?
void CheckKey(void) {
int key;
if (kbhit()) {
key=getch();
if (key == 224) {
do {
key=getch();
} while(key==224);
switch (key) {
case 72:
printf("up");
break;
case 75:
printf("left");
break;
case 77:
printf("right");
break;
case 80:
printf("down");
break;
}
}
printf("%d\n",key);
}
int main() {
while (1) {
if (kbhit()) {
CheckKey();
}
}
}
(if you can't understand why there is 224, then try running this code: )
#include <stdio.h>
#include <conio.h>
int main() {
while (1) {
if (kbhit()) {
printf("%d\n",getch());
}
}
}
but I don't know why it's 224. can you write down a comment if you know why?
for a solution that uses ncurses with working code and initialization of ncurses see getchar() returns the same value (27) for up and down arrow keys
I have written a function using getch to get arrow code. it's a quick'n'dirty solution but the function will return an ASCII code depending on arrow key :
UP : -10
DOWN : -11
RIGHT : -12
LEFT : -13
Moreover,with this function, you will be able to differenciate the ESCAPE touch and the arrow keys. But you have to press ESC 2 time to activate the ESC key.
here the code :
char getch_hotkey_upgrade(void)
{
char ch = 0,ch_test[3] = {0,0,0};
ch_test[0]=getch();
if(ch_test[0] == 27)
{
ch_test[1]=getch();
if (ch_test[1]== 91)
{
ch_test[2]=getch();
switch(ch_test[2])
{
case 'A':
//printf("You pressed the up arrow key !!\n");
//ch = -10;
ch = -10;
break;
case 'B':
//printf("You pressed the down arrow key !!\n");
ch = -11;
break;
case 'C':
//printf("You pressed the right arrow key !!\n");
ch = -12;
break;
case 'D':
//printf("You pressed the left arrow key !!\n");
ch = -13;
break;
}
}
else
ch = ch_test [1];
}
else
ch = ch_test [0];
return ch;
}
I'm Just a starter, but i'v created a char(for example "b"), and I do b = _getch(); (its a conio.h library's command)
And check
If (b == -32)
b = _getch();
And do check for the keys (72 up, 80 down, 77 right, 75 left)
void input_from_key_board(int &ri, int &ci)
{
char ch = 'x';
if (_kbhit())
{
ch = _getch();
if (ch == -32)
{
ch = _getch();
switch (ch)
{
case 72: { ri--; break; }
case 80: { ri++; break; }
case 77: { ci++; break; }
case 75: { ci--; break; }
}
}
else if (ch == '\r'){ gotoRowCol(ri++, ci -= ci); }
else if (ch == '\t'){ gotoRowCol(ri, ci += 5); }
else if (ch == 27) { system("ipconfig"); }
else if (ch == 8){ cout << " "; gotoRowCol(ri, --ci); if (ci <= 0)gotoRowCol(ri--, ci); }
else { cout << ch; gotoRowCol(ri, ci++); }
gotoRowCol(ri, ci);
}
}
Try this...
I am in Windows 7 with Code::Blocks
while (true)
{
char input;
input = getch();
switch(input)
{
case -32: //This value is returned by all arrow key. So, we don't want to do something.
break;
case 72:
printf("up");
break;
case 75:
printf("left");
break;
case 77:
printf("right");
break;
case 80:
printf("down");
break;
default:
printf("INVALID INPUT!");
break;
}
}

hold screen for accepting arrow keys

for using arrow keys, first it has to be stored for analyzing it. That's why I am using scanf to store it.
But when I try to run this code, and when I press up key, then it is showing ^[[A and when I press enter then this ^[[A removes and program exit without printing printf statement of printf("%s",c). and printf("UP\n").
#include <stdio.h>
int main()
{
char c[50];
scanf("%s",&c);
printf("%s",c);
if (getch() == '\033'){ // if the first value is esc
getch();// skip the [
getch();// skip the [
switch(getch()) { // the real value
case 'A':
printf("UP\n");
break;
case 'B':
printf("DOWN\n");
break;
}
}
return 0;
}
You will find it easy if you use the ncurses library. Just go through the documentation to see how to install it.
After installing read the part on Interfacing with the key board
Here is a sample code
#include <ncurses.h>
int main()
{
int ch;
initscr();
raw();
keypad(stdscr, TRUE);
noecho();
while(1)
{
ch = getch();
switch(ch)
{
case KEY_UP:
printw("\nUp Arrow");
break;
case KEY_DOWN:
printw("\nDown Arrow");
break;
case KEY_LEFT:
printw("\nLeft Arrow");
break;
case KEY_RIGHT:
printw("\nRight Arrow");
break;
}
if(ch == KEY_UP)
break;
}
endwin();
}

SDL 2 Space keydown not detected but Space keyup works fine

Hey so I'm working on a project/2d game and I'm having some odd behavior from SDL which I'm sure is probably something I'm not understanding. The function ProcessKeys is called and works fine for all the key press downs except SDLK_SPACE and I cannot for the life of me figure out why.
What is even more bizarre is that the SDL_KEYUP switch of SDLK_SPACE works great. I tried using some debugging code to print out which key is being pressed and when you press space down nothing registers. Every other key on the keyboard registers in my debug statement at the top of the SDL_KEYDOWN case.
If anyone can see what is going on I would really appreciate it.
And if you need to see where its being called let me know.
SDLKeyboard::KeyState SDLKeyboard::ProcessKeys(SDL_Event * event)
{
switch(event->type)
{
/* Look for a keypress */
case SDL_KEYDOWN:
{
std::cout << "Key currently pressed" << event->key.keysym.sym << std::endl;
/* Check the SDLKey values and move change the coords */
switch(event->key.keysym.sym)
{
case SDLK_LEFT:
{ // rotate the ship left
c.setIsTurningLeft(true);
return this->keystate = LeftPressed;
// add code when user presses left
break;
}
case SDLK_RIGHT:
{
// rotate the ship right
c.setIsTurningRight(true);
return this->keystate = RightPressed;
// add code when user presses right
break;
}
case SDLK_UP:
{
// accleration
c.setIsAccelerating(true);
return this->keystate = UpPressed;
// add code when user presses up
break;
}
case SDLK_SPACE:
{
// shoot
c.setIsShooting(true);
std::cout << "keystate = " << this->keystate;
return this->keystate = SpacePressed;
// add code when user presses space
break;
}
default:
{
return this->keystate = NotPressed;
break;
}
}
break;
}
/* We must also use the SDL_KEYUP events to zero the x */
/* and y velocity variables. But we must also be */
/* careful not to zero the velocities when we shouldn't*/
case SDL_KEYUP:
{
std::cout << "Key currently pressed" << event->key.keysym.sym << std::endl;
switch(event->key.keysym.sym)
{
case SDLK_LEFT:
{ /* We check to make sure the ship is moving */
/* to the left. If it is then we zero the */
/* velocity. If the ship is moving to the */
/* right then the right key is still press */
/* so we don't touch the velocity */
c.setIsTurningLeft(false);
return this->keystate = LeftReleased;
// code to do things when left isn't pushed anymore but still moving left
break;
}
case SDLK_RIGHT:
{ // code to do things when right isn't pushed anymore but still moving right
c.setIsTurningRight(false);
return this->keystate = RightReleased;
break;
}
case SDLK_UP:
{ // code to do things when up isn't pushed anymore but still moving up
c.setIsAccelerating(false);
return this->keystate = UpReleased;
break;
}
case SDLK_SPACE:
{ // accleration
c.setIsShooting(false);
return this->keystate = SpaceReleased;
// add code when user presses up
break;
}
default:
break;
}
break;
}
default:
{
return this->keystate = NotPressed;
break;
}
}
}
EDIT:
Here is the example requested. The other thing that I've noticed is the latency in response isn't that great. Like if you press a key sometimes the console doesn't print the corresponding key. Probably has to do with the issue I'm having with the space as well.
void GUI::TakeInput(SDL_Event *e)
{
while (SDL_PollEvent(e))
OnEvent(e);
}
void SDLEvent::OnEvent(SDL_Event * event)
{
switch(event->type)
{
case SDL_KEYDOWN:
{
OnKeyDown(event->key.keysym.sym);
break;
}
case SDL_KEYUP:
{
OnKeyUp(event->key.keysym.sym);
break;
}
case SDL_MOUSEMOTION:
{
OnMouseMove(event->motion.x,event->motion.y);
break;
}
case SDL_MOUSEBUTTONDOWN:
{
OnMouseButtonDown(event->button.button, event->button.x,event->button.y);
break;
}
case SDL_MOUSEBUTTONUP:
{
OnMouseButtonUp(event->button.button, event->button.x,event->button.y);
break;
}
case SDL_QUIT: {
OnExit();
break;
}
case SDL_SYSWMEVENT: {
//Ignore
break;
}
case SDL_WINDOWEVENT_RESIZED: {
OnResize();
break;
}
case SDL_WINDOWEVENT_EXPOSED: {
OnExpose();
break;
}
default: {
OnUser(event->user.type,event->user.code,event->user.data1,event->user.data2);
break;
}
}
}
void GUI::Play()
{
Uint32 start_ticks = SDL_GetTicks();
TakeInput(this->setup->GetEvent());
this->keyboard->ProcessKeys(this->setup->GetEvent());
this->setup->RenderBegin();
this->ship->drawBackBuffer();
this->ship->renderSprite();
Uint32 end_ticks = SDL_GetTicks();
int sleep_delay = (1000 / 60) - (end_ticks-start_ticks);
if (sleep_delay > 0) {
SDL_Delay(sleep_delay);
}
}
If you are only writing event->key.keysym.sym on the console, you should know that the spacebar key produces an almost invisible character.
Try this instead:
std::cout << "<" << event->key.keysym.sym << ">"
So you can see whataver invisible character printed between angle brackets.

why isnt initgraph getting recognized in my program?

I have programmed a code for displaying a GUI menu in Turbo C++ but I don't know why it wont recognize initgraph
This is the output message
BGI Error:Graphics not initialized
when i tried a simpler program on graphics in Turbo C++ it said egavga.bgi not found but it was there in the bgi file in my turbo c++ folder
Also when i tried to put the location of the bgi in initgraph it doesnt do anything
this is the program code
#include<iostream.h>
#include<conio.h>
#include <dos.h>
#include<graphics.h>
//Menu Global Item
#define pixTOrc(x) (8*(x-1)) //convert pixel into row and col format
#define INC 5 //Increment Distance Between Menu Items
#define ROW 15 //Row Value for Menu Item
#define COL 8 //Column Value for Menu Item
#define MAXMENU 5 //Total menu items
// To display the Inventory Main menu options
typedef char option[20];
option MMenu[]= {
"View Account",
"Transactions",
"New Accont",
"Edit Account",
"Quit"
};
// Function to displays all the menu prompt messages from the pointer array of option a[]
void normalvideo(int x,int y,char *str)
{
x=pixTOrc(x);
y=pixTOrc(y);
outtextxy(x,y,str);
}
// Function to move the cursor on the menu prompt with a reverse video color
void selectedMenu(int x,int y,char *str)
{
x=pixTOrc(x);
y=pixTOrc(y);
setcolor(5); //Selected Item Color
sound(400);
delay(100);
nosound();
outtextxy(x,y,str);
setcolor(WHITE); //Unselected Item Color
sound(500);
delay(100);
nosound();
}
//Keep Track of which arrow key is pressed
char menu()
{
settextstyle(TRIPLEX_FONT,HORIZ_DIR,2);
setcolor(WHITE); //Initial Menu Item Color
int i,done;
for(i = 1; i < MAXMENU; i++)
normalvideo(COL, (i*INC)+ROW, MMenu[i]);
selectedMenu(COL,ROW, MMenu[0]);
i = done = 0;
do
{
/**Status Bar Code**/
setfillstyle(SOLID_FILL,BLUE);
settextstyle(SMALL_FONT,HORIZ_DIR,5);
bar(pixTOrc(2),pixTOrc(52.5),pixTOrc(75),pixTOrc(55));
setcolor(LIGHTCYAN);
switch(i)
{
case 0 : outtextxy(pixTOrc(5),pixTOrc(52.75),"View Account --> View Detail of an account");
break;
case 1 : outtextxy(pixTOrc(5),pixTOrc(52.75),"Transactions --> Do transaction Debit/Credit");
break;
case 2 : outtextxy(pixTOrc(5),pixTOrc(52.75),"New Accont --> Create a new account for customer");
break;
case 3 : outtextxy(pixTOrc(5),pixTOrc(52.75),"Edit Account --> Edit an existing account");
break;
case 4 : outtextxy(pixTOrc(5),pixTOrc(52.75),"Close the Program");
break;
}
/**status Bar ends**/
setcolor(WHITE);
settextstyle(TRIPLEX_FONT,HORIZ_DIR,2);
int key = getch();
switch (key)
{
case 00: key = getch();
switch (key)
{
case 72: normalvideo(COL, (i*INC)+ROW, MMenu[i]);
i--;
if (i == -1)
i = MAXMENU-1;
selectedMenu(COL,(i*INC)+ROW,MMenu[i]);
break;
case 80: normalvideo(COL, (i*INC)+ROW, MMenu[i]);
i++;
if (i == MAXMENU)
i = 0;
selectedMenu(COL, (i*INC)+ROW, MMenu[i]);
break;
}
break;
case 13: done = 1;
}
}
while (!done);
return(i+49);
}
//This part you can use for main functionality of the menu
void mainArea()
{
setcolor(BLUE);
outtextxy(pixTOrc(30),pixTOrc(20),"http://cbsecsnip.in/");
setcolor(YELLOW);
}
/* Code for displaying the main menu*/
void call_menu()
{
char choice;
do
{
choice = menu();
switch (choice)
{
case '1': setcolor(BLUE);
outtextxy(pixTOrc(40),pixTOrc(15),"View Account");
mainArea();
getch();
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(pixTOrc(28),pixTOrc(14),pixTOrc(75),pixTOrc(50));
mainArea();
break;
case '2':
setcolor(BLUE);
outtextxy(pixTOrc(40),pixTOrc(15),"Transactions");
mainArea();
getch();
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(pixTOrc(28),pixTOrc(14),pixTOrc(75),pixTOrc(50));
mainArea();
break;
case '3':
setcolor(BLUE);
outtextxy(pixTOrc(40),pixTOrc(15),"New Accont");
mainArea();
getch();
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(pixTOrc(28),pixTOrc(14),pixTOrc(75),pixTOrc(50));
mainArea();
break;
case '4':
setcolor(BLUE);
outtextxy(pixTOrc(40),pixTOrc(15),"Edit Account");
mainArea();
getch();
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(pixTOrc(28),pixTOrc(14),pixTOrc(75),pixTOrc(50));
mainArea();
break;
case '5': //Close the project
setcolor(BLUE);
outtextxy(pixTOrc(40),pixTOrc(15),"Quit");
mainArea();
delay(1000);
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(pixTOrc(28),pixTOrc(14),pixTOrc(75),pixTOrc(50));
mainArea();
goto exit;
}
} while (choice != MAXMENU);
exit:
}
void main()
{
int i,j;
int gd=DETECT,gm;
initgraph(&gd,&gm,"");
setcolor(BLACK);
rectangle(0,0,640,480);
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(2,1,637,478);
setfillstyle(SOLID_FILL,BLACK);
bar(1,3,637,50);
settextstyle(BOLD_FONT,HORIZ_DIR,2);
setcolor(YELLOW);
outtextxy(pixTOrc(12),pixTOrc(1)," BANKING SYSTEM PROJECT ");
setfillstyle(CLOSE_DOT_FILL,DARKGRAY);
bar(pixTOrc(7),pixTOrc(14),pixTOrc(25),pixTOrc(50));
call_menu();
closegraph();
getch();
}
Possible Solutions:
Copy all Files from BGI folder to BIN.
Check if it works.

Wait for input for a certain time

Is there any function that can wait for input until a certain time is reached? I'm making kind of Snake game.
My platform is Windows.
For terminal based games you should take a look at ncurses.
int ch;
nodelay(stdscr, TRUE);
for (;;) {
if ((ch = getch()) == ERR) {
/* user hasn't responded
...
*/
}
else {
/* user has pressed a key ch
...
*/
}
}
Edit:
See also Is ncurses available for windows?
I found a solution using kbhit() function of conio.h as follows :-
int waitSecond =10; /// number of second to wait for user input.
while(1)
{
if(kbhit())
{
char c=getch();
break;
}
sleep(1000); sleep for 1 sec ;
--waitSecond;
if(waitSecond==0) // wait complete.
break;
}
Try with bioskey(), this is an example for that:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <bios.h>
#include <ctype.h>
#define F1_Key 0x3b00
#define F2_Key 0x3c00
int handle_keyevents(){
int key = bioskey(0);
if (isalnum(key & 0xFF)){
printf("'%c' key pressed\n", key);
return 0;
}
switch(key){
case F1_Key:
printf("F1 Key Pressed");
break;
case F2_Key:
printf("F2 Key Pressed");
break;
default:
printf("%#02x\n", key);
break;
}
printf("\n");
return 0;
}
void main(){
int key;
printf("Press F10 key to Quit\n");
while(1){
key = bioskey(1);
if(key > 0){
if(handle_keyevents() < 0)
break;
}
}
}
Based on #birubisht answer I made a function which is a bit cleaner and uses NON-deprecated versions of kbhit() and getch() - ISO C++'s _kbhit() and _getch().
Function takes: number of seconds to wait for user input
Function returns: _ when user does not put any char, otherwise it returns the inputed char.
/**
* Gets: number of seconds to wait for user input
* Returns: '_' if there was no input, otherwise returns the char inputed
**/
char waitForCharInput( int seconds ){
char c = '_'; //default return
while( seconds != 0 ) {
if( _kbhit() ) { //if there is a key in keyboard buffer
c = _getch(); //get the char
break; //we got char! No need to wait anymore...
}
Sleep(1000); //one second sleep
--seconds; //countdown a second
}
return c;
}