I am creating a console application in C. This is a game in which characters are falling down and user has to press that specific key on the keyboard. I don't know how to detect which key is pressed by the user without pausing the falling characters. When I use scanf the Program waits for input and everything pauses.
Please help me soon!
There is a function called kbhit() or _kbhit it is in the <conio.h> library it returns true or false depending whether a key was hit. So you can go with something like this:
while (1){
if ( _kbhit() )
key_code = _getch();
// do stuff depending on key_code
else
continue;
Also use getch() or _getch which reads a character directly from the console and not from the buffer. You can read more about conio.h functions here they might be very useful for what you want to do.
Note: conio.h is not a standard library and implementations may vary from compiler to compiler.
You may probably look for ncurses
ncurses (new curses) is a programming library that provides an API
which allows the programmer to write text-based user interfaces in a
terminal-independent manner. It is a toolkit for developing "GUI-like"
application software that runs under a terminal emulator.
Also check C/C++: Capture characters from standard input without waiting for enter to be pressed
#include <conio.h>
if (kbhit()!=0) {
cout<<getch()<<endl;
}
I think this might be the non-blocking keyboard input you are looking for.
void simple_keyboard_input() //win32 & conio.h
{
if (kbhit())
{
KB_code = getch();
//cout<<"KB_code = "<<KB_code<<"\n";
switch (KB_code)
{
case KB_ESCAPE:
QuitGame=true;
break;
}//switch
}//if kb
}//void
And as for the characters falling down.. here you go.
Code for if you are on Windows:
/* The Matrix falling numbers */
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
using namespace std;
#define KB_UP 72
#define KB_DOWN 80
#define KB_LEFT 75
#define KB_RIGHT 77
#define KB_ESCAPE 27
#define KB_F8 66
/* Variables*/
char screen_buffer[2000]={' '};
int y_coord[2000]={0};
int x=0, y=0,dy=0;
int XMAX=77;
int YMAX=23;
int KB_code=0;
bool QuitGame=false;
int platformX=35, platformY=23;
/* function prototypes*/
void gotoxy(int x, int y);
void clrscr(void);
void setcolor(WORD color);
void simple_keyboard_input();
void draw_falling_numbers();
void draw_platform();
/* main */
int main(void)
{
/* generate random seed */
srand ( time(NULL) );
/* generate random number*/
for(int i=0;i<XMAX;i++) y_coord[i]= rand() % YMAX;
while(!QuitGame)
{
/* simple keyboard input */
simple_keyboard_input();
/* draw falling numbers */
draw_falling_numbers();
}
/* restore text color */
setcolor(7);
clrscr( );
cout<<" \n";
cout<<" \nPress any key to continue\n";
cin.ignore();
cin.get();
return 0;
}
/* functions */
void draw_falling_numbers()
{
for(x=0;x<=XMAX;x++)
{
/* generate random number */
int MatixNumber=rand() % 2 ;
/* update falling number */
y_coord[x]=y_coord[x]+1;
if (y_coord[x]>YMAX) y_coord[x]=0;
/* draw dark color */
setcolor(2);
gotoxy(x ,y_coord[x]-1); cout<<" "<<MatixNumber<<" ";
/* draw light color */
setcolor(10);
gotoxy(x ,y_coord[x]); cout<<" "<<MatixNumber<<" ";
}
/* wait some milliseconds */
Sleep(50);
//clrscr( );
}
void draw_platform()
{
setcolor(7);
gotoxy(platformX ,platformY);cout<<" ";
gotoxy(platformX ,platformY);cout<<"ÜÜÜÜÜÜ";
setcolor(7);
Sleep(5);
}
void simple_keyboard_input()
{
if (kbhit())
{
KB_code = getch();
//cout<<"KB_code = "<<KB_code<<"\n";
switch (KB_code)
{
case KB_ESCAPE:
QuitGame=true;
break;
case KB_LEFT:
//Do something
platformX=platformX-4;if(platformX<3) platformX=3;
break;
case KB_RIGHT:
//Do something
platformX=platformX+4;if(platformX>74) platformX=74;
break;
case KB_UP:
//Do something
break;
case KB_DOWN:
//Do something
break;
}
}
}
void setcolor(WORD color)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color);
return;
}
void gotoxy(int x, int y)
{
static HANDLE hStdout = NULL;
COORD coord;
coord.X = x;
coord.Y = y;
if(!hStdout)
{
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
}
SetConsoleCursorPosition(hStdout,coord);
}
void clrscr(void)
{
static HANDLE hStdout = NULL;
static CONSOLE_SCREEN_BUFFER_INFO csbi;
const COORD startCoords = {0,0};
DWORD dummy;
if(!hStdout)
{
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hStdout,&csbi);
}
FillConsoleOutputCharacter(hStdout,
' ',
csbi.dwSize.X * csbi.dwSize.Y,
startCoords,
&dummy);
gotoxy(0,0);
}
Related
I've seen this answered for other languages but not for C++. How would I get a program to wait for the user to press Enter or some key like that, but also to automatically continue after a set time period as long as a key hasn't been entered? I need basic code, I'm sort of a beginner. I know that cin.get(); or system("pause"); will wait for a key and sleep(x seconds); or Sleep(x milliseconds); (with the "windows.h" library) will pause a program, but how do I get both at once?
In windows you can use GetAsyncKeyState() to poll the current state of the keyboard. Then you can use Sleep() to sleep a certain number of milliseconds. Combine those two and you can make something like what you need:
int keyToWaitFor = VK_SPACE;
int count = 0;
int maxcount = 500;
for(int a = 0; a < maxcount; a++){
if (GetAsyncKeyState(keyToWaitFor)!=0){
break;
}
Sleep(5);
}
Since you apparently want to do this on Windows, it's fairly straightforward.
You start by opening a handle to the console, such as with GetStdHandle. Then when you want to do a read, you call WaitForSingleObject on that handle, specifying your timeout value. Check the return. If the return value is WAIT_OBJECT_0, it means you have some input, which you can read with (for example) ReadConsoleInput. If the return is WAIT_TIMEOUT, it means there's no input, so you can do whatever else it is you want to do.
With conio.h, You can wait for a keypress with kbhit() and getch() and make a wait for a 20 second timer with a
while loop, while( key==0 && (time_to_wait < secs) ).
#include <iostream>
#include <cstdio>
#include <ctime>
#include <conio.h>
#include <windows.h>
using namespace std;
int key=0;
bool quit=false;
void check_if_keypressed();
void gotoxy(int x, int y);
void clrscr();
int main()
{
clock_t start;
double time_to_wait;
double secs=10;
gotoxy(1, 2);
cout<<"Press any key to continue or wait 20 seconds: \n ";
start = clock();
while( key==0 && (time_to_wait < secs) )
{
check_if_keypressed();
time_to_wait = ( clock() - start ) / (double) CLOCKS_PER_SEC;
// proceed with whatever here
gotoxy(1, 23);
cout<<"countdown: "<< secs-time_to_wait <<" \n ";
}
// proceed with whatever here
// while( key!=27)
// {
// check_if_keypressed();
// do_other_stuff();
// }
return 0;
}
void check_if_keypressed()
{
if( kbhit() ) key=getch();
switch(key)
{
case 27:
quit=true;
break;
}
}
void gotoxy(int x, int y)
{
COORD coord;
coord.X = x; coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
return;
}
void clrscr()
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
return;
}
I am trying to learn how to use graphics.h and conio.h libraries.I am developing a graphic program which i need to move a rectangle after keyboard input.ex: if player press right , rectangle should move right side.Problem is i don't know how to get user input.I need to get user input inside a loop continuous.Here is my code.Any help is appreciated(keyword,function name etc)
#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <math.h>
void drawrect(int left,int top,int right,int bot);
int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");
drawrect(5,400,40,450); // default start position
firsttime=1;//counter for if its first time in for loop
int currentl=5;
int currentt=400;
int currentr=40;
int currentb=450;
if(firsttime==1)
{
//get user input and drawrectangle with new inputs
//if player press right add 5 to currentl and current r and
//redraw the rectangle
}
getch();
closegraph();
}
void drawrect(int left,int top,int right,int bot)
{
rectangle(left,top,right,bot);
}
You can use getch() or _getch() to read codes of keys and react on it. But some things you should think over.
1) loop is needed to perform continuois action in your program.
2) keys such as "arrow left", "arrow up", etc. is given by getch() as two codes - the first -32 and the second depends on key.
Use the following programm to see the loop example and to find codes for keys:
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
int main(void)
{
char ch;
printf("Press 'q' to exit prom program\n");
do{
ch = _getch();
printf("%c (%d)\n", ch, ch);
} while( ch != 'q');
}
Its solved this code works thanks for help
#include
#include
void drawrect(int left,int top,int right,int bot);
int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");
int firsttime=1;//counter for if its first time in for loop
int currentl=5;
int currentt=400;
int currentr=40;
int currentb=450;
char ch;
settextstyle(0, HORIZ_DIR, 1);
outtextxy(20, 20, "To start press 'S'");
ch = getch();
cleardevice();
drawrect(5,400,40,450); // default start position
while(ch!='q')
{
ch = getch();
switch (ch)
{
case KEY_RIGHT:currentr=currentr+5;
currentl=currentl+5;
break;
case KEY_LEFT:currentr=currentr-5;
currentl=currentl-5;
break;
}
cleardevice();
drawrect(currentl,currentt,currentr,currentb);
}
getch();
closegraph();
}
void drawrect(int left,int top,int right,int bot)
{
rectangle(left,top,right,bot);
}
I want to use getch() or something similar to register a keystroke in a while() function.
while()
{
.
.
.
if(kbhit()) k=getch();
else cout<<"no input";
cout<<k<<endl;
k=0;
Sleep(1200);
.
.
.
}
If i hold a key, the function will keep displaying that key for a while. I will use a similar code to implement movement for a worm game. If a key will not be pressed the worm will keep going int he direction it's facing (but i don't need help with this i already have it sorted out).
I just need to know how do i register just 1 key press for a while cycle. Using Codeblocks.
Simple. Like this!!!.
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
using namespace std;
#define KB_UP 72
#define KB_DOWN 80
#define KB_LEFT 75
#define KB_RIGHT 77
#define KB_ESCAPE 27
#define KB_F8 66
bool QuitGame=false;
char KB_code;
void simple_keyboard_input();
int main(void)
{
while(!QuitGame)
{
/* simple keyboard input */
simple_keyboard_input();
}
return 0;
}
void simple_keyboard_input()
{
if (kbhit())
{
KB_code = getch();
switch (KB_code)
{
case KB_ESCAPE:
QuitGame=true;
break;
}
}
}
Personally I would use something like this:
int support_code = 0; //global variable
void input()
{
if (GetKeyState('W') & 0x8000)
{ int helpful_button = "1"; // unique number for every button!
if (helpful_button != support_code)
{ support_code = helpful_button;
// do something
}
}
else if (...)
...
// End of "key registering" "if's"
}
// And then somewhere else in your code you can "reset" 'support_code' for it to be 0
// (so you can use the same button again)
// But if you don't want a worm to be able to change direction from "UP" to "UP"
// Then you don't even have to implement "support_code = 0" part from it
int main()
{
...
while (!gameover)
{
input();
calculate();
draw();
...
support_code = 0;
}
...
}
For a "worm game" you won't probably need lot of keystrokes (I guess <10) so you can easily implement it this way. And as you can see, it will only "register" each key once.
(Worked for all of the games I coded so far)
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;
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I would like to ask how can I make a console game when I need the user to input some string within a period of time? (I've tried to use Sleep function but it will make the screen freeze for a period of time which I don't want to)
Example : A Pop Quiz
I think this can be done without multithreading (A very simple version of a timer)
You can try to write something like this and modify it to serve your needs:
Please note that the code is not complete. You need to edit it so it match your needs. However, this should give you an idea.
int main()
{
time_t begin, end;
char input;
bool flag = true;
begin = time();
while (flag)
{
if(kbhit())
ch = getch();
end = time();
if(difftime(end, begin) > NEEDED_TIME_IN_SECONDS)
flag = false; //The user didn't enter it in within the wanted period of time
}
}
Some documentations:
double difftime(time_t time2, time_t time1)
Return difference between two times
Calculates the difference in seconds between time1 and time2.
getch() Prompts the user to press a character and that character is not printed on screen.
kbhit() It returns a non-zero integer if a key is in the keyboard buffer. It will not wait for a key to be pressed.
Try this code if you use windows:
#include <stdio.h>
#include <time.h>
#include <conio.h>
#include <windows.h>
#include <string>
#include <iostream>
using namespace std;
#define KB_UP 72
#define KB_DOWN 80
#define KB_LEFT 75
#define KB_RIGHT 77
#define KB_ESCAPE 27
#define KB_F8 66
#define KB_ENTER 13
unsigned int x_hours=0;
unsigned int x_minutes=0;
unsigned int x_seconds=0;
unsigned int x_milliseconds=0;
unsigned int totaltime=0,count_down_time_in_secs=0,time_left=0;
clock_t x_startTime,x_countTime;
int KeyBoard_code,input_count=0;
int caret_x=0,caret_y=0;
char keyboard_buffer[100]={' '};
char answer_buffer[100]={' '};
char correct_answer[ ]="foo bar";
int is_from_keyboard(int ch);
void start_timer();
void delta_time_update_timer();
void gotoxy(int x, int y);
void clrscr(void);
void setcolor(WORD color);
void keyboard_input();
int main ()
{
count_down_time_in_secs= 4; // 1 minute is 60sec (60x1min), 1 hour is 3600 (60x60min)
start_timer();
delta_time_update_timer();
gotoxy(1 , 2);
printf( "\nWhat is the answer to the bla bla of bla bla? ");
gotoxy(1,5);printf( "Answer? >");
while (time_left>0)
{
keyboard_input();
delta_time_update_timer();
}
gotoxy(1 , 12);
printf( "\n\n\nTime's out\n\n\n");
return 0;
}
void start_timer()
{
x_startTime=clock(); // start clock
}
void delta_time_update_timer()
{
x_countTime=clock(); // update timer difference
x_milliseconds=x_countTime-x_startTime;
x_seconds=(x_milliseconds/(CLOCKS_PER_SEC))-(x_minutes*60);
x_minutes=(x_milliseconds/(CLOCKS_PER_SEC))/60;
x_hours=x_minutes/60;
time_left=count_down_time_in_secs-x_seconds; // update timer
gotoxy(1 , 1);
printf( "\nYou have %d seconds left ",time_left,count_down_time_in_secs);
gotoxy(1,5);
}
void keyboard_input()
{
if (kbhit())
{
KeyBoard_code = getch();
caret_x++;
gotoxy(10+caret_x,5+caret_y);
printf( "%c",KeyBoard_code);
input_count++;
keyboard_buffer[input_count]=(char)KeyBoard_code;
switch (KeyBoard_code)
{
case KB_ESCAPE:
break;
case KB_ENTER:
memcpy(answer_buffer, keyboard_buffer,sizeof(keyboard_buffer));
gotoxy(1 ,7);
printf( "Your answer is %s ",answer_buffer);
gotoxy(1,5);printf( "Answer? > ");
gotoxy(1 ,9);
printf( "The correct answer is %s ", correct_answer);
caret_x=0;
input_count=0;
start_timer();
count_down_time_in_secs= 7;
delta_time_update_timer();
memset(keyboard_buffer,32,sizeof(keyboard_buffer));
memset(answer_buffer,32,sizeof(answer_buffer));
break;
case KB_LEFT:
break;
case KB_RIGHT:
break;
case KB_UP:
break;
case KB_DOWN:
break;
}
}
}
void setcolor(WORD color)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color);
return;
}
void gotoxy(int x, int y)
{
static HANDLE hStdout = NULL;
COORD coord;
coord.X = x;
coord.Y = y;
if(!hStdout)
{
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
}
SetConsoleCursorPosition(hStdout,coord);
}
void clrscr(void)
{
static HANDLE hStdout = NULL;
static CONSOLE_SCREEN_BUFFER_INFO csbi;
const COORD startCoords = {0,0};
DWORD dummy;
if(!hStdout)
{
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hStdout,&csbi);
}
FillConsoleOutputCharacter(hStdout,
' ',
csbi.dwSize.X * csbi.dwSize.Y,
startCoords,
&dummy);
gotoxy(0,0);
}
int is_from_keyboard(int ch)
{
if ( ch>=31 && ch<128) return 1;
else return -1;
}