How to implement kbhit() and gethch() in C++ on linux [duplicate] - c++

This question already has answers here:
Using kbhit() and getch() on Linux
(5 answers)
Closed 6 years ago.
I'm trying to build a primitive snake game.
The function void Input() calls _kbhit() and _getch()
But the problem is that I can't implement these function 'cause conio.h isn't included in the gcc package in linux. Is there an alternative way to accomplish the tasks of _kbhit() and _getch() without using conio header file ?
void Input() // handle controls
{
if(_kbhit()) // boolean positive if key is pressed
{
switch(_getch()) // gets ascii val of key pressed
{
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
case 'x':
gameOver = true;
break;
}
}
}

These functions are sort of "illegal" and are not used anymore in standard C++.
The ncurses library can be helpful.
ncurses, by the way, defines TRUE and FALSE. A correctly configured ncurses will use the same data-type for ncurses' bool as the C++ compiler used for configuring ncurses.
Here is an example illustrating how ncurses could be used like the conio example:
#include <ncurses.h>
int main()
{
initscr();
cbreak();
noecho();
scrollok(stdscr, TRUE);
nodelay(stdscr, TRUE);
while (true) {
if (getch() == 'g') {
printw("You pressed G\n");
}
napms(500);
printw("Running\n");
}
}

Related

