简体   繁体   English

使用 Unity Engine 和 C# 在代码中进行排序和二分搜索

[英]Sort and Binary Search in the code with Unity Engine and C#

I'm doing a job for school purpose, and then it was required into the Game I'm creating with a friend to use some sort by Ascending the points in a Rank every time the Space Ship destroy a target and Update the Score, and after this happen, implement the method binary search (recursive) or even a new method of binary search and return the exact position of the actual points of the player in the Rank.我正在为学校目的做一份工作,然后我和朋友一起创建的游戏需要使用某种方式,每次太空船摧毁一个目标并更新分数时,都会通过提升排名中的点数,以及发生这种情况后,实现方法二分搜索(递归)甚至一种新的二分搜索方法,并返回玩家在排名中实际点的确切位置。 But I tried to insert the Method into the Update, but every time the position returned is -1.但是我试图将方法插入到更新中,但是每次返回的位置都是-1。

Besides that, an important thing to say is 2 things: First, the Sort by Ascending and Binary Search need to be done manually with every if, else, for, etc to do the sort and the search, this is one important requirement that I have been asked to do, nothing of array.sort() methods equals that I have done to test into the code, or ready unity methods to do the thing in just one line of command.除此之外,要说的重要一点是两件事:首先,升序和二分查找排序需要手动完成,每个 if、else、for 等进行排序和搜索,这是我的一个重要要求已经被要求做,没有什么 array.sort() 方法等于我为测试代码所做的,或者准备好统一方法在一行命令中完成这件事。

And second and more important, I'm trying everyday to seek and learn solutions to move the elements in and array to use conditional cases and binary search, but i assume that to me (who study arts and have a basic programming logic to understand how the codes work), was and yet still hard to understand how and why the codes to do this things works, and I'm doing my best to understand and learn about it, and all this reasons that I have pointed out above are the main reasons that I ask the help, because I think that this two implementations can be easy for someone who have more knowledge in this than me and my partner (an artist too).其次,更重要的是,我每天都在努力寻找和学习移动元素和数组以使用条件案例和二分搜索的解决方案,但我认为这对我来说(学习艺术并具有基本的编程逻辑来理解如何代码有效),过去和现在仍然很难理解执行这些操作的代码如何以及为什么有效,我正在尽最大努力去理解和学习它,我上面指出的所有这些原因都是主要的我寻求帮助的原因,因为我认为这两个实现对于比我和我的合作伙伴(也是艺术家)有更多知识的人来说可能很容易。 Now, follow the code:现在,请按照以下代码操作:

public class GameController : MonoBehaviour
{

    public GameObject Hazard;
    public Vector3 SpawnValues;
    public int HazardCount;
    public float SpawnWait;
    public float StartWait;
    public float WaveWait;
    public GUIText ScoreText;
    private int Score;
    public GUIText RestartText;
    public GUIText GameOverText;
    public bool GameOver;
    private bool Restart;
    public List<int> Lista_Array;
    public int[] arr = { 0, 1, 2, 3, 4, 5 };

    IEnumerator SpawnWaves()
    {

        yield return new WaitForSeconds(StartWait);
        while (true)
        {
            for (int i = 0; i < HazardCount; i++)
            {
                Vector3 SpawnPosition = new Vector3(UnityEngine.Random.Range(-SpawnValues.x, SpawnValues.x), SpawnValues.y, SpawnValues.z);
                Quaternion SpawnRotation = Quaternion.identity;
                Instantiate(Hazard, SpawnPosition, SpawnRotation);
                yield return new WaitForSeconds(SpawnWait);
            }
            yield return new WaitForSeconds(WaveWait);

            if (GameOver)
            {
                RestartText.text = "Press 'B' to return to main menu or 'R' to restart";
                Restart = true;
                break;
            }
        }

    }

