【问题标题】:Sort and Binary Search in the code with Unity Engine and C#使用 Unity 引擎和 C# 在代码中进行排序和二进制搜索
【发布时间】:2018-11-07 13:05:35
【问题描述】:

我正在为学校目的做一份工作,然后它被要求进入我与朋友创建的游戏中,以通过每次太空飞船摧毁目标时提升等级中的点数并更新得分,发生这种情况后,实现方法二分搜索(递归),甚至是一种新的二分搜索方法,并返回玩家实际点数在排名中的确切位置。但是我尝试将Method插入到Update中,但是每次返回的位置都是-1。

除此之外,重要的是要说两件事:首先,按升序排序和二进制搜索需要手动完成每个 if、else、for 等来进行排序和搜索,这是一个重要的我被要求做的要求,array.sort() 方法中的任何一个都不等于我在代码中所做的测试,或者准备好统一的方法来只用一行命令来做这件事。

其次,更重要的是,我每天都在尝试寻找和学习将元素移入和数组以使用条件案例和二分搜索的解决方案,但我认为对我来说(学习艺术并具有基本的编程逻辑了解代码是如何工作的),但仍然很难理解代码是如何以及为什么这样做的,我正在尽我所能去理解和了解它,以及我在上面指出的所有这些原因是我寻求帮助的主要原因,因为我认为这两种实现对于比我和我的合作伙伴(也是艺术家)有更多知识的人来说很容易。现在,按照代码:

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

    }

}

【问题讨论】:

  • 间隔良好的文本阅读起来更愉快。
  • UpdateScore() 中,您总是重新创建数组arr。它包含值 0、999、1999、2999、3999 和 Score 的当前内容。然后将 x 的值设置为 10,并使用二进制搜索在数组中搜索包含值 10 的数组的位置,因为条件是,当您以非 -1 的结果离开二进制搜索时,当arr[mid] == x 时,所以当元素的值与x 相同时。但是您的数组不包含值 10,这就是返回 -1 的原因。
  • @gofal3 我已经更改了 x = Score; 的代码,现在返回分数的元素位置,但只要点在元素位置为元素 24,导致出现如下错误:StackOverflowException: The requested operation caused a stack overflow. GameController.BuscaBinaria (System.Int32[] arr, Int32 l, Int32 r, Int32 x) (at Assets/Scripts/GameController.cs:86) ------ 第86行内容: return BuscaBinaria(arr, mid + 1, r, x);
  • 是的,我明白了。在我看到数组的东西之后,我没有仔细研究二进制搜索本身,但我没有。发现了一些问题。出于格式化原因,我将发布作为答案。

标签: c# sorting binary-search-tree


【解决方案1】:

您的二分搜索方法存在一些问题:

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
}

考虑此更改,然后重试。使用几个输入参数调试您的代码(编写一个 unittest 方法!),然后您将看到您的二进制搜索是否符合您的要求。

【讨论】:

    【解决方案2】:

    感谢@gofal3 的所有帮助,对于延迟回复答案以及我和我的队友完成的代码的最终版本,我们深表歉意。现在,按照代码:

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

    【讨论】:

      猜你喜欢
      • 2013-10-29
      • 1970-01-01
      • 2017-03-26
      • 2022-01-24
      • 2021-12-03
      • 1970-01-01
      • 2020-09-05
      • 2015-10-31
      • 1970-01-01
      相关资源
      最近更新 更多