【问题标题】:(How to read arrow keys) Cheat code in C programming (when inputted from the keyboard)(如何阅读箭头键) C 编程中的作弊代码(从键盘输入时)
【发布时间】:2014-01-28 14:50:58
【问题描述】:

我正在用 C 语言制作游戏,当用户输入 Konami 代码(作弊码)时,程序应该会打印出正确的答案。 (编辑#3)发现我的程序在输入时不会“读取”箭头键,我该如何做到这一点?请。看我下面的评论

这是我更新的代码(编辑 #2): //试试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!");

}

现在,我的问题是它总是打印 Lol!即使我正确输入了作弊码。 . .

注意:这是我的编程入门课程(我也是第一次学习 c)。到目前为止所涵盖的课程是基础知识、循环、数组和字符串(还没有函数,但我现在明白了,没有结构和进一步的请。谢谢 :)

【问题讨论】:

  • 你正在用 C 实现 Contra?
  • 在 C 中,您不能将字符串与 foo == bar 进行比较。您需要使用strcmp()
  • 哦,对了。但我主要关心的是如何使用箭头键初始化我的作弊数组,以将其与用户的输入进行比较。
  • @user3203014,所以你的问题与“作弊”或类似的东西无关?您根本不知道如何将箭头键放入数组中?然后,请相应地编辑您的问题(和标题)。
  • @user3203014:如果你刚刚开始 C,那么坦率地说,他们都不会。我建议只使用一个作弊词,而忘记箭头键,但如果你真的必须尝试,并且你都不熟悉,那么 ncurses 可能比 win32 的控制台 API 稍微简单一些。

标签: c arrow-keys


【解决方案1】:

my question is how do i check it coming from the user

我听说您想知道用户何时按下箭头键?我必须在 C++ 中执行此操作,结果证明这是一次非常有启发性的体验,因此尽管您使用的是 C 而不是 C++,但我仍然会分享我记得的内容。

Arrow keys 采用字节序列而不是一个 AND 通常在硬件级别实现!

尽管您使用的任何操作系统都应该有支持(再见可移植性),但您需要寻找的术语是key codes,在windows 他们称它们为Virtual-Key Codes

Windows我已经学会了用win32api编程。

我可以轻松地向您展示 Windows 的 key codes(我将从该链接粘贴它们)但它们对您没有好处,除非您想提交 Windows 事件驱动类型程序(也许您已经是?) ,这些代码是从您程序中的key 事件中获取的,而不是ascii-codes,我会尽可能假设特定于windows

VK_LEFT
0x25
LEFT ARROW key
VK_UP
0x26
UP ARROW key
VK_RIGHT
0x27
RIGHT ARROW key
VK_DOWN
0x28

在 linux 中,我仍然需要处理事件,这次使用 X11,哦,我在 X11 上的乐趣!这里的键码称为XK_[key],即XK_left

这些键码在标题&lt;X11/keysymdef.h&gt; - Xlib programming manual中定义

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 */

希望这可以让您走上正确的道路,每当我需要 arrow keys 时,我现在只需使用 wasd


编辑:这是 Windows 版本,我将它从我制作的 C++ 游戏浓缩到这个 C 程序中,它有很多代码,任何看起来不应该存在的东西可能都不应该存在,但它可以编译并读取箭头键,因此您需要的一切至少在此源中。

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) 这是我使用的示例程序,实际上当我第一次开始编程时,我想自己做这个,我不记得它来自哪里或是谁写的,所以我不能相信他们不幸的是,但这是来源;

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

【讨论】:

  • 似乎我的 MinGW 编译器没有 因为它说“没有这样的文件或目录编译终止” 有效,但我遇到了问题了解如何使用密钥代码。我是否让它们像这样 - #define VK_LEFT 0x25 // 左箭头键?那么如何将它们作为字符串/数组将它们与猜测输入进行比较?请您进一步启发我。谢谢
  • 哦,对不起,X11 用于 linux,虽然你可以为其他平台下载它,例如 windows 我认为,我认为 X11 可能需要一些标志编译时!使用 windows,我可以使用 win32api 将 C 程序编辑到我的答案中(请记住,我不是 windows pro,我可能做错了,但至少它读取箭头键对吗?),我会有看看我在 Linux 中使用的示例程序,以便为您整理X11 的想法。但我认为如果你刚刚开始,你不应该为此烦恼,这些 api 使用一种语言中可用的一切。
  • X11 标头用于 X11 程序。它们对任何操作系统上的控制台程序都没有任何作用。
  • 您回复的是我回答的哪一部分?我不确定您要告诉我什么,我不知道您所说的“X11 标头用于 X11 程序”或“它们对控制台程序没有任何作用”是什么意思,您需要对此进行扩展,我一开始对 X11 不太了解,很久以前我接触过它,但是当我接触到它时,我做了一个糟糕的控制台绘图程序,X11 标题似乎在我的程序??我不是想争论,我只是有点困惑。
  • @n.m 哦,等等,如果它打开一个新窗口,它不是控制台程序吗?那是我忽略的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-27
相关资源
最近更新 更多