    public void UpdateScore()
    {
        ScoreText.text = "Score: " + Score;
        for (int i = 0; i < 1; i++)
        {
            //Lista_Array = new List<int>(Score);
            Lista_Array.Insert(0, Score);
            Lista_Array.Insert(0, 0);
            Lista_Array.Insert(0, 999);
            Lista_Array.Insert(0, 1999);
            Lista_Array.Insert(0, 2999);
            Lista_Array.Insert(0, 3999);
            arr = Lista_Array.ToArray();
            Lista_Array = new List<int>(Score);
            Array.Sort(arr); // Need to implement here manually some kind of sort by Ascending the Points in the Rank (Rank = Array and Points = Elements and Position = Position of Elements in the Array)
        }
    }

    public int BuscaBinaria(int[] arr, int l, int r, int x) //This is the Method of a Recursive Binary Search, but always return the position of -1
    {
        if (r >= 1)
        {
            int mid = 1 + (r - l) / 2;
            if (arr[mid] == x)
            {
                return mid;
            }
            if (arr[mid] > x)
            {
                return BuscaBinaria(arr, 1, mid - 1, x);
            }
            return BuscaBinaria(arr, mid + 1, r, x);
        }
        return -1; //Aqui era -1
    }


    public void AddScore(int NewScoreValue)
    {
        Score += NewScoreValue;
        UpdateScore();
        int n = arr.Length;
        int x = 10;
        int result = BuscaBinaria(arr, 0, n - 1, x);
        if (result == -1)
        {
            Debug.Log("Posicao nao encontrada");
        }
        else
        {
            Debug.Log("Posicao encontrada no Ranking " + result);
        }
    }

    public void gameOver()
    {
        GameOverText.text = "Game Over";
        GameOver = true;
    }

    public void Start()
    {
        GameOver = false;
        Restart = false;
        RestartText.text = "";
        GameOverText.text = "";
        Score = 0;
        StartCoroutine(SpawnWaves());
        UpdateScore();
    }

    void Update()
    {
        if(Restart){
            if(Input.GetKeyDown (KeyCode.B)){
                SceneManager.LoadScene ("Menu");
            }
        }

        if(Restart){
            if(Input.GetKeyDown (KeyCode.R)){
                Application.LoadLevel (Application.loadedLevel);
            }
        }

    }

}

Some issues with your binary search method:您的二进制搜索方法的一些问题:

public int BuscaBinaria(int[] arr, int l, int r, int x) //This is the Method of a Recursive Binary Search, but always return the position of -1
{
    if (r >= 1) // You do a recursive algorithm, so the exit criteria should not be,
                // as long as the right border is larger than 1, but the exit should
                // be if there is still a range, like if (r-l>0) or similar.
                // Otherwise you could end in a endless loop
    {
        int mid = 1 + (r - l) / 2; // the middle of r and l is (r+l)/2 !!!! 
                                   // try with l = 3 and r = 5. middle should be 4.
                                   // 1 + (5-3) /2 = 2; (5+3)/2 = 4;
        if (arr[mid] == x)
        {
            return mid;
        }
        if (arr[mid] > x)
        {
            return BuscaBinaria(arr, 1, mid - 1, x); // Index, problem. Your array has
                                      // a 0-based index, so you should call (arr, 0, mid-1, x)
        }
        return BuscaBinaria(arr, mid + 1, r, x);
    }
    return -1; //Aqui era -1
}

Take this changes into account and try again.请考虑此更改并重试。 Debug your code with selveral input parameters (write a unittest method!), then you will see if your binary search does what you desire.使用多个输入参数调试您的代码(编写单元测试方法!),然后您将看到您的二分搜索是否符合您的要求。

Thank you @gofal3 for all your help and sorry for the delay to reply the answer and the final version of the code that me and my team mate done.感谢@gofal3 的所有帮助,对于我和我的队友完成的答案和最终版本代码的延迟回复表示抱歉。 Now, follow the code:现在,请按照以下代码操作:

