Array or list for trivia game? C#

Hi guys

I’m in the process of making a trivia game, and need your opinions on a matter regarding the questions…

I basically need to have an amount of questions and then, once a question is drawn remove it from the possible questions for the rest of the game…

As far as I understand lists can expand, but in this case I don’t need it to expand… only decrease…
Should I still use a list or is an array fine? (or more efficient even?)

Regardless of whether its an array or a list, what function will I then need to call a random variable from the array/list and then remove that variable from said list/array?

It’s that last part about removing it from the array/list than I’m unsure about.

Thank you in advance!

Have a list of questions (or dictionary keys or however you want to structure it).

Choose a random number between 0 and list.Count()-1.

Pull that entry from the list using list.RemoveAt(). That’s your question. Because it’s been pulled from the list, it won’t repeat.

For something like this, it probably doesn’t matter (performance-wise) whether you use an array or a List, so I’d still stick with a List.
Then you can just follow what BlackePete stated above.

1 Like

Lists are easier to use when their length is going to change over time.

As others said, use List. This is the right collection for your task.

Use a queue that you populate by selecting randomly from the global array of all questions.

1 Like

Thank you for the answers guys!

I still havn’t quite found a solution though…
I’m not very experienced with using lists, so I got a few issues…
Currently I’ve made a travia-question system that works like this:

Each question has three possible answers. Each answer has a script like this:

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

[System.Serializable]
public class Answer1Data
{
    public string answer1Text;
    public bool isCorrect;
}

Each question then have this script:

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

[System.Serializable]
public class QuestionData
{
    public string questionText;
    public Answer1Data answer1;
    public Answer2Data answer2;
    public Answer3Data answer3;
}

I then have this script to define stuff like timelimit, points won or lost and so on.

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

[System.Serializable]
public class RoundData
{
    public int timeLimitInSeconds;
    public int hiddenTimeLimitInSeconds;
    public int pointsAddedForFirstCorrectAnswer;
    public int pointsAddedForSecondCorrectAnswer;
    public int pointsSustractedForWrongAnswer;
    public QuestionData[] questions;
}

I then finally have a script that tie all the scripts above together, so that the information can be decided from the inspector:

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

public class DataController : MonoBehaviour
{
    public static DataController instance;
    void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public RoundData[] allRoundData;

    void Start()
    {
        SceneManager.LoadScene("MenuScreen");
    }

    public RoundData GetCurrentRoundData()
    {
        return allRoundData[0];
    }
}

I made the scripts this way, to make the overview in the inspector look somewhat neat, since I won’t be the one writing all the questions myself.
As mentioned, I am by no means a good programmer, so I am sure that this is a very cluncky way to do it and that it probably could be done from a single script, but I just don’t know how.

But in either case…
How do I turn something like this into lists instead of arrays?
As mentioned I only really have experience with arrays, and when I try to figure out how to make the same thing with lists instead I keep getting various scripting errors.

And I forgot to ask:

If it is difficult to change the code I posted above into using lists, instead of arrays, should I then use the same “array.RemoveAt()” approach or is it done differently with arrays?

Arrays are a crude low-level data structure. They’re for speed, or for quickly making very simple things. Lists are the good version of arrays. They have an array inside of them. If you use an array, and add extra features to make it more useful, you’re just rewriting a worse version of what List’s already have.

Unity uses arrays in lots of places for the same reason it uses floats – for games worried about FPS. Don’t let it give you the wrong impression. Normal programs use doubles, and Lists.

But wouldn’t that basically mean that games should prefer arrays (I know that my trivia game won’t have problems with fps, but on at larger scale?).

Depends. If you are going to resize the collection, then you are going to need to implement your own wrapper for array which won’t be all that different from List. If your collection doesn’t every change size, use an array.

My collection will only have to be able to become smaller… Never grow in size…
Are arrays okay for that purpose?

Lists seems smarter, so I’d rather use them, but I can’t figure out how to use lists if I want to make the inspector looking neat (as shown in my coding example above, where each objects in the array has a drop down arrow, that leads to the answers and boleans declaring if they’re true or not)

So far I’ve made it work the way I wanted to by using arrays (couldn’t figure out how to make it work with lists).

But I still cannot figure out how to remove the pulled index from the array…
If I use “RemoveAt” is gives me a “does not contain a definition for RemoveAt”-error.

When searching I can find some sites saying that c# has no RemoveAt…
What should I then use instead?

I believe this should work:

myList.Remove(myList[<index>]);

Where = an integer value.

Lists have a RemoveAt function.

Can you post code of how you were trying to build a list?

Here’s a very simple example of how to build a list, then remove an item:

List<string> someStringList = new List<string>(); 
someStringList.Add("Hello"); 
someStringList.Add("Goodbye"); 
someStringList.Add("World."); 

someStringList.RemoveAt(1); 

for (int i = 0; i < someStringList.Count(); ++i)
    Debug.Log(someStringList[i]);

Although, after reading the code you’ve posted, I do think I see a source of confusion: You may not want to remove stuff from a serializable container at runtime. What I originally was suggesting is you build a temporary list using random questions selected from a master array of questions.

However, since you have your questions baked into RoundData, it doesn’t look like you actually want a random set of questions for each round. Is that correct?

Well yes and no…
I’m making a “game” meant to be used for practicing trivia knowledge on some topics…
I made a simple version some time ago, but in that version the questions always came in the same order, which made it easier to remember (without necessarily learning the actual answer… just the order).

So what I wanted to create was basically the same thing but randomized…

So that you get a question with 3 possible answers.
Then you end your turn (there is some board game movement involved) and then again, at the end of your next turn, you get a new question… But without any risk of the question being repeated and preferably also without the order being the same every time you play.

The biggest hindrance however, was that I tried to write the code so that it would be costumizable through the inspector and look something like this:

https://ibb.co/eOH33K

(Edit: Couldn’t figure out how to upload image directly… but link is to imageshare)

But if that is much more complicated then writing it in the script will have to do…
I’m just not going to be writing all the questions myself, so wanted to make it easy for my friends to use :slight_smile:

Remove is not something it will recognize either (It might if I had used list instead of array though)

@BlackPete is right. There are actually two collection, not one.

The first one is your predefined array of questions for each round. Let it be array and keep it intact. There is no need to remove anything from this array.

And the second one is the queue of the questions for actual round. It can be a List, or a Queue, anything. Name it remainingQuestions or questionsQueue or something appropriate, initialze it from your original array and use it, for example like this.

// questions is your original array of questions, your predefined questions
// this statement will create a list and shuffle it
var shuffledQuestions = questions.OrderBy(q => Guid.NewGuid()).ToList();

// this will create a queue from your shuffled questions
var queuedQuestions = new Queue<Question>(shuffledQuestions);

// this will assign next question to the questionX variable AND remove it from the queue
var question1 = queuedQuestions.Dequeue();
var question2 = queuedQuestions.Dequeue();
var question3 = queuedQuestions.Dequeue();

Well yes, Remove is a List method. You cannot remove spaces in an array.

1 Like