我想要做的是在控制台应用程序中编写俄罗斯方块游戏。 这是我的问题:我有两个叫做ListenToKeyEvents和DropTetramino的函数如何调用两个任务来执行块的下降,如果用户的输入在调用DropTetramino之前对输入作出反应?
以下是我迄今为止所做的尝试:
Thread.CurrentThread.Name = "Main";
Task taskA = new Task(() => ListenToKeyEvents());
Task taskB = new Task(() => DropTetramino());
// Start the task.
taskA.Start();
Thread.Sleep(1000);
taskB.Start();
// Output a message from the calling thread.
Console.WriteLine("Hello from thread '{0}'.",
Thread.CurrentThread.Name);
taskA.Wait();
taskB.Wait();
和
private static void ListenToKeyEvents()
{
ConsoleKeyInfo x = new ConsoleKeyInfo();
while (!Console.KeyAvailable && x.Key != ConsoleKey.Escape)
{
x = Console.ReadKey(true);
if (x.Key == ConsoleKey.UpArrow)
{
Blockrotieren();
}
if (x.Key == ConsoleKey.DownArrow)
{
}
if (x.Key == ConsoleKey.LeftArrow)
{
}
if (x.Key == ConsoleKey.RightArrow)
{
}
if (x.Key == ConsoleKey.Spacebar)
{
}
}
}
和
private static void DropTetramino()
{
List<char> belegt = new List<char> ();
for (int i = 0; i < 21; i++)
{
char[] z = feld[i].ToCharArray();
for(int j = 0; j < 12; j++)
{
belegt.Add(z[j]);
}
}
int[] x = new int[4];
int[] y = new int[4];
int[] x1 = new int[173];
int[] y1 = new int[173];
int countrows = 0;
int sum = 0;
int s = 0;
int s1 = 0;
foreach (char i in belegt)
{
if (s >= 4)
{
//break;
//alle übrigen nicht fallenden Blöcke
if ((sum % 12) == 0 && sum != 0)
countrows++;
if (i == 'ö')
{
x1[s1] = sum % 12;
y1[s1] = countrows;
s1++;
s++;
}
if (i == '*' && ((sum % 12) != 0))
{
x1[s1] = sum % 12;
y1[s1] = countrows;
s1++;
s++;
}
sum += 1;
}
if ((sum % 12) == 0 && sum != 0)
countrows++;
if (i == 'ö')
{
x[s] = sum % 12;
y[s] = countrows;
Console.WriteLine("x {0} y {1}", x[s], y[s]);
s++;
}
sum += 1;
}
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if ((i - j) > -1 && (i - j) < 4)
{
if (y[i] > y[i - j] && x[i] == x[i - j])
{
x[i - j] = -1;
y[i - j] = -1;
}
if (y[i] < y[i - j] && x[i] == x[i - j])
{
x[i] = -1;
y[i] = -1;
}
}
}
}
for (int i = 0; i < 4; i++)
{
Console.WriteLine("x rel {0} y rel {1}", x[i], y[i]);
}
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < x1.Length; j++)
{
if ((y[i] != -1 && (y[i] + 1) == y1[j]) && x[i] == x1[j])
{
return;
}
}
}
Console.Clear();
Blockrotieren(xyPos);
}
也许这不是最好的代码,但这两个功能可以完成他们的工作,但只有一次,我不知道如何反复调用它们。
答案 0 :(得分:0)
我认为您可以通过了解Thread Signaling来解决您的问题。 这是一个定制的控制台应用程序示例。实际上并不是一个好的现实场景,但线程信令的使用就在那里。
using System;
using System.Threading;
class Program
{
static void Main()
{
bool isCompleted = false;
int diceRollResult = 0;
// AutoResetEvent is one type of the WaitHandle that you can use for signaling purpose.
AutoResetEvent waitHandle = new AutoResetEvent(false);
Thread thread = new Thread(delegate() {
Random random = new Random();
int numberOfTimesToLoop = random.Next(1, 10);
for (int i = 0; i < numberOfTimesToLoop - 1; i++) {
diceRollResult = random.Next(1, 6);
// Signal the waiting thread so that it knows the result is ready.
waitHandle.Set();
// Sleep so that the waiting thread have enough time to get the result properly - no race condition.
Thread.Sleep(1000);
}
diceRollResult = random.Next(1, 6);
isCompleted = true;
// Signal the waiting thread so that it knows the result is ready.
waitHandle.Set();
});
thread.Start();
while (!isCompleted) {
// Wait for signal from the dice rolling thread.
waitHandle.WaitOne();
Console.WriteLine("Dice roll result: {0}", diceRollResult);
}
Console.Write("Dice roll completed. Press any key to quit...");
Console.ReadKey(true);
}
}
答案 1 :(得分:0)
您可以做的一件事是您可以从任务中同步调用ListenToKeyEvents()
函数让它工作一段时间并调用DropTetramino()
而不管执行结果如何。但要做到这一点,你需要限制玩家做出反应的时间:
private static void ListenToKeyEvents()
{
int timeToReact = 1000; // your time for user to react in ms
ConsoleKeyInfo x = new ConsoleKeyInfo();
Stopwatch s = new Stopwatch();
s.Start();
while (s.ElapsedMilliseconds < timeToReact && !Console.KeyAvailable && x.Key != ConsoleKey.Escape)
{
// ..... your code
}
s.Stop();
}
Task taskA = new Task(() =>
{
// Whether or not user pressed arrows
// ListenToKeyEvents finishes executing
// DropTetraMino is invoked and it is repeated
while(gameIsOn)
{
ListenToKeyEvents();
DropTetramino();
}
});
// Start the task.
taskA.Start();
taskA.Wait();