using System;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameController : MonoBehaviour
{

    public GameObject [] Hazards;
    public Vector3 SpawnValues;
    public int HazardCount;
    public float SpawnWait;
    public float StartWait;
    public float WaveWait;
    public GUIText ScoreText;
    private int Score;
    public GUIText RestartText;
    public GUIText GameOverText;
    public bool GameOver;
    private bool Restart;
    public List<int> Lista_Array;
    public int[] arr = { 0, 1, 2, 3, 4, 5 };

    IEnumerator SpawnWaves()
    {

        yield return new WaitForSeconds(StartWait);
        while (true)
        {
            for (int i = 0; i < HazardCount; i++)
            {
                GameObject Hazard = Hazards[UnityEngine.Random.Range(0, Hazards.Length)];
                Vector3 SpawnPosition = new Vector3(UnityEngine.Random.Range(-SpawnValues.x, SpawnValues.x), SpawnValues.y, SpawnValues.z);
                Quaternion SpawnRotation = Quaternion.identity;
                Instantiate(Hazard, SpawnPosition, SpawnRotation);
                yield return new WaitForSeconds(SpawnWait);
            }
            yield return new WaitForSeconds(WaveWait);

            if (GameOver)
            {
                RestartText.text = "Press 'B' to return to main menu or 'R' to restart";
                Restart = true;
                break;
            }
        }

    }

    public void UpdateScore()
    {
        ScoreText.text = "Score: " + Score;
        for (int i = 0; i < 1; i++)
        {
            //Lista_Array = new List<int>(Score);
            Lista_Array.Insert(0, Score);
            Lista_Array.Insert(0, 0);
            Lista_Array.Insert(0, 999);
            Lista_Array.Insert(0, 1999);
            Lista_Array.Insert(0, 2999);
            Lista_Array.Insert(0, 3999);
            arr = Lista_Array.ToArray();
            Lista_Array = new List<int>(Score);
            BubbleSort(arr);
            //Array.Sort(arr);
            //Lista_Array = arr.ToList();
            //Array_Lista = Lista_Array.ToArray();
        }
    }

    public int BuscaBinaria(int[] arr, int l, int r, int x)
    {
        if (r >= 1)
        {
            int mid = (r + l) / 2;
            if (arr[mid] == x)
            {
                return mid;
            }
            if (arr[mid] < x)
            {
                return BuscaBinaria(arr, 0, mid - 1, x); //aqui tbm
            }
            return BuscaBinaria(arr, mid + 1, r, x); //aqui tbm
        }
        return -1; //Aqui era -1
    }

    public static int[] BubbleSort(int[] arr1)
    {
        int length = arr1.Length;

        int temp = arr1[1];

        for (int i = 0; i < length; i++)
        {
            for (int j = i + 1; j < length; j++)
            {
                if (arr1[i] < arr1[j]) //mudei aqui
                {

                        temp = arr1[i];

                        arr1[i] = arr1[j];

                        arr1[j] = temp;
                }
            }
        }

        return arr1;
    }

    public void AddScore(int NewScoreValue)
    {
        Score += NewScoreValue;
        UpdateScore();
    }

    public void gameOver()
    {
        int n = arr.Length;
        int x = Score;
        int result = BuscaBinaria(arr, 0, n - 1, x);
        if (result == -1)
        {
            Debug.Log("Posicao nao encontrada");
        }
        else
        {
            Debug.Log("Posicao encontrada no Ranking " + result);
        }
        GameOverText.text = "Game Over";
        GameOver = true;
    }

    public void Start()
    {
        GameOver = false;
        Restart = false;
        RestartText.text = "";
        GameOverText.text = "";
        Score = 0;
        StartCoroutine(SpawnWaves());
        UpdateScore();
    }

    void Update()
    {
        if(Restart){
            if(Input.GetKeyDown (KeyCode.B)){
                SceneManager.LoadScene ("Menu");
            }
        }

        if(Restart){
            if(Input.GetKeyDown (KeyCode.R)){
                //Application.LoadLevel (Application.loadedLevel);
                SceneManager.LoadScene("Main");
            }
        }

    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM