如何检查一系列击键

时间:2011-08-27 20:06:29

标签: java keyboard io

我正在制作一款游戏,并希望实施类似Konami代码的作弊码。

但是我该如何检查按键序列?

我希望它能够正常工作,以便玩家只需键入代码即可触发。

提前致谢!

5 个答案:

答案 0 :(得分:5)

修改 有关始终有效的代码,请参阅我的其他帖子。如果代码与自身重叠,则以下代码不会检测到代码(例如:“UP,UP,UP,DOWN,DOWN,LEFT,RIGHT,LEFT,RIGHT,B”不起作用)

感谢 Gevorg 指出这一点。


如果只是如何识别你所关注的序列(我假设你知道如何从键盘输入)那么你可以得到如下内容。

int[] sequence = {UP, UP, DOWN, DOWN, LEFT, RIGHT, LEFT, RIGHT, B};
int currentButton = 0;

boolean checkKonami(int keyPressed) {
    //Key sequence pressed is correct thus far
    if(keyPressed == sequence[currentButton]) {
        currentButton++;

        //return true when last button is pressed
        if(currentButton == sequence.length) {

            //Important! Next call to checkKonami()
            //would result in ArrayIndexOutOfBoundsException otherwise
            currentButton = 0;

            return true;
        }
    }
    else {
        //Reset currentButton
        currentButton = 0;
    }

    return false;
}

只要按下按键,通过已按下的键,即可调用此功能。当然,在适当的时候修改类型。

答案 1 :(得分:5)

下面是一个检查Konami代码的类,包括“ UP ,UP,UP,DOWN等”的情况。

这适用于任何给定序列。

import java.util.Map;
import java.util.TreeMap;

public class Konami {

    static private int[] code = 
        {UP, UP, DOWN, DOWN, LEFT, RIGHT, LEFT, RIGHT, B};
    static private Map<Integer, Integer>[] graph;
    static private int currentNode = 0;

    public static void main(String args[]) {
        //Create graph
        graph = generateSequenceMap(code);

        //Call checkKonami(key) whenever a key is pressed
    }


    static public boolean checkKonami(int keyPressed) {
        Integer nextNode = graph[currentNode].get(keyPressed);

        //Set currentNode to nextNode or to 0 if no matching sub-sequence exists
        currentNode = (nextNode==null ? 0 : nextNode);

        return currentNode == code.length-1;
    }


    static private Map<Integer, Integer>[] generateSequenceMap(int[] sequence) {

        //Create map
        Map<Integer, Integer>[] graph = new Map[sequence.length];
        for(int i=0 ; i<sequence.length ; i++) {
            graph[i] = new TreeMap<Integer,Integer>();
        }

        //i is delta
        for(int i=0 ; i<sequence.length ; i++) {
            loop: for(int j=i ; j<sequence.length-1 ; j++) {
            if(sequence[j-i] == sequence[j]) {
                System.out.println("If at Node "+j+" you give me seq["+(j-i+1) 
                        + "] OR " + (sequence[j-i+1]) + " , goto Node " + (j-i+1));

                //Ensure that the longest possible sub-sequence is recognized
                Integer value = graph[j].get(sequence[j-i+1]);
                if(value == null || value < j-i+1)
                    graph[j].put(sequence[j-i+1], j-i+1);
            }
            else
                break loop;
            }
        }
        return graph;
    }
}

答案 2 :(得分:3)

我确定你现在已经过了这个项目,但我刚刚把它实现到我的一个任务中,并希望让其他人找到它。此解决方案将最后n次击键(此处定义为10)记录到循环数组中,并在匹配我们的代码时返回true。作为方法的一部分,您可以轻松地传入不同的长度和代码(但是这种实现并不需要它)。我用^ ^ v v&lt; &GT; &LT; &GT; b a。

public class Code {
private static int[] history = new int[10];
private static int front = 0;
private static int size = 0;

// Here is the Code they must enter (ascii vals for konami).
private static int[] code = {38, 38, 40, 40, 37, 39, 37, 39, 66, 65};

// Static class. No constructor.
private Code(){}

// Adds key-press into history buffer. If code is matched, return true.
public static boolean add(int e){

    // Write the value into our key history.
    history[(front + size) % 10] = e;

    // Stop growing at length 10 and overwrite the oldest value instead.
    if (size < 10){
        size++;
    } else {
        front = front + 1 % 10;
    }

    // Compare our history (from the current front) to the code (from 0)
    for(int i = front; i < front + size; i++){
        if (history[i % 10] != code[i-front]){
            // Any 1 mismatch will abort
            return false;
        }
    }
    // Make sure we've logged enough keystrokes so it doesn't fire off
    // if your first key press matches the code.
    if (size < 10){
        return false;
    }
    return true;
}

享受! :d

答案 3 :(得分:0)

我不知道你的需求是什么。您是尝试使用System.inSystem.out制作游戏还是尝试制作完整的可视化GUI?

在此期间,请参阅界面java.awt.event.KeyListener。 (Oracle Documentation)另请参阅Oracle's Tutorial

根据个人经验,下面的代码近似于您的需要。

import java.awt.event.*; //Specifically KeyListener and KeyEvent
import java.util.ArrayList;

public class Test implements KeyListener {

    private final int[] cheatCode = {38, 38, 40, 40, 37, 39, 37, 39, 66, 65, 83, 84, 65, 82, 84} //assuming user types out "start"
    private final ArrayList<Integer> KONAMI_CODE = createCheatCode(cheatCode);
    private ArrayList<Integer> typedKeys = new ArrayList<Integer>();
    public Test() {
        //constructor goes here, if necessary
    }

    public /*static*/ ArrayList<Integer> createCheatCode(int[] code) { //uses Key Codes
        ArrayList<Integer> temp = new ArrayList<Integer>();
        for (int i = 0; i < code.length; i++)
            temp.add(new Integer(code[i]));
        return temp;
    }

// Warning: MUST implement ALL KeyListener methods, or compiler will complain

    public /*static*/ void keyPressed(KeyEvent e) {}

    public /*static*/ void keyReleased(KeyEvent e) {
        typedKeys.add(new Integer(e.getKeyCode()));
    }

    public /*static*/ void keyTyped(KeyEvent e) {}

    public /*static*/ boolean cheatEntered() {
        int cheatLen = KONAMI_CODE.size(); // or length, depending on what you use
        int index = typedKeys.size() - cheatLen;
        if (index < 0)
            return false;
        return typedKeys.get(index, typedKeys.size()).equals(KONAMI_CODE);
    }
}

使用跑步方法时,只需指定

即可
if (test.cheatEntered()) {
    // do something
}

如果您想要面向对象的编程,可以删除/*static*/;否则,如果要使用静态方法运行它,请删除/**/对。

答案 4 :(得分:0)

查看状态模式可能会很有趣,但您可以尝试下面的技巧,因为这是一个简单的案例:

  1. 将要识别的序列放在String secretCode
  2. 创建一个StringBuilder userInput,用于按住用户按下的键
  3. 每次用户按下某个键时,都会将其附加到userInput
  4. userInput中附加的每个密钥后,检查更新的userInput是否包含secretCode以及以下内容:userInput.indexOf(secretCode)>-1
  5. 您可能希望从现在开始清空userInput,然后根据时间或在识别序列后清空。