首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数组索引超出范围,但应进行定义。编程新手

数组索引超出范围,但应进行定义。编程新手
EN

Stack Overflow用户
提问于 2017-10-04 03:11:27
回答 1查看 200关注 0票数 2

这里的第一篇文章。

我正在自学C#和unity,并致力于开发一款类似于bejewelled的"match-3“风格的游戏。我已经根据教程编写了下面发布的所有代码,但是我自己和评论区中的其他人都遇到了数组超出范围的问题。

正如编译器所说的那样,错误。

代码语言:javascript
复制
IndexOutOfRangeException: Array index is out of range.
CreateGame.CheckGrid () (at Assets/Scripts/CreateGame.cs:181)
CreateGame.Update () (at Assets/Scripts/CreateGame.cs:229)

下面粘贴了CreateGame.cs的完整代码(整个项目中唯一的脚本)。但为了帮助你,我可以说,从我的研究来看,当你搜索没有存储在数组中的东西时,就会发生索引溢出。作为C#的新手,我只有两个项目(也来自教程),我缺乏如何实际解决这个问题的技术知识。

据我所知,当数组小于0 (比如负值)时,编译器会返回这个错误,因为-1显然超出了范围。

我认为罪魁祸首与这些if语句有关,特别是我们从c整数中减去1的情况。

代码语言:javascript
复制
if (tiles[c, r] != null && tiles[c - 1, r] != null)

但是,上面的代码嵌套在这个for语句中

代码语言:javascript
复制
for (int c = 0; c < cols; c++)

所以C的值永远不应该小于0,或者我误解了这个for语句的逻辑,c从0开始,如果它小于cols变量,就加1,或者当c=0时,它先完成for循环。我不太确定如何解决这个问题。

值得一提的是,数组大小在我工作的场景内的GameObject (在检查器中)上定义为4,并且我有4个单独的对象预置分配给tiles数组的4个值,并将它们的位置存储在tiles数组中(如代码中所示)。此外,cs脚本仅附加到单个游戏对象,因此没有代码运行的多个实例。

抱歉,如果这篇文章组织得不够好,我才学了一个星期。

感谢您的关注!:)

代码语言:javascript
复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tile
{
    public GameObject tileObj;
    public string type;
    public Tile(GameObject obj, string t)
    {
        tileObj = obj;
        type = t;
    }

}

public class CreateGame : MonoBehaviour
{
    GameObject tile1 = null;
    GameObject tile2 = null;

    public GameObject[] tile;
    List<GameObject> tileBank = new List<GameObject> ();

    static int rows = 8;
    static int cols = 8;
    bool renewBoard = false;
    Tile[,] tiles = new Tile[cols, rows];

