GetAsyncKeyState not working - c++

I'm fairly new to C++ as I'm more experienced with Java/Python etc. But, I've been trying to implement a simple Trigger Bot, but added a failsafe so that if I press a certain key, the program will call the exit(0) method. But the way I implemented key input doesn't seem to work, could someone maybe help me out?
void MainScan(Contents scan) {
#if DB
int debug = clock();
#endif
while (true) {
for (int y = scan.startY; y < scan.compareY; y++) {
for (int x = scan.startX; x < scan.compareX; x++) {
//SetCursorPos(x, y);
if (GetAsyncKeyState(VK_DELETE)) {
exit(0);
}
}
}
}
}

Here's how you use it: https://msdn.microsoft.com/en-us/library/windows/desktop/ms646293(v=vs.85).aspx
Here's a snippet of code from an old project of mine for a console based maze game:
Difficulty AskDifficulty() {
// xy norm = 1, 2 y++ for rest
point base(1, 2);
drawatxy(1, 2, '*');
while (GetAsyncKeyState(VK_RETURN)) // while it is being pressed, do not consider any input until we let go of the key
g_delay(0.001);
while (true) { // now we let go of it, consider inputs once more
if (GetAsyncKeyState(VK_RETURN) & 0x8000) {
switch (base.y) {
case 2:
return DIFF_EASY;
case 3:
return DIFF_NORM;
case 4:
return DIFF_HARD;
default:
return DIFF_INVALID;
}
}
else if (GetAsyncKeyState(VK_DOWN) & 0x8000) {
if (base.y < 4) {
drawatxy(1, base.y, ' ');
base.y++;
drawatxy(1, base.y, '*');
g_delay(0.125);
}
}
else if (GetAsyncKeyState(VK_UP) & 0x8000) {
if (base.y > 2) {
drawatxy(1, base.y, ' ');
base.y--;
drawatxy(1, base.y, '*');
g_delay(0.125);
}
}
else
_getch();
}
}

Related

