问题
I am making a game in C, and when the user input the Konami code (cheat code), the program should print out the correct answer. (edit #3) found out that my program does not "read" the arrow keys whenever I input it, how do I make it so? pls. see my comment below
Here is my updated code (edit #2): //try konami
#include<stdio.h>
#include<string.h>
main() {
int c;
char cheat[] = {24,24,25,25,27,26,27,26,98,97}; //thanks to Vicky for clarifying this
char guess[100];
printf("Enter guess: ");
scanf("%c", &guess);
//just checking if the cheat array is right, and yes it is. I'll remove this later
for ( c = 0; c < 11; c++ ) {
printf("%c", cheat[c]);
}
//comparison of the guess (input) to the cheat code
if (strcmp (cheat, guess) == 0 )
printf("\nYou win!");
else
printf("\nLol!");
}
Now, my problem is it always prints Lol! even though I input the cheat code correctly . . .
note: this is for my intro class in programming (my first time in c too). lessons covered so far are basics, loops, arrays and strings (no functions yet but i understood that now, no structures and further pls. thank you :)
回答1:
my question is how do i check it coming from the user
I'm hearing that you want to know when the user presses an arrow key? I had to do this in C++ and it turned out to be a very enlightening experience, so although you are using C and not C++ i will still share what i remember.
Arrow keys
take a sequence of bytes instead of one AND are usually implemented at the hardware level!
Though whatever operating system you are using should have support (goodbye portability), the term you need to be looking for is key codes
and in windows
they call them Virtual-Key Codes
On Windows
I had learn to program with the win32api.
I can easily show you the key codes
for windows (and i will paste them from that link) but they are no good to you unless you want to commit to a windows event driven type program (maybe you already are?), these codes are fetched from the key
events in your program and are not ascii-codes
and i would go as far to assume specific to windows
.
VK_LEFT
0x25
LEFT ARROW key
VK_UP
0x26
UP ARROW key
VK_RIGHT
0x27
RIGHT ARROW key
VK_DOWN
0x28
And in linux I still had to deal with events, this time using X11, oh the joys i had with X11! the keycodes here are called XK_[key]
i.e XK_left
.
These key codes are defined in the header <X11/keysymdef.h>
- Xlib programming manual
see header online
#define XK_Left 0xff51 /* Move left, left arrow */
#define XK_Up 0xff52 /* Move up, up arrow */
#define XK_Right 0xff53 /* Move right, right arrow */
#define XK_Down 0xff54 /* Move down, down arrow */
Hopefully this can set you on the right path, whenever i need arrow keys
now i just use wasd
.
EDIT: This is the windows one, i condensed it down from the C++ game i made to this C program,it's a lot of code, anything that looks like it shouldn't be there probably shouldn't, but it compiles and reads the arrow keys, so everything you need is in this source atleast.
WINDOWS;
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
#include <Tchar.h>
//directional keys
#define key_left 0x25
#define key_up 0x26
#define key_right 0x27
#define key_down 0x28
// to quit
#define key_escape 0x1B
char checkType(INPUT_RECORD *buffer, int i);
int checkKey(INPUT_RECORD *buffer, int i);
void outputString(const char *str, SHORT col, SHORT row);
void outputChar(char ch, SHORT col, SHORT row);
void clearScreen(void);
CHAR_INFO *p_consoleBuffer;
HANDLE whnd; // handle to write console
HANDLE rhnd; // handle to read console
SMALL_RECT winSize;
COORD buffSize;
SHORT consoleHeight = 25;
SHORT consoleWidth = 60;
DWORD Events = 0; // Event count
DWORD EventsRead = 0; // Events read from console
int _tmain(int argc, _TCHAR* argv[]){
// set up handles for read/writing:
whnd = GetStdHandle(STD_OUTPUT_HANDLE);
rhnd = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleTitle(TEXT("DEMO WIN PROG"));
SMALL_RECT winLen = {0,0,((SHORT)consoleWidth-1),((SHORT)consoleHeight-1)};
COORD bLen = {consoleWidth,consoleHeight}; // width / height
winSize = winLen;
// set console size
SetConsoleWindowInfo(whnd, TRUE, &winSize);
// set the buffer size coords
SetConsoleScreenBufferSize(whnd, buffSize);
CHAR_INFO consoleBuffer[consoleHeight*consoleWidth];
p_consoleBuffer = consoleBuffer;
CONSOLE_CURSOR_INFO cci;
cci.dwSize = 1;
cci.bVisible = FALSE;
SetConsoleCursorInfo(whnd, &cci);
clearScreen();
int Running = 1;
char type = 0;
while(Running) {
//game loop
GetNumberOfConsoleInputEvents(rhnd, &Events);
if(Events != 0){ // something happened
// create buffer the size of how many Events & store
INPUT_RECORD eventBuffer[Events];
// fills buffer with events and save count in EventsRead
ReadConsoleInput(rhnd, eventBuffer, Events, &EventsRead);
DWORD i;
for(i = 0; i<EventsRead; ++i){
type = checkType(eventBuffer,i);
if(type == 'k'){ // event type was key
int key = checkKey(eventBuffer, i);
int arrow_key_pressed = FALSE;
switch (key){
case key_up:
case key_down:
case key_left:
case key_right:
// IF ANY ARROW KEY WAS PRESSED, EXECUTION WILL "COLLAPSE" TO HERE
arrow_key_pressed = TRUE;
break;
case key_escape:
// escape was pressed
Running = 0;
break;
default:
// no case was pressed
break;
}
clearScreen();
if(arrow_key_pressed){
const char *str = "Arrow key was pressed";
outputString(str, 20, 12); // roughly centre
}else {
const char *str = "Arrow key was not pressed";
outputString(str, 20, 12);
}
}else if(type == 'm'){
// MOUSE CLICK, I'M NOT COVERING SORRY.
}
}
}
}
return 0;
}
char checkType(INPUT_RECORD *buffer, int i){
if(buffer[i].EventType == MOUSE_EVENT){
return ('m');
}else if(buffer[i].EventType == KEY_EVENT){
return ('k');
}else return (0);
}
int checkKey(INPUT_RECORD *buffer, int i){
return (buffer[i].Event.KeyEvent.wVirtualKeyCode);
}
void outputString(const char *str, SHORT col, SHORT row){
SHORT fs_len = strlen(str);
int i;
for(i = 0; i<fs_len; ++i){
outputChar(str[i], col++, row);
}
}
void outputChar(char ch, SHORT col, SHORT row){
p_consoleBuffer[row*consoleWidth+col].Char.AsciiChar = ch;
p_consoleBuffer[row*consoleWidth+col].Attributes = 240;
SHORT CH = consoleHeight, CW = consoleWidth;
COORD charBufSize = {CW,CH};
COORD charPos = {0,0};
SMALL_RECT writeArea = {0,0,CW,CH};
WriteConsoleOutputA(whnd,p_consoleBuffer,charBufSize,charPos,&writeArea);
}
void clearScreen(void){
int i;
for(i = 0; i<(consoleHeight*consoleWidth); ++i){
//fill it with white-backgrounded spaces
p_consoleBuffer[i].Char.AsciiChar = ' ';
p_consoleBuffer[i].Attributes =
BACKGROUND_BLUE |
BACKGROUND_GREEN |
BACKGROUND_RED |
BACKGROUND_INTENSITY;
}
// clear screen
SHORT CH = consoleHeight, CW = consoleWidth;
COORD charBufSize = {CW,CH};
COORD charPos = {0,0};
SMALL_RECT writeArea = {0,0,CW,CH};
WriteConsoleOutputA(whnd,p_consoleBuffer,charBufSize,charPos,&writeArea);
}
/* Remember i did this in c++, i made a class with these ints
to represent the virtual key codes, you can define them how you
want like i did or use windows actual definitions.
//special keys
key_escape = 0x1B;
key_space = 0x20;
key_home = 0x24;
key_end = 0x23;
key_pgUp = 0x21;
key_pgDown = 0x22;
key_caps = 0x13;
key_shift = 0x10;
key_ctrl = 0x11;
key_backspace = 0x08;
key_tab = 0x09;
key_enter = 0x0D;
key_alt = 0x12;
key_delete = 0x2E;
//directional keys
key_left = 0x25;
key_up = 0x26;
key_right = 0x27;
key_down = 0x28;
//number keys
key_0 = 0x30;
key_1 = 0x31;
key_2 = 0x32;
key_3 = 0x33;
key_4 = 0x34;
key_5 = 0x35;
key_6 = 0x36;
key_7 = 0x37;
key_8 = 0x38;
key_9 = 0x39;
// alphabet keys
key_a = 0x41;
key_b = 0x42;
key_c = 0x43;
key_d = 0x44;
key_e = 0x45;
key_f = 0x46;
key_g = 0x47;
key_h = 0x48;
key_i = 0x49;
key_j = 0x4A;
key_k = 0x4B;
key_l = 0x4C;
key_m = 0x4D;
key_n = 0x4E;
key_o = 0x4F;
key_p = 0x50;
key_q = 0x51;
key_r = 0x52;
key_s = 0x53;
key_t = 0x54;
key_u = 0x55;
key_v = 0x56;
key_w = 0x57;
key_x = 0x58;
key_y = 0x59;
key_z = 0x5A;
*/
LINUX: (X11) This is that example program i used, it was actually when i first started programming that i wanted to do this myself, and i cannot remember where it came from or who wrote it, so i cannot credit them unfortunately, but here is the source;
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
/*Linux users will need to add -ldl to the Makefile to compile
*this example.
*/
Display *dis;
Window win;
XEvent report;
GC green_gc;
XColor green_col;
Colormap colormap;
/*
Try changing the green[] = below to a different color.
The color can also be from /usr/X11R6/lib/X11/rgb.txt, such as RoyalBlue4.
A # (number sign) is only needed when using hexadecimal colors.
*/
char green[] = "#00FF00";
int main() {
dis = XOpenDisplay(NULL);
win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 500, 500, 0, BlackPixel (dis, 0), BlackPixel(dis, 0));
XMapWindow(dis, win);
colormap = DefaultColormap(dis, 0);
green_gc = XCreateGC(dis, win, 0, 0);
XParseColor(dis, colormap, green, &green_col);
XAllocColor(dis, colormap, &green_col);
XSetForeground(dis, green_gc, green_col.pixel);
XSelectInput(dis, win, ExposureMask | KeyPressMask | ButtonPressMask);
XDrawRectangle(dis, win, green_gc, 1, 1, 497, 497);
XDrawRectangle(dis, win, green_gc, 50, 50, 398, 398);
XFlush(dis);
while (1) {
XNextEvent(dis, &report);
switch (report.type) {
case Expose:
fprintf(stdout, "I have been exposed.\n");
XDrawRectangle(dis, win, green_gc, 1, 1, 497, 497);
XDrawRectangle(dis, win, green_gc, 50, 50, 398, 398);
XFlush(dis);
break;
case KeyPress:
/*Close the program if q is pressed.*/
if (XLookupKeysym(&report.xkey, 0) == XK_q) {
exit(0);
}
break;
}
}
return 0;
}
来源:https://stackoverflow.com/questions/21408837/how-to-read-arrow-keys-cheat-code-in-c-programming-when-inputted-from-the-key