    void Start()
    {

        //List population
        int numCopies = (rows * cols) / 3;
        for (int i = 0; i < numCopies; i++)
        {
            for(int j = 0; j < tile.Length; j++) // J becomes the int = to number of tile prefabs added
            {
                GameObject o = (GameObject)Instantiate 
                    (tile [j], new Vector3 (-10, -10, 0), tile [j].transform.rotation); // creates a clone tile of the screen
                o.SetActive (false);
                tileBank.Add (o); // adds tile (game object called o) to the array (not shuffled)
            }
        }

        ShuffleList(); //Shuffles the list of tile-bank after the list has been populated

        //Populates rows and columns with tiles from tileBank array
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                Vector3 tilePos = new Vector3 (c - 2, r - 4, 0); //creates tiles with an offset ( -2x and -4y) to place them in scene
                for (int n = 0; n < tileBank.Count; n++)
                {
                    GameObject o = tileBank [n];
                    if (!o.activeSelf) // if the tile is not active move it and make it active
                    {
                        o.transform.position = new Vector3 (tilePos.x, tilePos.y, tilePos.z); //moves tile into position, it was stored inactive at -10,-10
                        o.SetActive (true);
                        tiles[c, r] = new Tile (o, o.name); //Stores tile back into array
                        n = tileBank.Count + 1; //Update tile count
                    }
                }

            }
        }
    }

    //Shuffles the order of the array storing the tiles
    void ShuffleList()
    {
        System.Random rand = new System.Random ();
        int r = tileBank.Count;
        while (r > 1)
        {
            r--;
            int n = rand.Next (r + 1);
            GameObject val = tileBank [n];
            tileBank [n] = tileBank [r];
            tileBank [r] = val;
        }
    }

    //checks for missing tiles and adds new ones from array, also drops tiles down if there is an opening
    void RenewGrid()
    {
        bool anyMoved = false;
        ShuffleList ();
        for (int r = 1; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                if (r== rows - 1 && tiles[c, r] == null)
                    //if in the top row and there are no tiles
                {
                    Vector3 tilePos = new Vector3 (c, r, 0);
                    for (int n = 0; n < tileBank.Count; n++)
                    {
                        GameObject o = tileBank [n];
                        if (!o.activeSelf)
                        {
                            o.transform.position = new Vector3 (tilePos.x, tilePos.y, tilePos.z);
                            o.SetActive (true);
                            tiles [c, r] = new Tile (o, o.name);
                            n = tileBank.Count + 1;
                        }
                    }
                }
                if (tiles[c, r - 1] != null)
                {
                    if (tiles[c, r - 1] == null)
                        //drop down if space below is empty
                    {
                        tiles [c, r - 1] = tiles [c, r];
                        tiles [c, r - 1].tileObj.transform.position = new Vector3 (c, r - 1, 0);
                        tiles [c, r] = null;
                        anyMoved = true;
                    }
                }
            }
        }
        if (anyMoved)
        {
            Invoke ("RenewGrid", 0.5f);
        }
    }


    void CheckGrid()
    {
        int counter = 1;
        //check in columns for matches
        for (int r = 0; r < rows; r++) //repeats function until you have satisfied the number of rows
        {
            counter = 1;
            for (int c = 1; c < cols; c++)
            {
                if (tiles[c, r] != null && tiles[c - 1, r] != null) //if the tiles exist (not null)
                {
                    if (tiles[c, r].type == tiles [c - 1, r].type) //if there is a match add 1 to the counter for match checks
                    {
                        counter++;
                    }
                    else
                    {
                        counter = 1; //reset counter
                    }

                    //if a match is found remove tiles
                    if (counter == 3)
                    {
                        if (tiles [c, r] != null)
                        {
                            tiles [c, r].tileObj.SetActive(false);
                        }

                        if (tiles [c - 1, r] !=null)
                        {
                            tiles [c - 1, r].tileObj.SetActive(false);
                        }

                        if (tiles [c - 2, r] !=null)
                        {
                            tiles [c - 2, r].tileObj.SetActive(false);
                        }

                        tiles[c , r] = null; // changes values to null in the 2D matrix
                        tiles[c - 1, r] = null;
                        tiles[c - 2, r] = null;
                        renewBoard = true;

                    }
                }
            }
        }

        //check in rows for matches
        for (int c = 0; c < cols; c++)
        {
            counter = 1;
            for (int r = 1; c < rows; r++)
            {
                if (tiles[c, r] != null && tiles[c - 1, r] != null) //if the tiles exist (not null)
                {
                    if (tiles[c, r].type == tiles [c - 1, r].type) //if there is a match add 1 to the counter for match checks
                    {
                        counter++;
                    }
                    else
                    {
                        counter = 1; //reset counter
                    }

                    //if a match is found remove tiles
                    if (counter == 3)
                    {
                        if (tiles [c, r] != null)
                        {
                            tiles [c, r].tileObj.SetActive(false);
                        }

                        if (tiles [c, r - 1] !=null)
                        {
                            tiles [c, r - 1].tileObj.SetActive(false);
                        }

                        if (tiles [c, r - 2] !=null)
                        {
                            tiles [c, r - 2].tileObj.SetActive(false);
                        }

                        tiles[c, r] = null; // changes values to null in the 2D matrix
                        tiles[c, r - 1] = null;
                        tiles[c, r - 2] = null;
                        renewBoard = true;

                    }
                }
            }
        }

        if(renewBoard)
        {
            RenewGrid();
            renewBoard = false;
        }
    }

    void Update()
    {
        CheckGrid ();

        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition); //casts a ray from mouse position
            RaycastHit2D hit = Physics2D.GetRayIntersection (ray, 1000); //tests for ray hit
            if (hit)
            {
                tile1 = hit.collider.gameObject; //changes tile1 null to the gameObject who's collider was hit
            }
        }

        // if mouse button up detected after an initial tile has been hit with ray
        else if (Input.GetMouseButtonUp(0) && tile1)
        {
            Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
            RaycastHit2D hit = Physics2D.GetRayIntersection (ray, 1000);

            if (hit)
            {
                tile2 = hit.collider.gameObject; //changes tile2 nulle to the gameObject who's collider was hit
            }

            if (tile1 && tile2) //If we has two tile values clicked, swap them
            {
                //check to see that distance of clicked tiles is not greater than 1 tile
                int horzDist = (int)Mathf.Abs (tile1.transform.position.x - tile2.transform.position.x);
                int vertDist = (int)Mathf.Abs (tile1.transform.position.y - tile2.transform.position.y);

                if (horzDist == 1 ^ vertDist == 1) // X-OR Statment, IF 1 , OR 1, but NOT BOTH
                {
                    //get tile 1's array position
                    Tile temp = tiles [(int)tile1.transform.position.x, (int)tile1.transform.position.y];
                    //change tile 1's array position to now be tile 2's array position
                    tiles [(int)tile1.transform.position.x, (int)tile1.transform.position.y] = 
                    tiles [(int)tile2.transform.position.x, (int)tile2.transform.position.y];
                    //change tile 2's array position to now be tile 1's old array position
                    tiles [(int)tile2.transform.position.x, (int)tile2.transform.position.y] = temp;


                    Vector3 tempPos = tile1.transform.position; //get tile 1's GameObject position
                    tile1.transform.position = tile2.transform.position; //change tile 1 to tile 2's GameObject position
                    tile2.transform.position = tempPos; //change tile 2 to tile 1's GameObject position
                    //reset clicked tiles
                    tile1 = null;
                    tile2 = null;
                }
                else
                {
                    GetComponent<AudioSource> ().Play (); // Play error sound when illegal swap attempted
                }
            }
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2017-10-04 03:30:12

错误只是在for语句中使用了不正确的变量。

for (int r = 1; c < rows; r++)

应该是

for (int r = 1; r < rows; r++)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46551757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档