visual usar repetir propiedad para numeros numero generar digitos como clase algoritmo aleatorios aleatorio c# winforms

c# - usar - random en visual basic



Los valores aleatorios parecen no ser realmente aleatorios? (5)

Debes usar el tamaño de tu panel. El tamaño de tu cuadrado. La altura de la misma en lugar de las constantes de esta manera si el tamaño de la pantalla cambia, tu juego seguirá funcionando.

_prevX = r.Next(bateriaSize, this.Width-bacteriaSize); //this.Width Gets you the of form _prevY = r.Next(bateriaSize, this.Height-bacteriaSize); //This.Height gets you the height of form

Tratar de hacer un juego simple para matar bacterias usando WinForm en C #, pero la bacteria (por el momento estoy usando el Panel ) no parece moverse al azar.

Específicamente, el problema que tengo es que las bacterias intentan moverse hacia la esquina superior izquierda y moverse solo por allí. Idealmente, las bacterias deben moverse alrededor del rango del rectángulo de manera uniforme, pero no estoy seguro de cómo lograrlo. Mira el archivo gif a continuación.

Como puede ver, el Panel rojo se mueve solo alrededor de la esquina superior izquierda. ¿Cómo puedo hacer que se mueva en todas partes de manera uniforme y aleatoria?

Aquí está mi código:

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; }

Intenté cambiar el +10 al +12, dejando el -10 como está, pero ahora esto solo hizo que las bacterias se movieran solo hacia la esquina inferior derecha. Estoy en una pérdida. Alguien puede ayudarme porfavor?


El problema es que está moviendo el objeto hacia adelante y hacia atrás porque el rango es anterior - + 10;

x = r.Next(_prevX - 10, _prevX + 10); y = r.Next(_prevY - 10, _prevY + 10);

debe agregar un indicador de dirección para yval y xval, establecerlo con cierta probabilidad p (menos de 1/2), cuando el indicador está en marcha a la derecha / arriba, cuando está apagado a la izquierda / abajo,

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;

¡Buena suerte!


Los argumentos de izquierda y derecha de r.Next son inclusivos y exclusivos respectivamente.

x = r.Next(_prevX - 10, _prevX + 10); y = r.Next(_prevY - 10, _prevY + 10);

Así que el espacio de probabilidad de este código es un cuadrado de 19x19 fuera del centro de (_prevX,_prevY) en su parte superior izquierda. Esto significa que el desplazamiento es más probable hacia la parte superior izquierda.

Si usamos 11s a la derecha, entonces el espacio de probabilidad es un cuadrado de 20x20 centrado en (_prevX,_prevY) . Las bacterias se moverán más uniformemente. Su desplazamiento promedio dentro de su cuadrado de probabilidad es cero, por lo que no hay una sola dirección favorecida. Pero las direcciones diagonales serán favorecidas ya que el desplazamiento diagonal es el mayor en promedio . Esto puede o no ser importante dependiendo de la situación.

Si usamos el radio y la dirección como lo explica Rufus L , entonces podemos generar un espacio de probabilidad circular más "natural". Es por eso que es el enfoque preferido.


Si lees la documentación de Random.next (int, int) encontrarás que el límite inferior es inclusivo y el límite superior es exclusivo, por eso funciona -10 y +11.


Una forma ligeramente diferente de abordar esto podría ser elegir una dirección aleatoria y una distancia aleatoria para viajar en esa dirección. Esto permitirá más movimiento sobre la forma si aumentamos la distancia máxima que las bacterias pueden viajar antes de cambiar de dirección.

También podemos "ponderar" la aleatoriedad de la distancia para que las distancias más cortas se elijan con mayor frecuencia. Esto agregará más variedad y aleatoriedad al patrón de movimiento, al mismo tiempo que permitirá algunos sprints largos a otra ubicación.

Este es un ejemplo que puede copiar / pegar en un nuevo proyecto de formulario implementando esta idea. Puede jugar con los ajustes para maxDistance (la distancia maxDistance permitida antes de cambiar de dirección) y stepDistance (la distancia recorrida en cada iteración del Timer ). Una stepDistance menor en el stepDistance resultará en un movimiento más suave pero más lento. Lo he hecho bastante pequeño, por lo que también he reducido la propiedad de Interval del Timer para acelerarlo.

Notarás que también agregué un método para validar que la dirección es válida, para que las bacterias no salgan de la pantalla. enum una enum para representar las direcciones, lo que facilitó la verificación del movimiento en una dirección en particular (es decir, si el valor de la enumeración contiene "Norte" y estamos demasiado cerca de la parte superior, es una dirección no válida; esto cubre "Norte Direcciones "," Noroeste "y" Noreste ").

Edición: Moví la creación de la lista de "distancias ponderadas" al constructor, y la modifiqué para seleccionar exponencialmente menos elementos en lugar de linealmente menos elementos.

Espero que tenga sentido:

public partial class Form1 : Form { // Program Settings and Controls private readonly Panel pnlBacteria; // Panel representing a piece of bacteria private readonly Random random = new Random(); // For randomly-generated values private readonly Timer tmrMoveBacteria; // Timer used for bacteria movement private readonly int bacteriaSize = 20; // Stores the size for our bacteria private const int maxDistance = 50; // The maximum number of moves allowed in the same direction. private const int stepDistance = 3; // The distance to travel on each iteration of the timer. Smaller number is slower and smoother private readonly List<int> weightedDistances; // Contains a weighted list of distances (lower numbers appear more often than higher ones) // Bacteria state variables private Direction direction; // Stores the current direction bacteria is moving private int distance; // Stores the distance remaining to travel in current direction // Represents possible directions for bacteria to move private enum Direction { North, NorthEast, East, SouthEast, South, SouthWest, West, NorthWest } public Form1() { InitializeComponent(); // Initialize our weighted differences array so that 1 is // chosen most often and maxDistance is chosen the least often weightedDistances = new List<int>(); for (var i = 0; i < maxDistance; i++) { var weight = maxDistance / (i + 1); for (var j = 0; j <= weight; j++) { weightedDistances.Add(i + 1); } } // Give life to the bacteria pnlBacteria = new Panel { BackColor = Color.Red, Width = bacteriaSize, Height = bacteriaSize, Left = random.Next(0, ClientRectangle.Width - bacteriaSize), Top = random.Next(0, ClientRectangle.Height - bacteriaSize) }; Controls.Add(pnlBacteria); // Start bacteria movement timer tmrMoveBacteria = new Timer {Interval = 10}; tmrMoveBacteria.Tick += TmrMoveBacteria_Tick; tmrMoveBacteria.Start(); } /// <summary> /// Sets the direction and distance fields to valid values based on the /// current bacteria position, direction, and remaining distance /// </summary> private void UpdateDirectionAndDistance() { // Get all directions var validDirections = Enum.GetValues(typeof(Direction)).Cast<Direction>(); // Remove invalid directions (based on the bacteria position) if (pnlBacteria.Top < bacteriaSize) validDirections = validDirections.Where(dir => !dir.ToString().Contains("North")); if (pnlBacteria.Right > ClientRectangle.Width - bacteriaSize) validDirections = validDirections.Where(dir => !dir.ToString().Contains("East")); if (pnlBacteria.Left < bacteriaSize) validDirections = validDirections.Where(dir => !dir.ToString().Contains("West")); if (pnlBacteria.Bottom > ClientRectangle.Height - bacteriaSize) validDirections = validDirections.Where(dir => !dir.ToString().Contains("South")); // If we''re supposed to keep on moving in the same // direction and it''s valid, then we can exit if (distance > 0 && validDirections.Contains(direction)) return; // If we got here, then we''re setting a new direction and distance distance = weightedDistances[random.Next(weightedDistances.Count)]; var directions = validDirections.Where(d => d != direction).ToList(); direction = directions[random.Next(directions.Count)]; } /// <summary> /// Executes on each iteration of the timer, and moves the bacteria /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TmrMoveBacteria_Tick(object sender, EventArgs e) { // Ensure direction and distance are valid UpdateDirectionAndDistance(); // Move the bacteria var dirStr = direction.ToString(); if (dirStr.Contains("North")) pnlBacteria.Top -= stepDistance; if (dirStr.Contains("East")) pnlBacteria.Left += stepDistance; if (dirStr.Contains("South")) pnlBacteria.Top += stepDistance; if (dirStr.Contains("West")) pnlBacteria.Left -= stepDistance; distance--; } }