Can't figure out how to loop playerturns and moves Tic Tac Toe (C++) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
EDIT: Solved now thank you triple_r and AJNeufield for your help on this problem I was having.
I've looked around multiple websites and YouTube about this and I can't seem to find anything on what I am specifically looking for this as my format for the program is a good bit different than others. Therefore, it's hard to decipher where I need to put the things I do need that I know of.
Please note that I'm relatively new to C++ so I'd appreciate all the feedback or criticism you might provide me.
Also, note my code does compile and run it just does not allow me to put in more than one input and more than likely does not allow for a switch of player turns.
Quick Edit: Switched the code with the new setup suggested by triple_r but I seemed to have messed it up somewhere along the line and it does compile(with the exception of x and y not being utilized and one other error) but it always starts off with player 2 going first and as soon as it receives input it ends automatically with a segmentation fault.
#include <iostream>
#include <cstdlib>
using namespace std;
//////////////////////////////////////////////////////////
void initboard(char board[3][3])
{
int x,y;
for (x=0;x<3;x++)
for (y=0;y<3;y++)
board[x][y]=' ';
return;
}
//////////////////////////////////////////////////////////
void printboard(char board[3][3])
{
int x,y;
for (x=0;x<3;x++)
{
cout<<"\n";
for (y=0;y<3;y++)
{
cout<<" "<<board[x][y]<<" ";
if (y<2) cout<<"|";
}
if (x<2) cout<<"\n===========";
}
return;
}
//////////////////////////////////////////////////////////
void getmove(char board[3][3], int player)
{
return;
}
//////////////////////////////////////////////////////////
int main()
{
bool done=false;
char board[3][3];
int x,y,player=1,turn,playerchoice,playermark;
initboard(board);
turn=0;
do
{
if (player==1)
playermark='X';
else
playermark='O';
if (turn%2)
player=1;
else
player=2;
cout<<"Player "<<player<<" where do you want to move?: ";
cin>>playerchoice;
if (playerchoice==1)
{
board[0][0]=playermark;
}
else if (playerchoice==2)
{
board[0][1]=playermark;
}
else if (playerchoice==3)
{
board[0][2]=playermark;
}
else if (playerchoice==4)
{
board[1][0]=playermark;
}
else if (playerchoice==5)
{
board[1][1]=playermark;
}
else if (playerchoice==6)
{
board[1][2]=playermark;
}
else if (playerchoice==7)
{
board[2][0]=playermark;
}
else if (playerchoice==8)
{
board[2][1]=playermark;
}
else if (playerchoice==9)
{
board[2][2]=playermark;
}
else
{
cout<<"Invalid move ";
}
if (board[x][y]!=' ')
cout<<"Move is already taken.";
board[x][y]=playermark;
if(board[x][y]==' ')
turn++;
}while (!done);
void printboard(char board[3][3]);
return 0;
}
EDIT: based on the updated code
So, the first thing I can see is that you are using x and y in your program but you don't initialize them or assign any values to them. Also, try to use functions/classes/... yo make your code more readable. You already have a function for player move but you are not using it. You can move the large if statement inside that function and that will make your main code shorter and more readable.
Here are my comments on the main part of your program:
int main()
{
// add a new variable to see if the move was valid or not:
bool done=false, validmove = true;
char board[3][3];
int x, y, player = 1, turn = 0, playerchoice, playermark;
initboard(board);
do
{
// swap the two `if`s so you decide who`s turn it is then assign the player mark,
// also, reverse the condition to make sure turn '0' is player 1's turn.
if (!(turn % 2))
player = 1;
else
player = 2;
if (player == 1)
playermark = 'X';
else
playermark = 'O';
cout << "Player " << player << " where do you want to move?: ";
cin >> playerchoice;
// Assign `x` and `y` here instead of updating the board, because you want to make
// sure that the move is valid before putting the mark:
validmove = true;
if (playerchoice == 1)
{
x = 0; y = 0;
}
else if (playerchoice == 2)
{
x = 0; y = 1;
}
else if (playerchoice == 3)
{
x = 0; y = 2;
}
else if (playerchoice == 4)
{
x = 1; y = 0;
}
else if (playerchoice == 5)
{
x = 1; y = 1;
}
else if (playerchoice == 6)
{
x = 1; y = 2;
}
else if (playerchoice == 7)
{
x = 2; y = 0;
}
else if (playerchoice == 8)
{
x = 2; y = 1;
}
else if (playerchoice == 9)
{
x = 2; y = 2;
}
else
{
cout << "Invalid move, try again!";
// Make sure to mark the move as invalid so they get a chance to
// change their move:
validmove = false;
}
// check to see if the turn was valid:
if(validmove)
{
if (board[x][y] != ' ')
{
cout << "Move is already taken, try again";
}
else
{
board[x][y] = playermark;
turn++;
}
}
// have to make sure you have a condition for end of game. A simple
// one is to check if turn is less than `9`, otherwise the board is
// full:
if(turn == 9)
done = true;
// you probably want to add a few more checks to see who won the game.
}while (!done);
// when calling a function, no need to put the return type or parameter type:
printboard(board);
return 0;
}
========================================================================
There are two do-while loops in your program and both seem to be meant as a game loop. What I would do is:
initboard(...);
turn = 0;
do{
//this is the game loop
...;
if( validturn )
turn++;
}while(!done);
release_resources(...);
return 0;
so, you fold everything into one loop. In that loop, you want to:
find who's turn it is:
if (turn % 2)
player = 1;
else
player = 2;
get users input:
std::cin >> playerchoice;
...
convert player choice to grid location:
switch ( move )
{
case 0:
x = 0;
y = 0;
break;
case 1:
...;
...
default:
//invalid move
}
see if the move is valid:
if( board[x][y] != ' ' )
//already taken, invalid move
then apply the move:
board[x][y] = playermark;
I hope this helps.
Your cin >> playerchoice is outside your do { ... } while ( moves != 9); loop. Move it inside.

How do I make a menu with structure array (transfering lua code to c++ code)

