Как проверить последовательность нажатий клавиш - PullRequest
9 голосов
/ 28 августа 2011

Я создаю игру и хочу использовать чит-коды, такие как код Konami.

Но как мне проверить эту последовательность нажатий клавиш?

Я хочу, чтобы она работалаесли игрок просто набирает код, который он сработает.

Заранее спасибо!

Ответы [ 5 ]

5 голосов
/ 29 августа 2011

Ниже приведен класс, который проверяет код 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;
    }
}
5 голосов
/ 28 августа 2011

РЕДАКТИРОВАТЬ: Смотрите мой другой пост для кода, который всегда работает.Следующий код не обнаруживает код, если он перекрывается с самим собой (например: «UP, UP, UP, UP, DOWN, DOWN, LEFT, RIGHT, LEFT, RIGHT, B» не будет работать)

Спасибона Геворг за указание на это.


Если это способ определения только последовательности, которая вас интересует (я предполагаю, что вы знаете, как получить ввод с клавиатуры)тогда вы можете получить что-то, следующее:

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

Вызывайте эту функцию всякий раз, когда нажимается клавиша, передавая нажатую клавишу.Конечно, при необходимости измените типы.

3 голосов
/ 31 марта 2013

Я уверен, что вы уже прошли этот проект, но я просто внедрил его в одно из своих заданий и хотел оставить его для других.Это решение регистрирует последние n нажатий клавиш (определенных здесь как 10) в круговой массив и возвращает true, когда они соответствуют нашему коду.Вы также можете легко передавать различные длины и коды как часть метода (но эта реализация не требовала этого).Я использовал ^ ^ vv <> <> 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

0 голосов
/ 28 августа 2011

Может быть интересно взглянуть на шаблон состояний, но вы можете попробовать трюк ниже, так как это простой случай:

  1. Поместите последовательность, которая будет распознана в String secretCode
  2. Создайте StringBuilder userInput, который будет удерживать нажатые пользователем клавиши
  3. Каждый раз, когда пользователь нажимает клавишу, добавляйте ее к userInput
  4. После каждого ключа, добавляемого в userInput, проверьте, содержит ли обновленный userInput secretCode со следующим: userInput.indexOf(secretCode)>-1

Возможно, вы захотите очистить userInput с этого момента, а затем в зависимости от времени или после распознавания последовательности, например.

0 голосов
/ 28 августа 2011

Я не знаю, каковы ваши потребности.Вы пытаетесь создать игру, используя System.in и System.out, или вы пытаетесь создать полноценный визуальный графический интерфейс?

А пока смотрите интерфейс java.awt.event.KeyListener.( Документация Oracle ) Также см. Руководство Oracle .

. Исходя из личного опыта, приведенный ниже код приблизительно соответствует вашим потребностям.* При использовании метода бегуна просто укажите, что

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

Вы можете удалить /*static*/, если хотите объектно-ориентированное программирование;в противном случае избавьтесь от пар /* и */, если хотите запустить его статическими методами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...