+1 vote

Hi all,

I have an array of X words (depends on the text tile provided). I want to choose just ONE word randomly from the list of words.

So far I have this (my first ever file handling which is a bit exciting):

#main game loop
func _ready():

    #get the words from the file and put them in a list
    var word_list = [loadWords()]       #load the words into an array
    for word in word_list:
        print(word)

func loadWords():
    var file = File.new();
    file.open("res://wordlist.txt", File.READ);

    var file_string = file.get_as_text();
    return file_string
    file.close();

If you look at my print statement it works. It's printing each word in the text file. So far so good. Now I want to grab just ONE of those words randomly from word_list.

I believe in Python I can use random.choice(word_list), but I also know GDScript is different.

Can anyone offer a link to a doc or a tutorial or even some advice on how to do this? I'm a little stumped unfortunately. I'm quite new at this but getting there.

All the best,

Rob

in Engine by (814 points)

1 Answer

+4 votes
Best answer

There are several things wrong with your code, some of them you didn't noticed:

var word_list = [loadWords()]

This is never going to give you an array of words. Instead, it will give you an array with one entry, and this single entry will contain whatever loadWords returns. Don't use the square brackets.

return file_string
file.close();

You returned before closing the file. return should be used as the very last instruction, because everything after it will never be executed.

var file_string = file.get_as_text();

This is going to read the whole file as a single string. You could think your print is fine, but that's actually because you are just printing the whole file with the \n characters, not the words.

So how to get an actual list of words?
Instead of file.get_as_text(), you can use this function:

static func get_lines(file):
    var lines = []
    while not file.eof_reached():
        lines.append(file.get_line())
    return lines

Assuming your file contains one word per line, this will read them one by one to fill an array of words, which is then returned.

Then, picking a random word will be easy at this point:

var word = words[randi() % words.size()]
by (27,505 points)
edited by

Brilliant!

So many beginner mistakes I made. Which make sense once I read your code, but still, I have a ways to go.

For future reference for anyone else learning, here is what I have:

extends Node

#variables
var activeWord = "XXXXXXXXXXXX"     #Display XXX's until a word is chosen

#main game loop
func _ready():

    #get the words from the file and put them in a list
    var word_list = loadWords()     #load the words into an array

    #pick a random word from the list
    randomize()
    activeWord = word_list[randi() % word_list.size()]
    print(activeWord)


func loadWords():
    var lines = []                              #set an empty array
    var file = File.new();                      #create an instance
    file.open("res://wordlist.txt", File.READ); #open the file into instance
    while not file.eof_reached():               #while we're not at end of file
        lines.append(file.get_line())           #append each line to the array
    return lines                                #send the array back

Thank you for the time spent, it's much appreciated.

An alternative for getting an array of words could be:

var text = file.get_as_text()
var arr = text.split(" ")

See http://docs.godotengine.org/en/latest/classes/class_string.html#class-string-split

I thought about this alternative too, but I wonder which one is better performance-wise if the file contains hundreds of thousands of words (that could be the whole dictionary, who knows xD).
Also, does split(" ") also works with \n?

I was researching this and looking at the ARRAY topic here http://docs.godotengine.org/en/latest/reference/gdscript.html it says that an array with tens of thousands of items can cause memory fragmentation. Now I'm too newby to fully understand how that could happen but it's possibly helpful.

Quote from link:

GDScript arrays are allocated linearly in memory for speed. Very large
arrays (more than tens of thousands of elements) may however cause
memory fragmentation. If this is a concern special types of arrays are
available. These only accept a single data type. They avoid memory
fragmentation and also use less memory but are atomic and tend to run
slower than generic arrays. They are therefore only recommended to use
for very large data sets:

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.

Categories