Reputation: 746
So sorry for this vague question... its doing my head in...
Basically just a test project, use the [+] key to add a bunch of values into the List.... The arrow keys need to go up and down the List values...
When a new value is added to the list the "historySelected" is reset, so that the 'Up Arrow'.. always selects the last item added in the List first, and then if you keep pressing it, it goes back through the List values. At anytime if the 'Down Arrow' key is pressed it needs to go back to the previous value in the List of values. At no point should a Up Arrow key followed by a Down Arrow key show the same List value, and vice versa..
The behavior I'm looking for is much like a developer console with a command history, where Up arrow goes further back in history, and Down arrow the opposite.
Again apologies for the code, its been through so many test changes, currently this works going Up arrow to the start of the List value, and then using the Down arrow to go all the back to the highest List index... but the problem is if you go half way through the List (or inbetween anyway), and switch from Up arrow.. to Down arrow.. the values increment/decrement don't act accordingly... I can't seem to get the right codelogic for it.
Any help or suggestions thanks.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ArrowKeys {
class Program {
//public static List<string> cmdHistory = new List<string>() { "1", "2", "3", "4", "5" };
public static List<string> cmdHistory = new List<string>();
public static int cmdHistoryCount = 0;
public static int historySelected = 0;
public static int num = 0;
public static string current = "";
public enum UpDown {
reset,
up,
down
};
public static UpDown LastUpDown;
static void Main(string[] args) {
bool running = true;
while (running) {
ConsoleKeyInfo kb = Console.ReadKey();
switch (kb.Key) {
case ConsoleKey.Escape:
Console.WriteLine("Exit");
running = false;
return;
case ConsoleKey.Add:
cmdHistory.Add(num.ToString());
cmdHistoryCount++;
historySelected= cmdHistoryCount;
LastUpDown = UpDown.reset;
Console.WriteLine(string.Join(" ", cmdHistory.Cast<string>().ToArray()));
num++;
break;
case ConsoleKey.UpArrow:
UpArrow();
LastUpDown = UpDown.up;
Console.WriteLine("UpArrow pressed");
Console.WriteLine(current);
break;
case ConsoleKey.DownArrow:
DownArrow();
LastUpDown = UpDown.down;
Console.WriteLine("DownArrow pressed");
Console.WriteLine(current);
break;
}
}
}
public static int Clamp(int value, int min, int max) {
return (value < min) ? min : (value > max) ? max : value;
}
public static void UpArrow() {
if (cmdHistoryCount != 0) {
if (LastUpDown == UpDown.down) {
if (historySelected - 1 == 0) {
return;
}
}
current = cmdHistory[historySelected - 1];
if (historySelected - 1 == 0) {
return;
}
historySelected--;
}
}
public static void DownArrow() {
if (cmdHistoryCount != 0) {
if (LastUpDown == UpDown.up) {
if (historySelected + 1 > cmdHistoryCount) {
return;
}
}
current = cmdHistory[historySelected - 1];
if (historySelected + 1 > cmdHistoryCount) {
return;
}
historySelected++;
}
}
}
}
Upvotes: 0
Views: 4109
Reputation: 1095
If I'm understanding what you're looking for correctly, a pair of dueling stacks might work for your case. They're going to give you the FILO/LIFO style item access you're looking for. Drop the List and do something like:
var UpStack = new Stack<string>();
var DownStack = new Stack<string>();
On "new item"
UpStack.Push(newItem);
On "Up"
DownStack.Push(UpStack.Pop());
On "Down"
UpStack.Push(DownStack.Pop());
If you wanted a "buffer" item that isn't in either of the stacks, that's easy enough to do by just Popping into the buffer item. It's a little more management, because you'd have to push it onto one stack, then pop the other each time, but it's whatever. There's also the Peek() method, which gets the item on top of a Stack without Popping it, so you use that for your display item, as well.
Upvotes: 0
Reputation: 26223
It sounds like you simply need to stop your index going out of range. It's not clear what the existing code was intended to do, but your clarification seems to imply it's not necessary. Try this:
public static void UpArrow()
{
historySelected = Math.Max(0, historySelected - 1);
current = cmdHistory[historySelected];
}
public static void DownArrow()
{
var maxIndex = cmdHistory.Count - 1;
historySelected = Math.Min(maxIndex, historySelected + 1);
current = cmdHistory[historySelected];
}
Upvotes: 0