How to write piano program in C/C++ [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am trying to write a C program for piano in which the node of piano is controlled by mouse movement. But as in linux #include<dos.h> and #include<conio.h> is not exist, so i am getting error . Is there any alternative library present in linux for #include<conio.h> and #include<dos.h> ?
I have tried the code following.
#include <dos.h>
#include <graphics.h>
union REGS in, out;
void detect_mouse ()
{
in.x.ax = 0;
int86 (0X33,&in,&out); //invoke interrupt
if (out.x.ax == 0)
printf ("\nMouse Failed To Initialize");
else
printf ("\nMouse was Succesfully Initialized");
}
void showmouse_graphics ()
{
int gdriver = DETECT, gmode, errorcode;
initgraph(&gdriver, &gmode, "c:\\tc\\bgi");
in.x.ax = 1;
int86 (0X33,&in,&out);
getch ();
closegraph ();
}
void detect ()
{
int button;
while (!kbhit () )
{
in.x.ax = 3;
int86 (0X33,&in,&out);
button=out.x.bx&7
switch(button)
{
case 1:
print(“left button pressed\n”);
break;
case 2:
print(“right button pressed\n”);
break;
case 4:
print(“middle button pressed\n”);
break;
case 3:
print(“left and right button pressed\n”);
break;
case 5:
print(“left and middle button pressed\n”);
break;
case 6:
print(“right and middle button pressed\n”);
break;
case 7:
print(“all the three buttons pressed\n”);
break;
default:
print(“No button pressed\n”);
}
delay (200); // Otherwise due to quick computer response 100s of words will get print
}
}
void hide_mouse ()
{
in.x.ax = 2;
int86 (0X33,&in,&out);
}
int main ()
{
detect_mouse ();
showmouse_graphics ();
detect ();
hide_mouse ();
return 0;
}
For #include<conio.h> you can use #include <curses.h> which will give you almost all the functionalities. Getchar
For #include<dos.h> it's not usable in any other operating system than DOS and there isn't really something similar with all the functionalities in linux. But you can use usleep(microseconds) in linux when you include #include <unistd.h>.
Or you can use sleep_for in c++:
using namespace std::this_thread; // sleep_for, sleep_until
using namespace std::chrono; // nanoseconds, system_clock, seconds
sleep_for(nanoseconds(20));
For Generating Sound, it seems that this post tries to do something similar/could help with your problem:
Generate Sound Frequency using GCC

Undefined Reference to (error coming in main.cpp file) [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 years ago.
When trying to compile my code in Code::Blocks I receive a bunch of Undefined reference errors. The code is below.
Header
#ifndef BLACKJACK_GAME
#define BLACKJACK_GAME
// A game of blackjack has a deck and two hands
#include "Deck.h"
#include "BlackjackHand.h"
// Different ways the game can end. The first states take precedence over
// over the latter states so check for the early ones first (like blackjack)!
// Note that a "natural 21" is when you are delt two cards totaling 21.
enum eGameState {
GAME_BLACKJACK_PUSH, // Both player and dealer have a natural 21
GAME_DEALER_BLACKJACK, // Dealer has a natural 21
GAME_PLAYER_BLACKJACK, // Player has a natural 21
GAME_DEALER_BUST, // The dealer has more than 21
GAME_PLAYER_BUST, // The player has more than 21
GAME_DEALER_WIN, // The dealer's score is higher than players
GAME_PLAYER_WIN, // The player's score is higher than dealers
GAME_PUSH // The scores are tied
};
class BlackjackGame
{
public:
BlackjackGame();
// Clear the players hands and shuffle the deck
void newGame();
// Play a single round of blackjack showing the output using
// the 'PDcurses' library (for color and card suits).
void playGameCurses();
// Display the deck on the screen (for debugging purposes)
void printDeckCurses();
// Print both players hands to the screen using 'PDCurses'
// If pShowDealerScore is true then the dealer's score is printed
// Otherwise, the dealer's score is shown as '??'
void printHandsCurses(bool pShowDealerScore = false) const;
// Determine the state of the game. Note that if you have not yet
// played a round since you constructed this object or called newGame()
// Then the state returned is not accurate.
eGameState getGameState() const;
private:
// A deck of cards for shufflying and dealing hands
Deck mDeck;
// The two hands for the player and the dealer
BlackjackHand mPlayer, mDealer;
// A helper function for prompting the player (internal use only)
char promptPlayerCurses();
// A helper function to quit the game (internal use only)
void quitGameCurses();
};
#endif
CPP
#include "BlackjackGame.h"
// The library used for our text based user interface
#include <curses.h>
// Normal text color for PDCurses (defined in main)
#define NORM_TEXT 1
// Default constructor (does nothing)
BlackjackGame::BlackjackGame() {}
/* newGame() - Clear the two hands so we are ready for a new game */
void BlackjackGame::newGame()
{
mDealer.clear();
mPlayer.clear();
}
/* playGameCurses() - Play a single round of poker with one human player and one
* dealer following standard Vegas rules. Uses PDCurses for input and output to
* the console.
*
* You must implement this method but you do not need to worry about curses. Call
* 'promptPlayerCurses() to show the hands and prompt the human player to hit, stand
* or quit. This method will return the key they pressed. You can also use
* quitGameCurses() to exit properly if the user chose to 'quit'.
*/
void BlackjackGame::playGameCurses()
{
// TODO: Shuffle the deck and deal the cards (make sure dealer's first card is hidden).
mDeck.shuffle();
mPlayer.takeCard(mDeck.dealCard());
mDealer.takeCard(mDeck.dealCard());
mDealer.hideCard();
mPlayer.takeCard(mDeck.dealCard());
mDealer.takeCard(mDeck.dealCard());
// TODO: Check for a 'natural 21' (blackjack) before playing
if ( mDealer.hasBlackjack() || mPlayer.hasBlackjack())
quitGameCurses();
// TODO: Allower human player to hit, stand and quit as needed (repeat until player is done)
int flag = 0;
while(flag!=1)
{
char input = promptPlayerCurses(); // This line is an example only, a placeholder
switch(input)
{
case 'h': mPlayer.takeCard(mDeck.dealCard());
break;
case 's': flag =1;
break;
case 'q': quitGameCurses();
break;
default: break;
}
}
// TODO: Play the 'dealer' hand according to vegas rules
mDealer.showCards();
while(vegasDealerWouldHit())
{
mDealer.takeCard(mDeck.dealCard());
}
}
/* promptPlayerCurses() - Show the hands and prompt the human player to hit, stand or quit.
* output: returns the single character entered by the player at the prompt.
* - 'h' means hit, 's' means stand
* - 'q' means you should immediatly quit (call 'quitGameCurses()')
*/
char BlackjackGame::promptPlayerCurses()
{
// Show the hands
printHandsCurses();
// Hit or stand?
attron(COLOR_PAIR(NORM_TEXT));
mvprintw(3, 0, "Hit, stand or Quit ('h', 's', 'q'): ");
refresh();
// Read and return a single character
return getch();
}
/* quitGameCurses() - End curses output and exit the program immediately */
void BlackjackGame::quitGameCurses()
{
// End curses output, then pause and exit
endwin();
system("pause");
exit(0);
}
/* printDeckCurses() - A handy function that displays the content of the game deck
* using curses.
*
* This can be handy for debugging your deck and making sure it is getting properly
* shuffled. It is presently used for the fancy opening screen.
*/
void BlackjackGame::printDeckCurses()
{
// Start at the upper left corner of the screen
move(0, 0);
// For all 52 cards
for(int i=1; i<=52; i++)
{
// Get the next card and print it
PrintableCard lCard = mDeck.dealCard();
lCard.printCurses();
// If we've output 13 cards then move down a row
if(i%13 == 0)
{
move(2*(i/13), 0);
}
else
{
// Switch back to normal text color and output ' ' characters
attron(COLOR_PAIR(NORM_TEXT));
if(lCard.getFaceValue() == VALUE_TEN) printw(" ");
else printw(" ");
}
}
}
/* printHandsCurses() - A function to display the current scores and hands for this game
* using curses.
*
* This function is used in promptPlayerCurses() to show the hands before asking them if
* they want to hit or stand. Note that it alsways clears the window before drawing.
*/
void BlackjackGame::printHandsCurses(bool pShowDealerScore) const
{
// Clear window
erase();
// Show dealer and player hands
attron(COLOR_PAIR(NORM_TEXT));
mvprintw(0, 0, "Player: %d\n", mPlayer.score());
move(1, 0); mPlayer.printCurses();
attron(COLOR_PAIR(NORM_TEXT));
if(pShowDealerScore)
{
mvprintw(0, 50, "Dealer: %d\n", mDealer.score());
}
else
{
mvprintw(0, 50, "Dealer: ??\n");
}
move(1, 50); mDealer.printCurses();
refresh();
}
/* getGameStat() - Examine the hands of both players and return the current state of
* the game using the eGameState enum.
*
* You must examine the state of the game by comparing the two hands (their scores and their
* number of cards) and return the appropriate constant from the eGameState enum. Assume
* that the game is over (i.e. the player and dealer have both either gone bust or decided
* to stand).
*/
eGameState BlackjackGame::getGameState() const
{
if(mDealer.hasBlackjack() && mPlayer.hasBlackjack())
{
return GAME_BLACKJACK_PUSH;
}
else if(mDealer.hasBlackjack())
{
return GAME_DEALER_BLACKJACK;
}
else if(mPlayer.hasBlackJack())
{
return GAME_PLAYER_BLACKJACK;
}
else if(mPlayer.score() > 21)
{
return GAME_PLAYER_BUST;
}
else if(mDealer.score() > 21)
{
return GAME_DEALER_BUST;
}
else if(mDealer.score() > mPlayer.score())
{
return GAME_DEALER_WIN;
}
else if(mDealer.score() < mPlayer.score())
{
return GAME_PLAYER_WIN;
}
else {
return GAME_PUSH;
}
}
}
Main
#include <cstdlib>
#include <iostream> // Standard input and output
#include <string>
using namespace std;
#include <curses.h>
#include "BlackjackGame.h"
// Three different types of text colors used with PDCurses
#define NORM_TEXT 1
#define WIN_TEXT 2
#define LOSE_TEXT 3
int main()
{
// Setup 'PDcurses'
initscr();
start_color();
// Define our colors text colors (foreground, background)
init_pair(NORM_TEXT, COLOR_WHITE, COLOR_BLACK);
init_pair(WIN_TEXT, COLOR_YELLOW, COLOR_BLACK);
init_pair(LOSE_TEXT, COLOR_RED, COLOR_BLACK);
// Define our card colors (these are declared in PrintableCard.h)
init_pair(BLACK_CARD, COLOR_BLACK, COLOR_WHITE);
init_pair(RED_CARD, COLOR_RED, COLOR_WHITE);
// Input from the user and a game object
char ch = '\0';
BlackjackGame myGame;
// Output a 'fancy' welcome screen
myGame.printDeckCurses();
attron(COLOR_PAIR(WIN_TEXT));
mvprintw(1, 13, "Welcome to Blackjack!");
mvprintw(5, 11, "Press any key to play ...");
refresh();
// Wait for input (the 'press any key to begin' thing)
ch = getch();
// Back to normal text to start the game
attron(COLOR_PAIR(NORM_TEXT));
do // Loop to play a new game until the user exits
{
// Restart and play a game (using curses)
myGame.newGame();
// Play a round of blackjack (most of the magic happens here!)
myGame.playGameCurses();
// Print the final status of the game
myGame.printHandsCurses(true);
// Print a game results message (use BOLD and the appropriate text color)
attron(A_BOLD);
switch(myGame.getGameState())
{
case GAME_BLACKJACK_PUSH:
attron(COLOR_PAIR(WIN_TEXT));
mvprintw(10, 25, "BLACKJACK TIE!!");
break;
case GAME_DEALER_BLACKJACK:
attron(COLOR_PAIR(LOSE_TEXT));
mvprintw(10, 25, "Dealer Blackjack. You lose.");
break;
case GAME_PLAYER_BLACKJACK:
attron(COLOR_PAIR(WIN_TEXT));
mvprintw(10, 25, "BLACKJACK! You win!");
break;
case GAME_DEALER_BUST:
attron(COLOR_PAIR(WIN_TEXT));
mvprintw(10, 25, "Dealer Bust. You Win!");
break;
case GAME_PLAYER_BUST:
attron(COLOR_PAIR(LOSE_TEXT));
mvprintw(10, 25, "BUST. You lose.");
break;
case GAME_DEALER_WIN:
attron(COLOR_PAIR(LOSE_TEXT));
mvprintw(10, 25, "You lose.");
break;
case GAME_PLAYER_WIN:
attron(COLOR_PAIR(WIN_TEXT));
mvprintw(10, 25, "You Win!");
break;
case GAME_PUSH:
attron(COLOR_PAIR(WIN_TEXT));
mvprintw(10, 25, "It's a tie!");
break;
}
// Turn off bold and return to normal text color
attroff(A_BOLD);
attron(COLOR_PAIR(NORM_TEXT));
// Prompt user to play again
mvprintw(20, 0, "Play again (y/n): ");
refresh();
ch = getch();
} while(ch != 'n');
// Close out 'PDCurses' and pause before exiting
endwin();
system("pause");
return 0;
}
In this program I am trying to create the game BlackJack, most of the game is in other files, but I do not receive errors in the other files. The errors come from the code inside of the Main. The errors are
undefined reference to `BlackjackGame::blackjackGame()
undefined reference to `BlackjackGame::printDeckCurses()
undefined reference to `BlackjackGame::newGame()
undefined reference to `BlackjackGame::playGameCurses()
undefined reference to `BlackjackGame::printedHandsCurses()
undefined reference to `BlackjackGame::getGameState()
With all of these errors coming from the main and these references in the header, that must be my problem, linking the two. Is that correct?
This problem is telling you that you are not linking in the BlackjackGame.o object file when you are building your executable or library.
You must fix your Makefile to link in this file in order to pass the linking stage.
Edit:
Seeing as how you are using Codeblocks for compilation, check these links out(as this error message means different things in different compilers):
undefined reference to function code blocks
Code::Blocks 10.05 Undefined reference to function
It looks like you need to add BlackJackGame.cpp to your project, based on the answer in link 2
Go to Project/Add files to add BlackJackGame source files to your Project, then re-build and that should work

How to check if CD drive is open or closed in linux?

I'm making an application that requires the knowledge of whether a CD drive is open or closed.
eject opens the CD drive, and checks how long it takes to open (a shorter amount of time says it's open, and a longer, well...), but I cannot use this technique, because the application actually opens the drive (and I do not want to re-open the drive if it's closed, neither do I want to close the drive if it is open).
How would I do this on linux? I saw that it is possible to do this under Windows (might be wrong though), but I haven't seen a way of doing this on linux.
If it's not possible using linux API calls, is it possible to implement a low-level function that could do this?
To make the example code work, you should do it this way:
#include <sys/ioctl.h>
#include <linux/cdrom.h>
int result=ioctl(fd, CDROM_DRIVE_STATUS, CDSL_NONE);
switch(result) {
case CDS_NO_INFO: ... break;
case CDS_NO_DISC: ... break;
case CDS_TRAY_OPEN: ... break;
case CDS_DRIVE_NOT_READY: ... break;
case CDS_DISC_OK: ... break;
default: /* error */
}
i.e. the result is returned as ioctl() function result, not into slot argument.
You can get tray state by using the CDROM_DRIVE_STATUS ioctl. All ioctls for CD-drives can be found in /usr/include/linux/cdrom.h
#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
Taken from here
int slot;
ioctl(fd, CDROM_DRIVE_STATUS, slot);
switch(slot) {
case CDS_NO_INFO: ... break;
case CDS_NO_DISC: ... break;
case CDS_TRAY_OPEN: ... break;
case CDS_DRIVE_NOT_READY: ... break;
case CDS_DISC_OK: ... break;
default: /* error */
}

How do I turn off or ignore key repeat for my curses application?

So I recently found curses (specifically PDcurses) and I'm just getting into it. Right now I'm trying to write a little space shooter type game with it and it's worked fine so far for rendering and getting menu type input, but now when I go into the game, I've noticed that key repeat is pretty bad for action games. I need to be able to hold the key and move my avatar every single frame that the key is down. I know how to do this with a normal Win32 application, but I don't have a window and therefore I don't have a wndproc and I can't control the messages the console recieves :/
I don't expect this is something for curses to handle, though if it can that would be awesome, I was really just looking for a work-around that plays nicely with curses.
I have tried cbreak(), nodelay() and raw() to no avail.
Additional info:
Microsoft Visual Studio 2010 Ultimate
PDcurses 3.4, from prebuilt binaries
Windows 7 x64 Ultimate
This is far from a complete solution, and I don't know how it'll interact with PDCurses, but it's an attempt:
In summary, grab the console's handle with GetStdHandle(), configure it for raw reading with SetConsoleMode(), and then read keys one at a time with ReadConsoleInput(). I use a std::set to keep track of the currently pressed keys and so ignore repeats.
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <cassert>
#include <set>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
BOOL success;
success=GetConsoleMode(h, &mode);
assert(success);
mode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
mode |= ENABLE_WINDOW_INPUT;
success=SetConsoleMode(h, mode);
assert(success);
INPUT_RECORD buffer[10];
std::set<WORD> keys_down;
while (true)
{
DWORD count=0;
success=ReadConsoleInput(h, buffer, 10, &count);
if (!success)
{
continue;
}
for (size_t i=0;i<count;++i)
{
switch (buffer[i].EventType)
{
case KEY_EVENT:
{
WORD keycode=buffer[i].Event.KeyEvent.wVirtualKeyCode;
if (buffer[i].Event.KeyEvent.bKeyDown)
{
if (keys_down.find(keycode)==keys_down.end())
{
std::cout<<"Key down: "<<keycode<<std::endl;
keys_down.insert(keycode);
}
}
else
{
if (keys_down.find(keycode)!=keys_down.end())
{
std::cout<<"Key up:"<<keycode<<std::endl;
keys_down.erase(keycode);
}
}
break;
}
default:
break;
}
}
}
}

