Можно ли сделать так что бы Console.ReadKey не останавливал цикл?(не ожидал нажатия клавиши)
Мне нужно что бы персонаж двигался по координатам сам, а я нажимая стрелочки определял его направление, пока только смог сделать движение по нажатию(нажал-двинул). Как считывать клавишу только когда ее жмут а не ожидать в каждой итерации цикла? Либо просто узнать что была нажата клавиша и если была нажата нужная клавиша, изменить направление.
static void Main(string[] args)
{
InitialisationCharacters();
char[,] map;
map = MapData("maps//map1.txt");
map[hero.y, hero.x] = hero.name;
DrawMap(map);
while (true) {
Move(map);
DrawMap(map);
if (hero.points == 253)
{
break;
}
}
Console.WriteLine("GOOOD JOB! YOU ARE WINNER!!!");
}
static public void Move(char[,] map)
{
ConsoleKey s = Console.ReadKey(true).Key;
if (s == ConsoleKey.LeftArrow)
{
if(map[hero.y, hero.x-1] != '*')
{
if (map[hero.y, hero.x-1] == '-')
hero.points += 1;
map[hero.y,hero.x]=' ';
hero.x = hero.x - 1;
map[hero.y, hero.x] = hero.name;
}
}
else if (s == ConsoleKey.RightArrow)
{
if (map[hero.y, hero.x + 1] != '*')
{
if (map[hero.y, hero.x + 1] == '-')
hero.points += 1;
map[hero.y, hero.x] = ' ';
hero.x = hero.x + 1;
map[hero.y, hero.x] = hero.name;
}
}
else if(s == ConsoleKey.UpArrow)
{
if (map[hero.y - 1, hero.x] != '*')
{
if (map[hero.y - 1, hero.x] == '-')
hero.points += 1;
map[hero.y, hero.x] = ' ';
hero.y = hero.y - 1;
map[hero.y, hero.x] = hero.name;
}
}
else if (s == ConsoleKey.DownArrow)
{
if (map[hero.y + 1, hero.x] != '*')
{
if (map[hero.y + 1, hero.x] == '-')
hero.points += 1;
map[hero.y, hero.x] = ' ';
hero.y = hero.y + 1;
map[hero.y, hero.x] = hero.name;
}
}
}
Ответы (2 шт):
ConsoleKey s нужно сделать статическим полем. После этого, где-то в Main сделать вот такую фигню:
Task.Run(() =>
{
while (true)
{
s = Console.ReadKey().Key;
}
});
А из Move убрать ConsoleKey s = Console.ReadKey(true).Key;.
Можно сделать аналог на событиях или каким-нибудь другим из множества способов организации конкурентного ввода-вывода.
На всякий случай, поясняю:
- Цикл обработки перемещения больше не ждёт ввод, а смотрит значение переменной.
- Значение переменной меняется из другого потока.
- Другой поток большую часть своего времени стоит в ожидании ввода (по этому рекомендую ещё
asyncсюда добавить) - Другой поток меняет значение переменной когда происходит ввод.
Таким образом персонаж будет продолжать двигаться после единовременного нажатия клавиши.
Спасибо @Alexander Petrov, использовал Console.KeyAvailable для проверки нажата ли кнопка.
Создал переменную key для клавиши, записываю какая именно клавиша была нажата в tmpKey и сверяю нужная ли это кнопка, если да записываю в переменную key и цикл работает с ней.
static void Main(string[] args)
{
InitialisationCharacters();
key = ConsoleKey.LeftArrow;
char[,] map;
map = MapData("maps//map1.txt");
map[hero.y, hero.x] = hero.name;
DrawMap(map);
ConsoleKey tmpKey = ConsoleKey.Enter;
while (true) {
Thread.Sleep(170);
if (Console.KeyAvailable)
{
tmpKey = Console.ReadKey(true).Key;
}
if(tmpKey == ConsoleKey.LeftArrow || tmpKey == ConsoleKey.RightArrow || tmpKey == ConsoleKey.UpArrow || tmpKey == ConsoleKey.DownArrow)
{
key = tmpKey;
}
Move(map,key);
DrawMap(map);
if (hero.points == 253)
{
break;
}
}
Console.WriteLine("GOOOD JOB! YOU ARE WINNER!!!");
}
static public void Move(char[,] map, ConsoleKey key)
{
if (key == ConsoleKey.LeftArrow)
{
if(map[hero.y, hero.x-1] != '*')
{
if (map[hero.y, hero.x-1] == '-')
hero.points += 1;
map[hero.y,hero.x]=' ';
hero.x = hero.x - 1;
map[hero.y, hero.x] = hero.name;
}
}
else if (key == ConsoleKey.RightArrow)
{
if (map[hero.y, hero.x + 1] != '*')
{
if (map[hero.y, hero.x + 1] == '-')
hero.points += 1;
map[hero.y, hero.x] = ' ';
hero.x = hero.x + 1;
map[hero.y, hero.x] = hero.name;
}
}
else if(key == ConsoleKey.UpArrow)
{
if (map[hero.y - 1, hero.x] != '*')
{
if (map[hero.y - 1, hero.x] == '-')
hero.points += 1;
map[hero.y, hero.x] = ' ';
hero.y = hero.y - 1;
map[hero.y, hero.x] = hero.name;
}
}
else if (key == ConsoleKey.DownArrow)
{
if (map[hero.y + 1, hero.x] != '*')
{
if (map[hero.y + 1, hero.x] == '-')
hero.points += 1;
map[hero.y, hero.x] = ' ';
hero.y = hero.y + 1;
map[hero.y, hero.x] = hero.name;
}
}
}