sneak/Shared/History.cs
Colin McMillen fb074dc318 History: make backing array readonly
GitOrigin-RevId: 33c1bfb915b4f2fb80c3bb1f4b88ef924a45363d
2020-02-13 14:49:34 -05:00

63 lines
1.7 KiB
C#

using System;
namespace SemiColinGames {
// A History is a queue of fixed length N that records the N most recent items Add()ed to it.
// The mostly-recently-added item is found at index 0; the least-recently-added item is at index
// N-1. Items older than the History's size are automatically dropped. The underlying
// implementation is a fixed-size circular array; insertion and access are O(1).
//
// Example:
// h = new History<int>(3);
// h.Add(2); h.Add(3); h.Add(5);
// Console.WriteLine("{0} {1} {2}", h[0], h[1], h[2]); // 5 3 2
// h.Add(7);
// Console.WriteLine("{0} {1} {2}", h[0], h[1], h[2]); // 7 5 3
// h.Add(11); h.Add(13);
// Console.WriteLine("{0} {1} {2}", h[0], h[1], h[2]); // 13 11 7
class History<T> {
// Backing store for the History's items.
private readonly T[] items;
// Points at the most-recently-inserted item.
private int idx = 0;
public History(int length) {
items = new T[length];
}
public void Add(T item) {
idx++;
if (idx >= items.Length) {
idx -= items.Length;
}
items[idx] = item;
}
public int Length {
get => items.Length;
}
public T this[int age] {
get {
if (age < 0 || age >= items.Length) {
throw new IndexOutOfRangeException();
}
int lookup = idx - age;
if (lookup < 0) {
lookup += items.Length;
}
return items[lookup];
}
}
// This creates and populates a new array. It's O(n) and should probably only be used for tests.
public T[] ToArray() {
T[] result = new T[items.Length];
for (int i = 0; i < items.Length; i++) {
result[i] = this[i];
}
return result;
}
}
}