Program Crashes After Checking for Console Mouse/Keyboard Input
Author |
Message |
HRI
|
Posted: Wed Apr 27, 2011 9:38 pm Post subject: Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
I use the GNU G++ compiler (default for C::B).
First of all, this is a small connect 4 game. What I'm trying to achieve is to let the user either press a key (continues when key hit is 1-7, ignores all others) or when they click inside the board on the column they want. It only crashes if I click in a valid position or press a valid key :/
It worked perfectly fine for just keyboard input with the following code:
c++: |
char column = NULL; // used for the character the user inputs
cout << "Enter a column (1 to 7): "; // output prompt
while (column = getch()) // get key press
{
if (int(column) >= 49 && int(column) <= 55) // if character is from 1 to 7
{
system ("cls"); // clear screen
return int(column) - 49; // return 0 to 6, column entered minus 1
break; // exit while loop
} // end if
} // end while
|
Now please be aware that the following is a bit messy. I've just been adding, not cleaning until it works. Also, I'm pretty sure some of this is c, but checking where the mouse was and where it was when the left button was clicked worked like a charm in a test program I made.
c++: |
//inputColumn()
{
HANDLE hand = GetStdHandle (STD_INPUT_HANDLE); // used for the window handle
INPUT_RECORD buffer [128]; // buffer to store records
DWORD numRead; // number of records read
HANDLE cursor = GetStdHandle (STD_OUTPUT_HANDLE); // handle to cursor (the flashing one)
COORD point; // a point
point.X = 0; // left column
point.Y = 15; // past the other graphics
POINT pos; // a point
RECT rec; // 4 members: top, left, bottom, right (used for window position)
HWND hwnd = GetConsoleWindow(); // get handle to console window (I wasn't sure if hand was this or not)
GetCursorPos (&pos); // get mouse position (this is for experimenting where coords are for where to click)
GetWindowRect (hwnd, &rec); // get window position
string title = ::integerToString (pos.x - rec.left - 6); // title of window starts as x coordinate of cursor
title += " | "; // add separator
title += ::integerToString (pos.y - rec.top - 32); // add y coord
SetConsoleTitle (title.c_str()); // set title
SetConsoleMode (hand, ENABLE_MOUSE_INPUT); // allow mouse input
SetConsoleCursorPosition (cursor, point); // set cursor position to just below all other text
char column = NULL; // used for the character the user inputs
cout << "Enter column (1 to 7): "; // output prompt
while (1) // infinite loop
{
ReadConsoleInput (hand, buffer, 128, &numRead); // read input buffer
for (int i = 0; i < numRead; ++i) // go through read records
{
switch (buffer[i].EventType) // make decision based on type of event
{
case MOUSE_EVENT: // if mouse event
MouseProc (buffer [i].Event.MouseEvent, column); // call mouse procedure
break; // exit switch
case KEY_EVENT: // if keyboard event
KeyProc (buffer [i].Event.KeyEvent, column); // call keyboard procedure
break; // exit switch
} // end switch
} // end for
if (int(column) >= 49 && int(column) <= 55) // if character is from 1 to 7
{
system ("cls"); // clear screen
return int(column) - 49; // return 0 to 6, column entered minus 1
break; // exit while loop
} // end if
} // end while
} // end function
|
c++: |
// MouseProc (takes MOUSE_EVENT_RECORD and char & (the column))
POINT pos; // a point
RECT rec; // up until the switch is kind of left over from a point before
HWND hwnd = GetConsoleWindow();
GetCursorPos (&pos);
GetWindowRect (hwnd, &rec);
string title = ::integerToString (pos.x - rec.left - 6);
title += " | ";
title += ::integerToString (pos.y - rec.top - 32);
SetConsoleTitle (title.c_str());
switch (mouse.dwButtonState) // check state of mouse
{
case FROM_LEFT_1ST_BUTTON_PRESSED: // if left button pressed
{
int xCoord = pos.x - rec.left - 6; // xccord is where the mouse is relative to desktop minus window's left border minus 6 for the edge of window
int yCoord = pos.y - rec.top - 32; // ycoord is mouse's y position minus top minus 32 for top edge
if (xCoord > 23 && xCoord < 52 && yCoord < 153) // if mouse is in first column
{
column = '1'; // set value of column passed as argument to '1' (remember the user was pressing '1', not '0')
return; // exit procedure
} // end if
if (xCoord > 52 && xCoord < 83 && yCoord < 153) // repeat the rest for other columns (and yes, I'm going to clean it up after)
{
column = '2';
return;
}
if (xCoord > 83 && xCoord < 116 && yCoord < 153)
{
column = '3';
return;
}
if (xCoord > 116 && xCoord < 148 && yCoord < 153)
{
column = '4';
return;
}
if (xCoord > 148 && xCoord < 179 && yCoord < 153)
{
column = '5';
return;
}
if (xCoord > 179 && xCoord < 209 && yCoord < 153)
{
column = '6';
return;
}
if (xCoord > 209 && xCoord < 240 && yCoord < 153)
{
column = '7';
return;
}
break;
}
}
column = 1; // set column's int value to 1 if none of the above
}
|
c++: |
// KeyProc (takes KEY_EVENT_RECORD and char &)
{
if (key.bKeyDown) // if key was pressed
{
if (key.wVirtualKeyCode == 0x31) // if key code is code for '1'
{
column = '1'; // set column to '1'
return; // exit function
} // end if
if (key.wVirtualKeyCode == 0x32) // repeat for other columns (I'm obviously planning on cleaning this one up after >.>)
{
column = '2';
return;
}
if (key.wVirtualKeyCode == 0x33)
{
column = '3';
return;
}
if (key.wVirtualKeyCode == 0x34)
{
column = '4';
return;
}
if (key.wVirtualKeyCode == 0x35)
{
column = '5';
return;
}
if (key.wVirtualKeyCode == 0x36)
{
column = '6';
return;
}
if (key.wVirtualKeyCode == 0x37)
{
column = '7';
return;
}
}
else
{
column = 1; // set column to char (1) if none of the above
}
}
|
Ask any questions you have. Basically the other one that worked drew an ASCII box in the middle of the console window and then checked the mouse like this one does and makes a message box upon clicking saying either that they clicked in the box or didn't click in the box. That one worked perfectly fine.
By crash I mean it comes up with the application error window with the option to send a report to Microsoft and returns 0xC0000005.
Thanks in advance for any help!
Description: |
Picture of the game when choosing a column. |
|
Filesize: |
8.54 KB |
Viewed: |
7828 Time(s) |
|
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
DemonWasp
|
Posted: Thu Apr 28, 2011 10:48 am Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
I'm no C++ expert, but shouldn't it be:
if you're trying to assign to the value the pointer points to?
|
|
|
|
|
|
crossley7
|
Posted: Sat Apr 30, 2011 7:00 pm Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
I haven't done too many games with c++ as I tought myself it last semester and have mostly done dwite style problems and mathematics related programs (ie factoring), but I did write a chess program, and it may help and clean up you code a lot if you checked out SDL. It requires a download, but makes things easier specifically mouse events and there are easy tutorials on how to use it. It handles all events in 1 variable. I haven't used STD GUI so I can't really help you with the code other than to say trying to make a game that is run in the console is not very pleasing and limits what you can do with the appearance.
If you want to make a game look good, you may as well go all out. Sorry if this post is of no use
|
|
|
|
|
|
HRI
|
Posted: Sun May 01, 2011 7:42 pm Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
Sorry I haven't been able to check this for so long.
@DemonWasp: What I'm doing when I'm specifying a char & parameter is telling the compiler to rather than make a copy of what gets sent to the function in the argument, send the actual object itself. In this case it would send the same char variable "column" that it uses in the other function and whatever changes are made to it are carried back. This is the way the whole connect 4 program is set up, passing along objects from function to function since I couldn't get declaring the objects I'd need in a namespace to work. I will try making it pointer-oriented though, and indeed, you are correct. The * dereferences it so that it pertains to the value contained in the address as opposed to the address itself. I think this is where the confusion lied as the & operator can also be used to reference the address of a variable, but in this case it is saying to pass by reference, rather than by value.
@crossley7: I haven't actually gotten into SDL yet, although I very much plan to in the near future! The reasoning behind this is that the main focus is to get the actual engine and the AI working before making it look nice. This was supposed to be a pretty simple approach to add a neat option to the game as we haven't done any graphics or anything of the sort yet in class and I've been exploring the Windows API in my spare time. We aren't getting marked on appearance, but we will try to get it looking good after the AI is done. We were initially thinking of linking it with a java application while this runs in the background, doing the processing. It's a neat idea, but learning a C++ graphics library could go a long way. I do agree with your logic though, as I often find myself adding every little thing to make it look/act as perfect as I can muster.
|
|
|
|
|
|
DemonWasp
|
Posted: Sun May 01, 2011 9:28 pm Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
What I meant is that:
is wrong because it's assigning the column pointer to be '1' (value 49, or 0x00000031). When you next try to dereference the column pointer after that, you're pointing at an invalid location because you've overwritten part of the pointer. This explains the crash, because you're making an invalid memory access (segmentation fault / violation).
The correct code, as I suggested in my first response, assigns the value of the char address that column points to. You could also use the (subtly different):
though I wouldn't recommend that as if you ever modify the value that column points to after such an assignment, you will hit a different kind of crash (modifying read-only memory).
|
|
|
|
|
|
HRI
|
Posted: Mon May 02, 2011 7:32 pm Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
The weird thing about that is that I have most of my other functions taking arguments of char &, Board &, Game &, whatever it is I'm passing around, but maybe I never changed any of those without using a set function O_o.
I really could've sworn that when we learned about pass-by-value and pass-by-reference the following code worked (quick draft):
c++: |
void addOne (int &);
int main()
{
int x = 0;
cout << x;
addOne (x);
cout << x;
}
void addOne (int &num)
{
++num;
}
|
And using pointer logic, would this not be equivalent to:
c++: |
void addOne (int *);
int main()
{
int x = 0;
cout << x;
addOne (&x); // this is how microsoft does it i believe
cout << x;
}
void addOne (int *num)
{
++*num;
}
|
What I'm saying is, when I pass in column, it should be passing that actual variable's value which can be changed as I please as if the function was not a function at all, but pasted into the other function where it is called. If the addOne example works (which I'm sure it did when I tried something of the sort) then this should work the same way. Anyways, I have a bit of time now that I'll try a couple things with it and let you know what happens.
|
|
|
|
|
|
HRI
|
Posted: Mon May 02, 2011 7:58 pm Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
Ok, I changed the parameter to char *column, and every time column was assigned a value I put a * in front. Also, I put a & before the argument column for the two procedures. It's still doing the same thing.
It didn't compile by simply just putting a * in front because I believe there wasn't an address to begin with.
Think of it this way (forgetting about some certain syntax issues):
c++: |
//pass-by-value
void addOne (MyInt num)
==
void addOne (MyInt *num = new MyInt) // creates new object of type MyInt to use in function
...
delete num;
----------------------
void addOne (MyInt &num)
==
void addOne (num) // I'm not absolutely solid on how the compiler keeps track of all the variables, but it would pass the actual variable address or whatever, instead of allocating a different memory block and deallocating it after
|
Next test, though I hate to say it, is not using new procedures for the events... duh duh duh
|
|
|
|
|
|
HRI
|
Posted: Mon May 02, 2011 8:10 pm Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
Yeah, Windows doesn't like you taking out their procedures. I just succeeded in making the mouse input not work and the key input doing the same thing lol
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
DemonWasp
|
Posted: Mon May 02, 2011 10:46 pm Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
I haven't taken the time to decipher everything you said above. What you should be doing is:
code: |
void addOne ( int *num ) {
++(*num);
}
|
Which you call by:
code: |
int foo = 1;
addOne ( &foo );
// foo is now equal to 2
// OR
int *bar;
*bar = 3;
addOne ( bar );
// *bar is now equal to 4
|
|
|
|
|
|
|
HRI
|
Posted: Thu May 05, 2011 6:34 pm Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
I tried changing everything to your first solution of having a pointer parameter and supplying an address argument, but the same thing happened.
|
|
|
|
|
|
HRI
|
Posted: Thu May 05, 2011 6:57 pm Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
Welllll....... I just took this code, and drew a generic, empty board in a separate program and outputted the return value. Guess what, everything worked fine :s
So the issue then is not the way the functions take arguments or change the column, but how it is implemented within the game.
I'll get back if I notice anything else.
Description: |
Working version in separate source code. |
|
Download |
Filename: |
pointer and address function.cpp |
Filesize: |
7.42 KB |
Downloaded: |
290 Time(s) |
|
|
|
|
|
|
HRI
|
Posted: Thu May 05, 2011 8:03 pm Post subject: RE:Program Crashes After Checking for Console Mouse/Keyboard Input |
|
|
BREAKING NEWS:
I'm not quite sure how it got there, but
c++: |
while (column = getch())
|
(which is the style I use for keyboard-only inputs) should be
That explains why the mouse wasn't working at all and why the keyboard just ended up making it confused >.>
Now for some reason it's not adding any tokens... I hope that's an easy fix though!
EDIT:
It's still acting as if a token was dropped there, it's just not showing them. I think I'm close! That's a good thing if I plan to add mouse capabilities elsewhere. It could add so much spice to the program, and there's really not enough time to learn a graphics library. Still need to do the AI...
EDIT:
heh heh heh...must've accidentally changed where it outputs the character to a space when I was transferring that to the test program...
Stupid me >.>
|
|
|
|
|
|
|
|