No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Verificar y evitar caramelos repetidos

13/31
Recursos

Vamos a solucionar el problema de la clase anterior.

Primero, debemos asignar un identificador diferente para cada elemento que generamos en la grilla. Adem谩s, debemos asegurarnos de que no hay un mismo tipo de dulce repetido en cualquier direcci贸n.

Para esto ultimo, en realidad, solo debemos verificar el tipo de dulce que generamos con las posiciones de abajo y a la izquierda, de esta forma nos aseguramos de que no habr谩 dulces repetidos en ninguna direcci贸n.

Recuerda que la primera columna de la grilla no tiene vecinos a la izquierda y, de igual forma, los primeros elementos de cada columna no tienen vecinos hacia abajo. De no tener esto en cuenta podemos generar algunos errores en nuestro algoritmo.

Aportes 10

Preguntas 0

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Reg铆strate o inicia sesi贸n para participar.

Para quien haya seguido mis pasos en los ultimos videos, les advierto aqui que ahora tuve que hacer mas cambios por preferencias personales, y que si siguieron lo que les dije antes, muchas cosas van a estar fuera de lugar, si aun asi quieren seguir con mis consejos:

Le quite el BoxCollider2D al background y se lo a;adi al objeto que sera el caramelo per se, cuando hice esto ya no se podia calcular el offset, asi que en vez de acceder al componente BoxCollider, accedo al GetComponent<SpriteRenderer>() que tienen una propiedad que es bounds y esa tiene sus propiedades vectoriales.

Como mis caramelos son prefabs que contienen la animacion y el box collider, y lo que existe en el juego son instancias de los caramelos, no puedo volverlos hijos de un objeto porque corromperia el estado del prefab, asi que decidi que no me molesta tanto que esten los candies en la jerarquia lateral, sin embargo los fondos si los hice hijos del board manager.

Mi codigo:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BoardManager : MonoBehaviour
{
    public static BoardManager sharedInstance;
    public List<GameObject> prefabs = new List<GameObject>();
    public GameObject backgroundGO;
    public int xSize, ySize;

    private GameObject[,] candies;

    int idx = -1;

    [SerializeField]
    private float paddingX = 0.4f, paddingY = 0.4f;

    public bool isShifting { get; set; }

    private void Start()
    {
        if(sharedInstance == null)
        {
            sharedInstance = this;
        }
        else
        {
            Destroy(this.gameObject);
        }

        Vector2 offset = new Vector2(backgroundGO.GetComponent<SpriteRenderer>().bounds.size.x + paddingX, backgroundGO.GetComponent<SpriteRenderer>().bounds.size.y + paddingY);
        CreateInitialBoard(offset);
    }

    private void CreateInitialBoard(Vector2 offSet)
    {
        candies = new GameObject[xSize, ySize];

        float startX = this.transform.position.x;
        float startY = this.transform.position.y;

        for(int x = 0; x < xSize; x++)
        {
            for(int y = 0; y < ySize; y++)
            {
                GameObject candyBackground = Instantiate(backgroundGO, new Vector3(startX + (offSet.x * x), startY + (offSet.y * y), 0), backgroundGO.transform.rotation);
                candyBackground.name = string.Format($"Candy[{x}][{y}]");

                candyBackground.transform.parent = this.transform;

                do
                {
                    idx = Random.Range(0, prefabs.Count);
                }while((x > 0 && idx == candies[x-1,y].GetComponent<Candy>().Id) || (y > 0 && idx == candies[x,y-1].GetComponent<Candy>().Id));

                GameObject candy = prefabs[idx];
                candy.GetComponent<Candy>().Id = idx;
                Instantiate(candy, candyBackground.transform.position, candyBackground.transform.rotation);

                candies[x, y] = candy;
            }
        }
    }

    private void Update()
    {
        
    }
}

Podemos configurar nuestros dulces para que todos sean hijos del Game Object invisible y podamos tener una vista m谩s c贸moda en Unity cuando colapsamos el elemento con el script del Board Manager:

newCandy.transform.parent = this.transform;

Condiciones del ciclo do-white para que los dulces no se repitan a la izquierda o hac铆a abajo:

do {
  // ... Random.Range ...
} while (
  (x > 0 && idx == candies[x-1, y].GetComponent<Candy>().id) ||
  (y > 0 && idx == candies[x, y-1].GetComponent<Candy().id>
)

Tengo un problema no aparecen los dulces en pantalla y desaparece el boardmanager cuando corro el juego鈥

Lo que entendi es que Si el dulce de la izquierda o abajo coincide se va a volver a llamar al 鈥淩andom.Range(0, prefabs.Count);鈥 para que ponga otro dulce aleatorio?

Genial

Analizando la l贸gica que se utiliza para evitar un tres en raya, note que tambi茅n evita el caso en el que sean solo dos caramelos en raya, cosa que si puede ocurrir en juegos de este tipo, cambie el while por el siguiente y este si permite ese caso.

< while((x>1 && idx == candies[x-2,y].GetComponent<Candy>().id) || (y>1 && idx == candies[x,y-2].GetComponent<Candy>().id)); >

OK. entonces generamos un bucle que esta garantizado a ejecutarse al menos una vez que lo que hace es generar un numero aleatorio siempre y cuando el identificador del caramelo que esta a nuestra izquierda y abajo no coincida con el identificador del caramelo que estamos generando.
.
Ahora este numero aleatorio generado lo usaremos para elegir el caramelo correspondiente a la hora de crear la matriz con los caramelos asegur谩ndonos que el juego no tenga caramelos repetidos uno cerca del otro.

Una sugerencia, para mejorar la lectura del c贸digo he movido la condici贸n del do - while a una funci贸n separada:

bool NeighborIsSameCandy(int x, int y) {
  return (x > 0 && idx == candies[x-1, y].GetComponent<Candy>().id) 
    || (y > 0 && idx == candies[x, y - 1].GetComponent<Candy>().id);
}

Y as铆 mi do - while se lee de este modo:

do 
{
   idx = Random.Range(0, prefabs.Count);
} while (NeighborIsSameCandy(x, y));

Saludos, tengo

Sprite sprite = prefabs[Random.Range(0, prefabs.Count)];
newCandy.GetComponent<SpriteRenderer>().sprite = sprite;
newCandy.GetComponent<Candy>().id = -1;

El problema es que solo me aparece un solo candy Random en vez de llenarse la pantalla