I used lua and I coded a menu and I want to make the same thing in c++
function printMenu( menu )
for i = 1,#menu do
if i == selectedItem then
print(">> "..menu[i].text)
else
print(" "..menu[i].text)
end
end
end
-- Handler Method --
function onKeyPressed( key, menu )
if key == keys.enter then
onItemSelected(menu)
elseif key == keys.up then
if selectedItem > 1 then
selectedItem = selectedItem - 1
end
elseif key == keys.down then
if selectedItem < #menu then
selectedItem = selectedItem + 1
end
end
end
function onItemSelected( menu )
menu[selectedItem].handler()
end
-- Main Method --
function main()
while inMainMenu do
term.clear()
term.setCursorPos(1,1)
printMenu(mainMenu)
event, key = os.pullEvent("key")
onKeyPressed(key,mainMenu)
end
end
the array is bellow
mainMenu = {
[1] = { text = "Physics", handler = PhysicsMenu },
[2] = { text = "Math [01-12]", handler = MathMenu1 },
[3] = { text = "Math [12-24]", handler = MathMenu2 },
[4] = { text = "Update", handler = Update },
[5] = { text = "Exit", handler = Exit }
}
so I basically wanted to make this code into c++
and what I tried is bellow
char* menuname[]
= { "calc", "internet", "painter", "movie", "update", "exit" };
void SelectItem(char* menu[])
{
fflush(stdin);
int key = _getch();
if (key == 13)
{
system("CLS");
switch (selecteditem)
{
case 1:Calcmenu(); break;
case 2:CtoF(); wait(); break;
case 3:painter(); break;
case 4:printf("Work In Progress\n"); wait(); break;
case 5:printf("Work In Progress\n"); wait(); break;
case 6:exit(0); wait(); break;
default: mainmenu(); break;
}
}
switch (key)
{
case 72: if(selecteditem > 1) selecteditem -= 1; break;
case 80: if (selecteditem < 6) selecteditem += 1; break;
}
}
void printmenu(char* menu[])
{
gotoxy(20, 10);
int menusize = strlen(*menu);
for (int i = 0; i < menusize; i++)
{
if (i == selecteditem - 1)
{
gotoxy(30, 9 + i);
printf(">>[%d]%s\n", i + 1, menu[i]);
}
else
{
gotoxy(30, 9 + i);
printf(" [%d]%s\n", i + 1, menu[i]);
}
}
}
void main()
{
while (1)
{
system("CLS");
printmenu(menuname);
SelectItem(menuname);
}
}
the thing is that in lua, I was able to make a array and just use only 3 function to make any menu what so ever. but in c++ I think I have to use struct and make a new array like in the lua.
Your coding is quite good. I mean, the Lua. You'll be a good C programmer too after some practice.
Here's how to do it in C (it's not really C++):
#include <stdio.h>
/* ---------------------- type -------------------------*/
/* Define type 'menu_item' as a menu item. */
typedef struct {
char *text;
void (*handler)(); /* a pointer to a function */
} menu_item;
/* --------------------- handlers ----------------------*/
void ItemCalc()
{
printf("Launching the calculator...\n");
}
void ItemPainter()
{
printf("Launching the painter...\n");
}
void ItemMovie()
{
printf("Launching the movie...\n");
}
/* --------------------- data --------------------------*/
menu_item my_menu[] = {
{ "calc", ItemCalc },
{ "painter", ItemPainter },
{ "movie", ItemMovie },
};
int my_menu_size = sizeof(my_menu) / sizeof(menu_item);
int selecteditem = 1;
/* -------------------- I/O-----------------------------*/
/*
Doing I/O is very platform-dependent. On my system there
isn't _getch(). So to make it possible to run this program
everywhere we simulate an I/O system:
*/
int _key = 0;
void simulate_key_press(int key)
{
_key = key;
}
int read_key()
{
return _key;
}
/* -----------------------------------------------------*/
void SelectItem(menu_item menu[], int menu_size)
{
fflush(stdin);
int key = read_key();
if (key == 13)
{
printf("I'm executing item %d:\n", selecteditem);
menu[selecteditem].handler();
}
else
{
int num = (key - '0'); // convert characters '1'..'9' to integers 1..9.
if (num >= 1 && num <= menu_size) {
selecteditem = num;
printf("item %d selected.\n", num);
}
else
printf("Invalid key. Either ENTER or digits are allowed\n");
}
}
void printmenu(menu_item menu[], int menu_size)
{
int i;
for (i = 0; i < menu_size; i++)
{
if (i == selecteditem - 1)
{
printf(">>[%d]%s\n", i + 1, menu[i].text);
}
else
{
printf(" [%d]%s\n", i + 1, menu[i].text);
}
}
}
void main()
{
printmenu(my_menu, my_menu_size);
simulate_key_press('2');
SelectItem(my_menu, my_menu_size);
printmenu(my_menu, my_menu_size);
simulate_key_press(13);
SelectItem(my_menu, my_menu_size);
}
As for working with arrays: there are two ways to figure out their size. Above I explicitly told the function the size of the array. A different approach is to use a "sentry" value to mark the end of the array:
menu_item my_menu[] = {
{ "calc", ItemCalc },
{ "painter", ItemPainter },
{ "movie", ItemMovie },
{ NULL, NULL },
};
and then in your loop you halt when you reach this element:
void printmenu(menu_item menu[])
{
int i;
for (i = 0; menu[i].text != NULL; i++)
{
There are lots of differences between a "scripting" language like Lua to a low-level language like C (or C++). I hope my code will motivate you to learn more. Even if you won't eventually use C it's worth learning it to understand how the machine actually works.

Convert char to string doesn't work fine C++

Well I have that code:
for (int x = 0; x<(worldWidth-1); x++) {
for (int y = 0; y<(worldHeight-1); y++) {
sf::Texture texture;
if (!texture.loadFromFile("images/blocks/" + ruta(mapa[y][x]) + ".png"))
return -1;
sf::RectangleShape rectCaja(sf::Vector2f(16, 16));
rectCaja.setPosition(sf::Vector2f(x*16, y*16));
rectCaja.setTexture(&texture);
window.draw(rectCaja);
}
}
That prints boxes (of 16*16 pixels), that are "blocks" in a game the problem is that it doesn't print any block, it crashes directly I don't know why :/
I know (by consoles tests) that array "mapa" isn't wrong... So the only explanation that I have is that ruta function doesn't work fine... (I have tested it with a std::string var = "dirt"; and it works fine)... :/
std::string ruta(char id) {
if (id=='0') return "air";
if (id=='1') return "stone";
if (id=='2') return "dirt";
if (id=='3') return "grass_side";
if (id=='4') return "coal_ore";
}
If somebody wants the hold code there is: http://pastebin.com/5jvbzwkR
Thanks! :P
Only a guess because there isn't enough information to be sure but this might be the answer
std::string ruta(int id) {
if (id==0) return "air";
if (id==1) return "stone";
if (id==2) return "dirt";
if (id==3) return "grass_side";
if (id==4) return "coal_ore";
}
In C++ you have to be careful about types, and understand the difference, for instance, between an int and a char. A char with value '3' is not the same an an int with value 3.
One issue I immediately see is that you're comparing an int to a char. Consider:
std::string ruta(int id)
{
switch( id )
{
case 0:
return "air";
case 1:
return "stone";
case 2:
return "dirt";
case 3:
return "grass_side";
case 4:
return "coal_ore";
}
}
Here is your scene declaration:
int scene[worldWidth][worldHeight];
Here is how you fill up your scene:
while (!finished) {
if (yPos >= topOfTheWorld) {
scene[xPos][yPos] = 1;
}
else if(yPos < topOfTheWorld) {
scene[xPos][yPos] = 0;
}
//etc...
}
Here is how you write into your mapa.txt:
std::ofstream output("mapa.txt");
for(int y=0;y<worldHeight;y++) {
for(int x=0;x<worldWidth;x++) {
output<<scene[x][y];
if(x<(worldWidth-1)){output<<",";}
}
if(y<(worldHeight-1)){output<<std::endl;}
}
Basically this all means that you are writing the numerical value 0 and 1 into your mapa.txt and not the character values '0' and '1'. Yet in your ruta function you compare with '0' and '1'. You should compare with 0 and 1 without the single quotes (').

Infinite while loop with a std::ofstream C++

Well I have that code that saves an array map on a txt file:
std::ofstream output("mapa.txt");
for(int y=0;y<worldHeight;y++) {
for(int x=0;x<worldWidth;x++) {
output<<scene[x][y];
if(x<(worldWidth-1)){output<<",";}
}
if(y<(worldHeight-1)){output<<std::endl;}
}
I want to integrate it to a while loop:
std::ofstream output("mapa.txt");
while (true) {
if (yPos == topOfTheWorld) {
scene[xPos][yPos] = 2;
} else if (yPos >= topOfTheWorld) {
scene[xPos][yPos] = 1;
} else if(yPos < topOfTheWorld) {
scene[xPos][yPos] = 0;
} else {
scene[xPos][yPos] = 0;
}
output<<scene[xPos][yPos] << ",";
//if(xPos<(worldWidth-1)){output<<",";}
//if(yPos<(worldHeight-1)){output<<std::endl;}
yPos++;
if(yPos>worldHeight) {
output<<std::endl;
slope = random(5)-2;
if(topOfTheWorld<(worldHeight/6)) {
slope = 1;
} else if(topOfTheWorld>(worldHeight-10)) {
slope = -1;
}
topOfTheWorld += slope;
yPos = 0;
xPos++;
}
if (xPos>=worldWidth) {
break;
}
}
But for some reason the 'while' loop becomes infinite... :/
What can I do?
The code looks good.
However I'm not sure if scene is correctly allocated.
You have yPos>worldHeight and below xPos>=worldWidth which suggests that you're not sure how to compare these. I suspect you got at least one of them wrong. This can easily write outside the scene variable and overwrite yPos or xPos.
Try changing to ypos>=worldHeight and see if that works.
If not check how much space you allocate for scene and if it looks OK try making it a bit bigger.

C++ console game input && refresh function

I am writing a small console adventure game and I faced a few problems.
1. The input is kinda laggy, I'm using while loop ( while(getch() == 'w') ). After a key is pressed the first time, nothing happens (you have to press it 2 times) and if you switch directions (press key A/D/S) it also doesn't react the 1st time. If you hold a key, it works fine. How can this be fixed?
2. Here's the function I use to refresh game (render the game scene when a key is pressed):
void refresh(char map[Y][X])
{
system("cls");
for (int i = 0; i<UP; i++)
{
cout<<endl;
}
for (int i = 0; i<Y; i++)
{
for (int k = 0; k<LEFT; k++)
{
cout<<" ";
}
for (int j = 0; j<X; j++)
{
cout<<map[i][j];
}
cout<<endl;
}
}
When I use this function once, it's ok, but when they key is pressed or held multiple times - the game field starts to flash. I figured that I need to redraw only a part of the field (where changes are made/movements are done), not the whole field. Can you offer any ideas how to do that?
The sample code for input:
while(getch() == 'w')
{
if (map[y-1][x]!= WALL)
{
map[y-1][x] = CHARACTER;
map [y][x] = ' ';
y--;
refresh(map);
Sleep(SPEED); // this is unnecessary, SPEED is 0, I just kept it for tests
}
}
Basically, the main function looks like this:
int main()
{
(...) Variables (...)
generateMap(FROM FILE);
refresh(); // First initialization of the field
while (getch() != 'q') // While not quitting
{
while(getch() == 'w')
{
if (THE FIELD ABOVE IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
while(getch() == 's')
{
if (THE FIELD BELOW IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
while(getch() == 'a')
{
if (THE FIELD ON THE LEFT IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
while(getch() == 'd')
{
if (THE FIELD ON THE RIGHT IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
return 0;
}
Don't use system("cls"), it is really slow, instead set the cursor on the beginning of the screen with the following code:
COORD cur = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cur);
You should call getch() only one time in the loop, like this:
char key;
do
{
key = getch();
if(key == 'w')
{
//do something
}
//the other if statements
}while(key != 'q');
The code should have only one getch() in the whole code (if possible) and inside a switch you do the action for each input. So, it is switch inside the loop, and not loops inside the switch. Something like this:
while ((ch = getch()) != 'q')
{
switch (ch)
{
case 'a':
GoLeft();
break;
...
}
}
There is a library called ncurses that you can use to move the cursor around the screen, and write anything anywhere.
It looks like your problem is calling getch() multiple times. Have only one loop, and call getch() once per loop, and store the result. Test that result for each value (q, w, s, ...) for each iteration of the loop.
I would recommend you to use function input() as it stands:
void input()
{ if (GetKeyState('W') & 0x8000) // That means when button "W" is pressed
... your code ...
// (changes global variables, or you can pass variables by reference)
}
without any getch() command that stops your game every single time.
You can use it with the draw() and calculate()/refresh() functions in the main(), like:
int main()
{
... other part of code ...
while (!gameover)
{
input();
calculate();
draw();
}
}
so that you will always have some sort of input value before the calculations, and then you would draw (+ it's much easier to debug ;) )