How to identify shift/ctrl keys were pressed in the linux world (without using GL and X11/XKBlib.h) in C++?

I used to do in windows:
SHORT key1 = ::GetKeyState(VK_LSHIFT)& 0xF0;
SHORT key2 = ::GetKeyState(VK_RSHIFT)& 0xF0;
SHORT key3 = ::GetKeyState(VK_LCONTROL)& 0xF0;
SHORT key4 = ::GetKeyState(VK_RCONTROL)& 0xF0;
bShift = (key1 != 0) || (key2 != 0);
bCtrl = (key3 != 0) || (key4 != 0);
How to detect if the shift/ctrl keys were pressed in the linux world?
Without using GL(it can be pressed not in the graphic window..) or X11..
Is there something general to retrieve it directly form the OS?
Thanks,
Vladimir.
I would do this using Linux Input API. Take a look at Youarefunny's answer here to see how you can check current key state (pressed or released).
Such check may take noticeable amount of time especially if you need to call it very often. So once you determine the initial state you may monitor for changes by reading input events from device file, like this (I skipped error-checking for brevity):
#include <stdio.h>
#include <linux/input.h>
int main (int argc, char *argv[])
{
struct input_event ev;
FILE *kbd = fopen("/dev/input/by-id/usb-Dell_Dell_QuietKey_Keyboard-event-kbd", "r");
while (fread(&ev, sizeof(ev), 1, kbd) == 1)
{
if (ev.type == EV_KEY && (ev.code == KEY_LEFTSHIFT || ev.code == KEY_RIGHTSHIFT))
{
switch (ev.value)
{
case 0: printf("Shift released\n"); break;
case 1: printf("Shift pressed\n"); break;
case 2: printf("Shift repeated\n"); break;
default: break;
}
}
// similarly for KEY_LEFTCTRL, KEY_RIGHTCTRL, etc.
}
fclose(kbd);
return 0;
}
Note that reading /dev/input/* files will probably require root privileges (unless you run chmod before) since default access mode is 640 and the files belong to root.