Choosing a random word from an array

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Robster
:warning: Old Version Published before Godot 3 was released.

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

:bust_in_silhouette: Reply From: Zylann

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()]

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.

Robster | 2016-09-19 12:48

An alternative for getting an array of words could be:

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

See String — Godot Engine (latest) documentation in English

Akien | 2016-09-19 12:50

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?

Zylann | 2016-09-19 18:40

I was researching this and looking at the ARRAY topic here GDScript reference — Godot Engine (latest) documentation in English 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:

Robster | 2016-09-20 01:06