Sliding window (shift) for an array

512 views Asked by At

I've got a low-level keyboard hook which currently allows me to control a media player from inside any application, including games.

It works by looking at the specific keystroke captured.

I'd like to extend it to look for combinations of keys. I can hardcode some logic but I feel there must be a more logical way.

Really, I'm looking for something like a shift register...

eg as I type "BlahPlay", I'd like a structure which can be used like this...

[_,_,_,_]
[_,_,_,B]
[_,_,B,l]
[_,B,l,a]
[B,l,a,h]
[l,a,h,P]
[a,h,P,l]
[h,P,l,a]
[P,l,a,y] <-- detect "Play"

Short of looping and shifting the items in an array, what's the correct way to do this?

The best I can think of right now is ...

Private Register(4) As Char
Private Position = 0 

Sub Add(Character as Char)
    Register(Position) = Character
    Position = (Position + 1) Mod Register.Length
End Sub

Function Get() as String
    Dim Ret As New StringBuilder
    For i = Position To Position + Register.Length
        Ret.Append(Register(i Mod Register.Length)
    Next
    Return Ret.ToString
End Function
1

There are 1 answers

1
p.s.w.g On

Instead of shifting the items in the buffer, you could create standard array and just inserting each item in the next position, looping around as necessary. Consider the following code:

var buffSize = 4;
var position = 0;
var buffer = new char[buffSize];

Now you simply insert every new character at position and set position = (position + 1) % buffSize every time a new key is entered. Suppose you typed abcPlay, the buffer would be:

[_,_,_,_] position = 0
[a,_,_,_] position = 1
[a,b,_,_] position = 2
[a,b,c,_] position = 3
[a,b,c,P] position = 0
[l,b,c,P] position = 1
[l,a,c,P] position = 2
[l,a,y,P] position = 3

This means that instead of simply reading each char out from the begin reading at position. For example, if you're testing to see if the buffer contains Play, you'd have to do something like this:

var test = new char[] { 'P', 'l', 'a', 'y' };
int p = (position + buffSize - test.Length) % buffSize;
bool success = true;
for(int i = 0; i < test.Length; i++)
{
    if (buffer[p] != test[i])
    {
        success = false;
        break;
    }

    p = (p + 1) % buffSize;
}

Edit You edited your question since I began writing this answer. It appears that you've already developed a solution pretty close to this. I'd still recommend going with something like this. It will be more efficient than shifting each item in the array on every insert.