C++ Game countdown timer [closed] - 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;
}

Related

Wait for key press but auto-start after time C++

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;
}

Listening to keyboard events without consuming them in X11 - Keyboard hooking

I tried to write a program which hooks keyboard messages to pronounce the name of each key whenever it is pressed in Ubuntu (KDE); without interfering with normal action of keyboard in programs (just announcing the key name).
This is my program:
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
void SendPressKeyEvent(Display *display, XKeyEvent xkey)
{
Window current_focus_window;
int current_focus_revert;
XGetInputFocus(display, &current_focus_window, &current_focus_revert);
xkey.type = KeyPress;
xkey.display = display;
xkey.window = current_focus_window;
xkey.root = DefaultRootWindow(display);
xkey.subwindow = None;
xkey.time = 1000 * time(0);
xkey.x = 0;
xkey.y = 0;
xkey.x_root = 0;
xkey.y_root = 0;
xkey.same_screen = True;
XSendEvent(display, InputFocus, True, KeyPressMask, (XEvent *)(&xkey));
}
void SendReleaseKeyEvent(Display *display, XKeyEvent xkey)
{
Window current_focus_window;
int current_focus_revert;
XGetInputFocus(display, &current_focus_window, &current_focus_revert);
xkey.type = KeyRelease;
xkey.display = display;
xkey.window = current_focus_window;
xkey.root = DefaultRootWindow(display);
xkey.subwindow = None;
xkey.time = 1000 * time(0);
xkey.x = 0;
xkey.y = 0;
xkey.x_root = 0;
xkey.y_root = 0;
xkey.same_screen = True;
XSendEvent(display, InputFocus, True, KeyReleaseMask, (XEvent *)(&xkey));
}
void *TaskCode(void* arg)
{
switch(*(int*)arg)
{
case 38:
system("espeak -v en " "\"a\"");
}
return 0;
}
int main()
{
Display *display = XOpenDisplay(0);
if(display == 0)
exit(1);
XGrabKeyboard(display, DefaultRootWindow(display), True, GrabModeAsync, GrabModeAsync, CurrentTime);
XEvent event;
while(true)
{
XNextEvent(display, &event);
if(event.type == Expose)
{
}
if(event.type == KeyPress)
{
SendPressKeyEvent(display,event.xkey);
if(event.xkey.keycode == 38)
{
pthread_t thread;
int thread_arg = event.xkey.keycode;
pthread_create(&thread,0, TaskCode, (void*) &thread_arg);
}
}
if(event.type == KeyRelease)
SendReleaseKeyEvent(display,event.xkey);
}
XCloseDisplay(display);
}
This program is just for the key a which can be extended to other keys.
But when this program is running, some programs (e.g. Chromium) do not show the blinker (cursor) in their edit boxes. Also all KDE hotkeys become disabled.
How can this be fixed?
Here's my quick and dirty example
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <ctype.h>
int main ()
{
Display* d = XOpenDisplay(NULL);
Window root = DefaultRootWindow(d);
Window curFocus;
char buf[17];
KeySym ks;
XComposeStatus comp;
int len;
int revert;
XGetInputFocus (d, &curFocus, &revert);
XSelectInput(d, curFocus, KeyPressMask|KeyReleaseMask|FocusChangeMask);
while (1)
{
XEvent ev;
XNextEvent(d, &ev);
switch (ev.type)
{
case FocusOut:
printf ("Focus changed!\n");
printf ("Old focus is %d\n", (int)curFocus);
if (curFocus != root)
XSelectInput(d, curFocus, 0);
XGetInputFocus (d, &curFocus, &revert);
printf ("New focus is %d\n", (int)curFocus);
if (curFocus == PointerRoot)
curFocus = root;
XSelectInput(d, curFocus, KeyPressMask|KeyReleaseMask|FocusChangeMask);
break;
case KeyPress:
printf ("Got key!\n");
len = XLookupString(&ev.xkey, buf, 16, &ks, &comp);
if (len > 0 && isprint(buf[0]))
{
buf[len]=0;
printf("String is: %s\n", buf);
}
else
{
printf ("Key is: %d\n", (int)ks);
}
}
}
}
It's not reliable but most of the time it works. (It is showing keys I'm typing into this box right now). You may investigate why it does fail sometimes ;) Also it cannot show hotkeys in principle. Hotkeys are grabbed keys, and only one client can get a grabbed key. Absolutely nothing can be done here, short of loading a special X11 extension designed for this purpose (e.g. XEvIE).
Thanks to n.m.'s answer and parsa's comment, this is my final code:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
void* TaskCode(void* parg)
{
int keycode = *((int*)parg);
cout<< "\n\n" << keycode << "\n\n";
if(keycode == XKeysymToKeycode(XOpenDisplay(0),'a'))
system("espeak -v en " "\"a\"");
delete (int*)parg;
return 0;
}
void Action(int keycode)
{
pthread_t thread;
pthread_attr_t attrs;
pthread_attr_init(&attrs);
pthread_attr_setdetachstate(&attrs,PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&attrs, 1000);
int* pthread_arg = new int;
*pthread_arg = keycode;
pthread_create(&thread,&attrs, TaskCode, (void*) pthread_arg);
}
int MyX11ErrorHandler(Display *, XErrorEvent *error_event)
{
cout << "\n\n" "An X11-Functions error occured. Probably the focused window was closed.""\n"
"This error will be ignored." "\n";
cout<< "error_code: " << (unsigned)error_event -> error_code << "\n";
cout<< "minor_code: " << (unsigned)error_event -> minor_code << "\n";
cout<< "request_code: " << (unsigned)error_event -> request_code << "\n";
cout<< "resourceid: " << error_event -> resourceid << "\n";
cout<< "serial; " << error_event -> serial << "\n";
cout<< "type: " << error_event -> type << "\n\n";
return 0;
}
int main()
{
Display* display = XOpenDisplay(0);
Window root = DefaultRootWindow(display);
Window current_focus_window;
int revert;
XSetErrorHandler(MyX11ErrorHandler);
XGetInputFocus(display, &current_focus_window, &revert);
XSelectInput(display,current_focus_window,KeyPressMask | KeyReleaseMask | FocusChangeMask);
while(true)
{
XEvent event;
XNextEvent(display, &event);
switch (event.type)
{
case FocusOut:
if(current_focus_window != root)
XSelectInput(display, current_focus_window, 0);
XGetInputFocus(display, &current_focus_window, &revert);
if(current_focus_window == PointerRoot)
current_focus_window = root;
XSelectInput(display, current_focus_window, KeyPressMask|KeyReleaseMask|FocusChangeMask);
break;
case KeyPress:
Action(event.xkey.keycode);
break;
}
}
}
Add these to a Qt Creator's project .pro file:
LIBS += -lX11
LIBS += -lpthread
LIBS += -lXtst
Any improvement suggestions is appreciated.
To archive I also add my final code with grabbing:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
void* TaskCode(void* parg)
{
int keycode = *((int*)parg);
cout<< "\n\n" << keycode << "\n\n";
system("espeak -v en " "\"a\"");
delete (int*)parg;
return 0;
}
void SendKeyEvent(Display *display, XEvent event)
{
Window current_focus_window;
XKeyEvent& xkey = event.xkey;
int current_focus_revert;
XGetInputFocus(display, &current_focus_window, &current_focus_revert);
xkey.state = Mod2Mask;
XSendEvent(display, InputFocus, True, xkey.type, (XEvent *)(&event));
}
int GrabKey(Display* display, Window grab_window, int keycode)
{
unsigned int modifiers = Mod2Mask; // numlock on
//Window grab_window = DefaultRootWindow(display);
Bool owner_events = True;
int pointer_mode = GrabModeAsync;
int keyboard_mode = GrabModeAsync;
XGrabKey(display, keycode, modifiers, grab_window, owner_events, pointer_mode, keyboard_mode);
return keycode;
}
void UngrabKey(Display* display, Window grab_window, int keycode)
{
unsigned int modifiers = Mod2Mask; // numlock on
// Window grab_window = DefaultRootWindow(display);
XUngrabKey(display,keycode,modifiers,grab_window);
}
void Action(int keycode)
{
pthread_t thread;
int* pthread_arg = new int;
*pthread_arg = keycode;
pthread_create(&thread,0, TaskCode, (void*) pthread_arg);
}
int main()
{
Display* display = XOpenDisplay(0);
Window root = DefaultRootWindow(display);
XEvent event;
int keycode = XKeysymToKeycode(display,'a');
GrabKey(display,root,keycode);
XSelectInput(display, root, KeyPressMask | KeyReleaseMask);
while(true)
{
XNextEvent(display, &event);
switch(event.type)
{
case KeyPress:
Action(event.xkey.keycode);
case KeyRelease:
SendKeyEvent(display,event);
default:
break;
}
}
XCloseDisplay(display);
}
Everything is good except that, unlike the code in question, it ignores language layout. Pressing a types a whatever regradless of language layout!
As an alternative to listening to X events, it's also possible to listen to Linux input events directly: https://stackoverflow.com/a/27693340/21501
This has the benefit that it's possible to modify the event stream in-flight, and block, edit or generate input events.
The proper way to listen to all events is using the X Record Extension Library, part of libXtst, apparently installed on pretty much every X system. It is documented here, but as the docs are patchy, you will need to browse previous implementations of this. Here is a nice working demo, and here is a more capable and complete implementation.
A simplified version of the first example is included below.
#include <stdio.h>
#include <X11/XKBlib.h>
#include <X11/extensions/record.h>
void key_pressed_cb(XPointer arg, XRecordInterceptData *d);
int scan(int verbose) {
XRecordRange* rr;
XRecordClientSpec rcs;
XRecordContext rc;
Display *dpy = XOpenDisplay(NULL);
rr = XRecordAllocRange();
rr->device_events.first = KeyPress;
rr->device_events.last = ButtonReleaseMask;
rcs = XRecordAllClients;
rc = XRecordCreateContext (dpy, 0, &rcs, 1, &rr, 1);
XFree (rr);
XRecordEnableContext(dpy, rc, key_pressed_cb, NULL);
}
void key_pressed_cb(XPointer arg, XRecordInterceptData *d) {
if (d->category != XRecordFromServer)
return;
int key = ((unsigned char*) d->data)[1];
int type = ((unsigned char*) d->data)[0] & 0x7F;
int repeat = d->data[2] & 1;
if(!repeat) {
switch (type) {
case KeyPress:
printf("key press %d\n", key);
break;
case KeyRelease:
printf("key release %d\n", key);
break;
case ButtonPress:
printf("button press %d\n", key);
break;
case ButtonRelease:
printf("button release %d\n", key);
break;
default:
break;
}
}
XRecordFreeData (d);
}
int main() {
scan(True);
return 0;
}
gcc -o x1 x1.c -lX11 -lXtst

Continuous keyboard input in C

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);
}

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;
}

How to deal with racing threads (C++; TinyThread++)?

Here is a sample of the main code ("Library/stack.h" doesn't really matter, but in any case, it is the last source included in this previous question of mine):
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <tinythread.h>
#include "Library/stack.h"
using namespace std;
using namespace tthread;
#define BOULDERspd 100
// ========================================================================= //
struct Coord {
int x, y;
};
int randOneIn (float n) {
return ((int) (n * (rand() / (RAND_MAX + 1.0))));
}
int randOneIn (int n) {
return ((int) ((float) n * (rand() / (RAND_MAX + 1.0))));
}
// ========================================================================= //
#include <windows.h>
void gotoxy (int column, int line) {
if ((column >= 0) && (line >= 0)) {
COORD coord;
coord.X = column;
coord.Y = line;
SetConsoleCursorPosition(
GetStdHandle( STD_OUTPUT_HANDLE ),
coord
);
}
}
void gotoxy (Coord pos) {
gotoxy(pos.x, pos.y);
}
// ========================================================================= //
void render (char image, Coord pos) {
gotoxy(pos);
cout << image;
}
void unrender (Coord pos) {
gotoxy(pos);
cout << ' ';
}
// ========================================================================= //
char randimage (void) {
return (rand() % 132) + 123;
}
mutex xylock;
class Boulder {
char avatar;
Coord pos;
public:
Boulder (int inix) {
pos.x = inix;
pos.y = 0;
avatar = randimage();
};
void fall (void) {
unrender(pos);
pos.y++;
render(avatar, pos);
Sleep(BOULDERspd);
};
void live (void) {
do {
fall();
} while (y() < 20);
die();
};
void die (void) {
unrender(pos);
pos.y = 0;
};
int x (void) { return pos.x; };
int y (void) { return pos.y; };
};
// ========================================================================= //
class thrStack: public Stack<thread*> {
public:
thrStack (): Stack<thread*> () { };
void pushNrun (thread* elem) {
push(elem);
top->core->joinable();
}
};
void randBoulder (void* arg) {
srand(time(NULL));
Boulder boulder(rand() % 40);
boulder.live();
}
void Boulders (void* arg) {
srand(time(NULL));
thrStack stack;
do {
stack.pushNrun(new thread (randBoulder, 0));
Sleep(rand() % 300);
} while(1);
}
// ========================================================================= //
// ========================================================================= //
int main() {
thread raining (Boulders, 0);
raining.join();
}
I'm new to multi-threading so, to fiddle around with it, I'm trying to make a program that makes random characters constantly fall from the top of the screen, as if it were raining ASCII symbols.
I've noticed, however, a little (big) error in my coding:
bool xylock = false;
class Boulder {
char avatar;
Coord pos;
public:
Boulder (int inix) {
pos.x = inix;
pos.y = 0;
avatar = randimage();
};
void fall (void) {
unrender(pos);
pos.y++;
render(avatar, pos);
Sleep(BOULDERspd);
};
void live (void) {
do {
fall();
} while (y() < 20);
die();
};
void die (void) {
unrender(pos);
pos.y = 0;
};
int x (void) { return pos.x; };
int y (void) { return pos.y; };
};
Because the fall() function uses gotoxy, which changes the 'global cursor', multiple calls to gotoxy would mess up the intended execution of the program. If you try to compile the code as-is, you'd get falling letters that constantly switch position and leave garbage of themselves behind.
Is there any way to use or implement a lock for this and future situations alike with just TinyThread? What is the logic of locks implementing in C++, in general?
EDIT: Modified fall(); is it okay, Caribou?
void fall (void) {
lock_guard<mutex> guard(xylock);
unrender(pos);
pos.y++;
render(avatar, pos);
xylock.unlock();
Sleep(BOULDERspd);
};
You can use the tinythread lib:
http://tinythreadpp.bitsnbites.eu/doc/
Look specifically at lock_guard and mutex
multiple calls to gotoxy would mess up the intended execution of the
program. If you try to compile the code as-is, you'd get falling
letters that constantly switch position and leave garbage of
themselves behind.
create a mutex object to synchronise on, and then in the function you want to be thread safe you create a local lock_guard using it. This mutex can be used in multiple places as well using the lock_guard.
Here I created a very basic threading example without a framework or classes. As you can see, threading and syncronisation isn't C++ work, it's OS work! ;-)
Here I created a simple threadfunction, which I call two times. The threads writing the same variable, but can't do that the same time, so have to protect it. In this sample I use a CRITICAL_SECTION object to lock the variable by one thread. If the one thread lock it, the other can't access it and have to wait until it's free.
Have a closer look and see, I also protected the printf operations. What would happen if you don't do this? You will get a very funny outprint! Find out why and you know how threads and locks work. :-)
#include <windows.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <process.h>
//a global variable (just do do someting):
int g_ThreadCounter = 0;
//global variable to end the threads:
bool g_Run = true;
//do not use global variables, there are better solutions! I just did it here to
//keep it simple and focus on the issue!
//a critical section object - something like a "soft-version" of a mutex to synchronize
//write access on variables
CRITICAL_SECTION critical;
//a thread function
unsigned __stdcall threadFunc(void *pThreadNum)
{
unsigned int iThreadNum = reinterpret_cast<unsigned int>(pThreadNum);
do{
//you need the critical section only when you change values:
EnterCriticalSection(&critical);
g_ThreadCounter++;
printf("from thread: ");
printf("%d", iThreadNum);
printf(" counter = ");
printf("%d", g_ThreadCounter);
printf("\n");
LeaveCriticalSection(&critical);
//sleep a secound
Sleep (1000);
}while(g_Run);
_endthreadex(0);
return 0;
}
int main()
{
unsigned int ThreadID1 = 1;
unsigned int ThreadID2 = 2;
//initialize the critical section with spin count (can be very effective in case
//of short operation times, see msdn for more information)
if(!InitializeCriticalSectionAndSpinCount(&critical, 1000))
{
//DO NOT START THE THREADS, YOU DON'T HAVE SYNCHRONISATION!!!
printf("someting went wrong, press any key to exit");
//do some error handling
getchar();
exit(-1);
}
//start the threads
HANDLE thHandle1 = (HANDLE)_beginthreadex(NULL, 0, &threadFunc, (void*) ThreadID1, 0, NULL);
HANDLE thHandle2 = (HANDLE)_beginthreadex(NULL, 0, &threadFunc, (void*) ThreadID2, 0, NULL);
if(thHandle1 == INVALID_HANDLE_VALUE || thHandle2 == INVALID_HANDLE_VALUE)
{
printf("something went wrong, press any key to exit");
//do some error handling
getchar();
exit(-1);
}
//the main thread sleeps while the other threads are working
Sleep(5000);
//set the stop variable
EnterCriticalSection(&critical);
g_Run = false;
LeaveCriticalSection(&critical);
//wait for the thread; infinite means, you wait as long as the
//thread takes to finish
WaitForSingleObject(thHandle1, INFINITE);
CloseHandle(thHandle1);
WaitForSingleObject(thHandle2, INFINITE);
CloseHandle(thHandle2);
DeleteCriticalSection(&critical);
printf("press any key to exit");
getchar();
return 0;
}
Study the OS on which you are working! It's sometimes better than pay too much attention on Frameworks and foreign classes. This can solve a lot of questions!