试图在C#中使用WinForm制作一个简单的杀死细菌的游戏,但是细菌(我暂时使用Panel
)似乎并不是随机移动的。
具体来说,我遇到的问题是,细菌试图向左上角移动并仅在那附近移动。理想情况下,细菌需要均匀地在矩形范围内移动,但是我不确定如何实现。 查看下面的 gif 文件。
您会看到红色的Panel
仅在左上角左右移动。如何使它均匀且随机地移动到任何地方?
这是我的代码:
private Panel _pnlBacteria; //Panel representing a piece of bacteria
private Random r = new Random(); //For randomly-generated values
private int _prevX; //Stores the previous X location
private int _prevY; //Stores the previous Y location
public Form1()
{
InitializeComponent();
_pnlBacteria = new Panel();
/* Get more property assignments to this._pnlBacteria (omitted) */
//Bacteria's start position is also randomly selected
_prevX = r.Next(50, 300);
_prevY = r.Next(50, 500);
}
//Timer runs every 100 seconds changing the location of the bacteria
private void TmrMoveBacteria_Tick(object sender, EventArgs e)
{
int x, y;
//Get random values for X and Y based on where the bacteria was previously
//and move randomly within ±10 range. Also it cannot go off the screen.
do
{
x = r.Next(_prevX - 10, _prevX + 10);
y = r.Next(_prevY - 10, _prevY + 10);
}
while ((y <= 0) || (y >= 500) || (x <= 0) || (x >= 300));
//Save the new location to be used in the next Tick round as previous values
_prevX = x;
_prevY = y;
//Apply the actual location change to the bacteria panel
_pnlBacteria.Top = y;
_pnlBacteria.Left = x;
}
我尝试将+10更改为+12,保持原样为-10,但现在这仅使细菌仅移动到右下角。我很茫然。 谁能帮忙吗?
答案 0 :(得分:22)
如果您阅读Random.next(int,int)的文档,您会发现下限是包含性的,上限是排他性的,这就是-10和+11起作用的原因。
答案 1 :(得分:13)
解决此问题的方法略有不同,可能是选择随机的方向和随机的距离沿该方向行驶。如果我们在改变方向之前增加细菌可以传播的最大距离,这将允许在表单上进行更多的移动。
我们还可以“加权”距离的随机性,以便更频繁地选择较短的距离。这将增加运动方式的多样性和随机性,同时仍允许一些长距离的冲刺到另一个位置。
这里是一个示例,您可以将其复制/粘贴到实现此想法的新表单项目中。您可以使用maxDistance
(更改方向之前允许的最远距离)和stepDistance
(Timer
的每次迭代所经过的距离)的设置进行播放。较小的stepDistance
将使运动更平稳,但速度更慢。我把它做的很小,所以我也减小了Interval
的{{1}}属性以加快速度。
您会注意到,我还添加了一种方法来验证方向是否有效,从而使细菌不会从屏幕上流下。我创建了一个Timer
来表示方向,这使检查特定方向上的运动变得容易(即,如果枚举值包含“北”并且我们离顶部太近,那么它是无效方向-涵盖“北”,“西北”和“东北”方向。
编辑:我将“加权距离”列表的创建移至构造函数,并对其进行了修改,以选择指数级减少的项目,而不是线性减少的项目。
希望这是有道理的:
enum
答案 2 :(得分:1)
r.Next
的左和右参数分别为包含式和排除式。
x = r.Next(_prevX - 10, _prevX + 10);
y = r.Next(_prevY - 10, _prevY + 10);
因此,此代码的概率空间是(_prevX,_prevY)
中心左上方19x19平方英寸。这意味着更可能向左上方移动。
如果我们在右边使用11s,则概率空间是一个以(_prevX,_prevY)
为中心的20x20正方形。细菌将移动得更均匀。其在概率平方内的平均位移为零,因此没有一个偏向的方向。但是对角线方向将是有利的,因为对角线位移平均是最大的。根据情况,这可能重要,也可能不重要。
如果我们使用半径和方向as explained by Rufus L,则可以生成更“自然”的圆形概率空间。这就是为什么它是首选方法。
答案 3 :(得分:0)
您应该使用panel.height的大小-square.height的大小与长度相同,而不是常量,如果屏幕尺寸更改,您的游戏仍然可以使用
return;
答案 4 :(得分:0)
问题在于您正在前后移动对象,因为范围是prev-+ 10;
x = r.Next(_prevX - 10, _prevX + 10);
y = r.Next(_prevY - 10, _prevY + 10);
您应该为yval和xval添加一个方向标记,并以一定的概率p(小于1/2)对其进行设置,当该标记处于打开状态时向右/向上移动,当其关闭时向左/向下移动,
if (forwardx){
x = r.Next(_prevX , _prevX + 10);
}
else {
x = r.Next(_prevX - 10, _prevX );
}
if (forwardy){
y = r.Next(_prevY , _prevY + 10);
}
else{
y = r.Next(_prevY - 10 , _prevY );
}
forwardx = r.Next(10) == 1; //p = 0.1
forwardy = r.Next(10) == 1;
祝你好运!