所以我开始学习C#(实际上这是我的第3天),我正在向左和向右戳。
所以我使用的是Console
,我创建了我的第一个非常简单的类
using System.Timers;
public class Star
{
private int x, y;
public Star(int fx, int fy)
{
Create(fx, fy);
Move();
}
private void Create(int fx, int fy)
{
this.x = fx;
this.y = fy;
Console.SetCursorPosition(this.x, this.y);
Console.Write("*");
}
private void Move()
{
Timer aTimer = new Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 500;
aTimer.AutoReset = false;
aTimer.Start();
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.SetCursorPosition(this.x, this.y);
Console.Write(" ");
}
}
}
我有一个主程序循环,它不停地等待用户输入,它有不同的状态。
while (true)
{
if (Mode == 0)
{
Console.SetCursorPosition(tX, tY);
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("[ " + System.DateTime.Now + " ]");
Cursor(Selection, OldSelection);
}
if (Mode == 2)
{
Random r = new Random();
System.Threading.Thread.Sleep(500);
for (int i = 0; i< 10; i++)
Star myStar = new Star(r.Next(nScreenWidth), r.Next(nScreenHeight));
}
if (Console.KeyAvailable)
{
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
if (Mode == 0)
{
switch (keyInfo.Key)
{
case ConsoleKey.DownArrow:
OldSelection = Selection;
if (Selection == 4) Selection = 0;
else Selection++;
break;
case ConsoleKey.UpArrow:
OldSelection = Selection;
if (Selection == 0) Selection = 4;
else Selection--;
break;
case ConsoleKey.Enter:
if (Selection == 0)
{
Console.Clear();
Mode = 1;
}
if (Selection == 1)
{
Console.Clear();
Mode = 2;
}
if (Selection == 4) return;
break;
}
}
if (keyInfo.Key == ConsoleKey.Escape)
{
Console.Clear();
MainMenu();
Mode = 0;
}
}
}
我的问题是,当我启动星星(模式2)时,它会在随机位置显示星星,但是如果我退出此状态,物体不会立即死亡,它们的计时器仍然在执行,并且它们正在定位光标 - 位置,并拧紧主菜单。我可能这里有点可怕,但我不知道是什么。
此致 罗伯特
最终工作示例
在IRC上查了一下之后,我被告知最好使用一个Timer,因为我已经有了一个主循环。我改变了我的代码。
首先是班级
public class Star : IDisposable
{
public static int instances = 0;
public Star(int fx, int fy)
{
Create(fx, fy);
Animate();
}
int x, y, animpos;
private void Create(int fx, int fy)
{
this.x = fx;
this.y = fy;
this.animpos = 0;
instances++;
}
public void Animate()
{
Console.SetCursorPosition(this.x, this.y);
switch (animpos)
{
case 0:
{
Console.Write("+");
}
break;
case 1:
{
Console.Write("*");
}
break;
case 2:
{
Console.Write(".");
}
break;
}
animpos++;
if (animpos == 3) { animpos = 0; }
}
public void Dispose()
{
instances--;
}
}
然后是程序中的主循环,只有相关部分:
if (Mode == 2)
{
System.Threading.Thread.Sleep(200);
if(Star.instances < 30)
{
Star myStar = new Star(r.Next(nScreenWidth-1), r.Next(nScreenHeight-1));
stars.Add(myStar);
}
if (stars.Count != 0)
{
foreach(var star in stars)
{
star.Animate();
}
}
Console.SetCursorPosition(0, nScreenHeight-1);
Console.Write("NUMBER OF STARS ON SCREEN : " + Star.instances);
}
我把Dispose留在那里,只是为了记住这一点,将来我希望能生成更复杂的代码。但我想这并不是真的需要它。
再次感谢你!
答案 0 :(得分:1)
您尝试每500毫秒创建10个Star
类的实例,但您没有维护对这些对象的引用。
您需要将它们添加到集合中,例如列表...
static List<Star> stars = new List<Star>();
for (int i = 0; i< 10; i++)
{
Star myStar = new Star(r.Next(nScreenWidth), r.Next(nScreenHeight));
stars.Add(myStar);
}
然后,当您退出主菜单时,您需要明确处理这些实例,以确保他们的计时器不再触发。
在C#中,通常的做法是在您希望能够明确处理的类中实现IDisposable接口...
public class Star : IDisposable
{
...
public void Dispose()
{
if (aTimer != null)
{
aTimer.Dispose();
aTimer = null;
}
}
...
}
然后,您可以通过调用处理它们来处置您的Star实例...
if (keyInfo.Key == ConsoleKey.Escape)
{
foreach (var star in stars)
star.Dispose();
Console.Clear();
MainMenu();
Mode = 0;
}