不确定问题是否足够精确,一旦您阅读了我的问题的解释,请纠正我。
控制台应用程序。简单的游戏。 所以我有9个燃油泵,每个都将为车辆提供服务。现在 - 我需要使用计时器加油方法(或者只使用基于主游戏计时器的普通变量)。
我的问题是接近它的最佳方法是什么?要么为每个泵制作单独的方法,要么为每个泵使用一种方法(消除变量等)。
提前谢谢。
答案 0 :(得分:1)
这似乎是一个广泛的问题所以我只想给你一些想法。您已使用OOP标记了该问题。如果您询问“面向对象”的方式,可以使用方法加密来创建类Pump。然后,您将创建一个Pump类的实例(每个泵9次)。如果泵具有不同的属性,如加油时间,您可以将它们作为公共属性。这只是为了给你一个想法:
public class Pump
{
public int RefuellingTimeSeconds { get; set; }
public void Refuel(Vehicle vehicle)
{
//refuelling code here
}
}
然后您可以实例化每个泵:
var firstPump = new Pump { RefuellingTimeSeconds = 120 };
var secondPump = new Pump { RefuellingTimeSeconds = 90 };
以上假设所有泵都有相同的加油程序,只有一些参数可以从外部设置。
另一方面,如果您有不同类型的泵,并且他们共享的只是加油接口,您可以创建具有不同泵实施的泵接口:
public interface IPump
{
void Refuel(Vehicle vehicle)
}
public class SlowRefuelPump
{
public void Refuel(Vehicle vehicle)
{
//slow refuelling
}
}
public class FastRefuelPump
{
public void Refuel(Vehicle vehicle)
{
//fast refuelling
}
}
然后您可以根据需要创建泵并在您的应用程序中使用它们的界面:
var pumps = new List<IPump> { new SlowRefuelPump(), new FastRefuelPump() };
并将它们用作:
pumps[0].Refuel(_vehicle);
pumps[1].Refuel(_vehicle);
一切都取决于你的情景...
答案 1 :(得分:0)
我会创建一个类Pump
,其中包含为Car
实例加油的逻辑。
这些泵实例中的每一个都将在泵送时保持对汽车的参考。 Pump
类可以有一种方法,可以根据游戏循环增加汽车中的燃料。
类似的东西:
public class Pump
{
private int _fuelRate;
public Car ServicingCar { get; set; }
public Pump(int fuelRate = 10)
{
_fuelRate = fuelRate;
}
public void IncreaseFuel()
{
if (ServicingCar == null) return;
ServicingCar.Fuel += _fuelRate;
}
}
然后在你的游戏中初始化你的泵:
var pump1 = new Pump();
var pump2 = new Pump(20); // this one is faster
等...
如果您想为汽车加油,只需指定ServicingCar
财产。
pump1.ServicingCar = car1;
你可以检查另一辆车是否已经加油等等。这将是你要弄明白的任务。
在游戏循环中,您可以为每个泵调用IncreaseFuel
。
这是最好的方法吗?这是非常主观的,很难回答,因为你的问题的细节水平很低。但是,这是一种简单的方法。
答案 2 :(得分:0)
你需要忘记编写代码和编程,但首先要确定要求并将它们放入简单,简单的英语句子中。这将帮助您设想您正在解决的问题,并提出一个更好的心理模型。现在我不知道你的要求,但我会尝试做出假设。例如,以下是编写需求的方法:
根据这些要求,不要过于花哨,使用OO概念,你可以找到名词,那些将成为你的类(还有其他先进的方法,但一开始这非常好)。所有粗体项目都是名词,因此您需要以下课程:
现在让我们专注于Pump
项目。
现在仔细查看措辞:&#34;泵将被占用&#34;,这意味着我们的Pump
类需要一个属性来存储它。 &#34;它将被占用一段时间&#34;,这意味着它还需要一些东西来跟踪时间。 &#34;要启动泵,它需要一辆车&#34;,这意味着我们需要一个&#34;开始&#34;财产,但听起来不对。属性是属性,这听起来像一个动作。因此,&#34;开始&#34;应该是一种方法。
对于物业总是认为&#34;形容词&#34;例如身高,体重等。对于方法总是认为&#34;动词&#34;特别是动作动词,如Start,Stop,Walk等。
<强>设计强>
好的,让我们设计Pump
课程。但在我们这样做之前,让我们澄清一下我们设计的目标。我们的班级设计应该是我们班级的用户永远不会让泵处于不良状态。例如,如果泵被占用,我们不能接受另一辆车。该级别的用户不应该启动泵并为其提供车辆,并且还说泵是免费的。泵需要某种信号来指示它是空闲还是被占用。
好的,足够的理论,现在有些代码:
class Pump
{
public event EventHandler<PumpEventArgs> StatusChanged;
private System.Timers.Timer timer;
private Vehicle vehicle;
public Pump(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentException("The name for the pump is not valid. It cannot be null or empty.");
}
this.Name = name;
this.timer = new System.Timers.Timer();
this.timer.Elapsed += Timer_Elapsed;
this.timer.Interval = 100;
this.timer.AutoReset = true;
}
public string Name { get; private set; }
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// If the pump is not occupied, we do nothing
if (!this.IsOccupied)
{
return;
}
// Looks like the pump was occupied and
// the timer went off so lets make the pump available by setting the
// vehicle at this pump to null
this.Vehicle = null;
}
// Private set so the only way to set this is to call the start method
public Vehicle Vehicle
{
get
{
return this.vehicle;
}
private set
{
this.vehicle = value;
if (value == null)
{
this.IsOccupied = false;
}
else
{
this.IsOccupied = true;
}
// If anyone has subscribed to the pump change event, notify them and send them the status
if (this.StatusChanged != null)
{
this.StatusChanged(this, new PumpEventArgs { Status = this.Status });
}
}
}
// private set so the only way a pump is occupied if start has been called.
// Other classes should not be able to set IsOccupied to false if there is a vehicle at the
// pump.
public bool IsOccupied { get; private set; }
// This is a read-only property. It depends on the IsOccupied property.
public string Status
{
get
{
if (this.IsOccupied)
{
return "Occupied";
}
return "Free";
}
}
public void Start(Vehicle vehicle)
{
// This object should take care of its own rules. If someone calls Start
// and the pump is busy and they call start again, do not allow it.
if (this.IsOccupied)
{
throw new InvalidOperationException("This pump is already occupied.");
}
// Set using property so the property can carry out the other rules
this.Vehicle = vehicle;
// Start the pump timer as well
this.timer.Start();
}
}
如果你注意,这个类没有Console.WriteLine
或其他控制台引用。这个班是独立的。当泵可用或一旦被占用时,由类的用户决定在何处写消息。也许用户想要写入控制台,或者用户想要显示对话框(窗口)或者可能用户想要向真实灯发送信号并将灯变为绿灯等。它还要确保它始终处于良好状态:如果它被占用,它将不会返回&#34; Free&#34 ;状态。此外,它不允许任何其他人将状态设置为免费。
该类还会在泵被占用和空闲时暴露事件。如果班级的用户感兴趣,他们将订阅该活动并做他们需要的任何事情。
所以有Pump
类,这应该给你很多关于如何创建良好封装的好的想法。
这是Vehicle
课,但显然没有完成。
class Vehicle
{
}
以下是Game
类的方法,但您需要更改它并为其添加更多代码。例如,当泵被占用时,您可能需要做一些事情。如果它是免费的,你可能需要别的东西。我只是在控制台上写一条消息。
class Program
{
static void Main(string[] args)
{
while (true)
{
Pump p1 = new Pump("Pump1");
// Lets make sure to subscribe to StatusChanged event before you start the pump
// with a new vehicle.
p1.StatusChanged += StatusChanged;
p1.Start(new Vehicle());
Pump p2 = new Pump("Pump2");
p2.StatusChanged += StatusChanged;
p2.Start(new Vehicle());
//Console.Write("Finished...");
Console.ReadLine();
}
}
// we can use the same handler for all pumps and we can do different things
// depending on who the sender is.
// Or if you prefer, you can have different event handlers
private static void StatusChanged(object sender, PumpEventArgs e)
{
var pump = sender as Pump;
Console.WriteLine("{0} status changed to {1}.", pump.Name, e.Status);
}
}
祝你好运!