How do I check 2 arrays to see if both size and content match?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By CCLaw

What I’m Doing: I am using 2 arrays to show if the correct buttons (6/12) are toggled on… (this was my first question where Noddy helped me choose to use arrays original question)
array1 is the base array of [1, 2, 3, 4, 5, 6] and array2 starts as and grows/shrinks as user toggles switches on/off.
Why: user needs to choose the 6 correct words out of the 12 listed

So far, each button correctly adds to array2, but when user clicks “submit” after choosing, I am only getting a size match, not a content match.
So, I want to know how to also check if my array2 content matches array1 exactly [1, 2, 3, 4, 5, 6].
If size and content match, “success” or if not, “try again”

What I’ve Tried: I read this answer but I don’t see where to put that func arrays_same_content in my code–or how to say “if all those return true, then do the success stuff under submit button, if false do the other stuff”. i tried adding it instead of my current “size” stuff (below submit button pressed) but it didn’t work (“method not called” error) and I tried to make a method/function for it and failed in every way. I only want it to check those on submit_pressed and I can’t figure out how to do that–or how the “return true” causes the other stuff to happen (and the else/false stuff to happen if it doesn’t return true).

Note: rn my toggle button code is a messy workaround since I can only seem to compare size not content… I just appended two things when a wrong one is pressed (instead of one) so it makes the array too big when any of the 6 pressed are not “correct.” It’s still not foolproof bc you can select 4 and end up with an array of 6 things.

Here’s my current code:
Top

extends Control
export var value = 100
var array1 = [1, 2, 3, 4, 5, 6]
var array2 = []
var length = array2.size() #I don't even remember where I got this--needed??

func _ready():
	array1.size() #do I even need these? Are they feeding Submit> if #2 ?
	array2.size()

Button Codes (Correct button then Incorrect button)

func _on_cardGIVE_toggled(button_pressed):
	if button_pressed==true:
		array2.insert(1, "2")
		print(array2)
	else:
		array2.erase("2")
		print(array2) 


func _on_cardAGE_toggled(button_pressed):
	if button_pressed==true:
		array2.append("A") 
		array2.append("FF")
		array2.append("EE")
		print(array2)
	else:
		array2.erase("A")
		array2.erase("FF")
		array2.erase("EE")
		print(array2) 

Then once user is done toggling/choosing, they click CHECK (Submit button) and…

func _on_Submit1_pressed():
	$RR1InfoAudio.stop()
	if array2.size() > 5: #Is this one better or is the == one right?
		print(true) #print should be return? print not feeding info I know, what good is returning true here if idk how to say "if true, do this"?
	if array1.size() == array2.size():
		$Success.show() #label "good job!"
		$GotoChal2.show() #button loads to next challenge scene
	else:
		$Fail.show() #label saying try again
		$RR1TryAgainAudio.play() #narration audio
		$TryAgainChal1.show() #button that reloads scene

I am totally new to coding and have done the “first 2d” and 3d game tutorials all the way through (successfully made those and dodged creeps etc). I watched all this guy’s stuff on arrays: https://godottutorials.com/courses/introduction-to-gdscript/godot-tutorials-gdscript-09/ and went through everything I can find. I know my “size” is basically checked 2 ways lol, I don’t know what I can take out on that (the function ready stuff? Line 1 or 2 check under if on Submit button??) i’m just lost on how to also check/return true for matching content. I didn’t do insert on wrong buttons because I didn’t want to overwrite the correct answer index positions.

I’m so grateful for any help anyone might have. Thanks so much (and please be gentle with me-tryin to learn here)

:bust_in_silhouette: Reply From: jgodfrey

Just noticed the post and code you mention is mine, so I’ll offer some input…

First, I think the arrays_have_same_content() method I posted in the linked message is useful here. Really, it should be about as simple as:

  1. Add the arrays_have_same_content() method to the above script
  2. Use it in your on_Submit1_pressed() method, something like:

.

if arrays_have_same_content(array1, array2):
    # do success stuff
else:
    # do failure stuff

Note however that the mentioned function will return true if the arrays have matching content, regardless of the content order. For example, these are seen as equivalent:

[1, 2, 3, 4]
[3, 2, 4, 1]

If you need to ensure the elements are the same AND in the same order, that script isn’t appropriate. Though, it’d be easy to replace with something else.

jgodfrey | 2022-02-13 21:48

You’re like the forums celebrity and I’m honored you answered!!! THANK you!!
I actually do NOT want it to have to be selected in order, so this is great!

Where I get stuck: where do I add “arrays_have_same_content” method to the above script? After var’s at top or after toggle buttons? Or just anywhere before “Submit_pressed”? I feel I missed something very basic on creating a function but I can’t figure it out. I get the “method not called” error when I think I added it above, then try to add the “if arrays_have_same_content” to submit1 button script. I’m going to go back through your linked post again and see if I can figure it out. (I’m going to do that in the morning so I am 100% focused and clear).

Thank you so much.

CCLaw | 2022-02-13 22:05

Referencing your original post above, you can put the new function anywhere after this line of code:

var length = array2.size() #I don't even remember where I got this--needed??

Obviously, don’t insert it “in the middle” of another function. Otherwise, it can go most anywhere.

jgodfrey | 2022-02-13 22:20

And, looking closer, I don’t see any reason for any of the following code:

var length = array2.size() #I don't even remember where I got this--needed??

and

array1.size() #do I even need these? Are they feeding Submit> if #2 ?
array2.size()

jgodfrey | 2022-02-13 22:28

That was IT!! I copied your exact code (from this answer) and put it right below my var’s:

func arrays_have_same_content(array1, array2):
    if array1.size() != array2.size(): return false
    for item in array1:
        if !array2.has(item): return false
        if array1.count(item) != array2.count(item): return false
    return true

Then I copied from above ^^ and put it in my Submit_Button pressed function:

if arrays_have_same_content(array1, array2):
     show success stuff
else
     show fail stuff

That works perfectly! I was glitching on what to put in Submit Button, and I guess where that “checker” function went (in my mind I got that I must refer to the check, but I needed what you wrote above to understand the exact syntax and where to put it all). Now I get it- first check “true” in its own function at top, then to get the result to trigger something by button press, I just only put the check function name in the “if” statement and add else.

Now, I’m going to change my “insert” in the toggle codes to “append” since in your solution, the order in array2 doesn’t matter, and currently by my using “insert”, if they check the boxes out of order, it returns false (if you try to insert (3, “4”) when there’s nothing in index position 2 yet, it won’t). Long story short, you got my mind out of a crashing loop, and I am grateful.

A Million thank you’s for your patience-- for helping me understand your answer in the other post, and especially for clarifying the order thing. Also for the bonus of confirming I had extra unneeded lines in there. Thank you so very much.

CCLaw | 2022-02-14 13:48

Nice - glad you got it working! Happy to help.

jgodfrey | 2022-02-14 14:02

Welll, when I changed them to “append” and they’re not in the order [1,2,3,4,5,6] it doesn’t work :-/ If they’re clicked in that order, it works, but if they’re clicked [5, 6, 4, 2, 3, 1] it returns false. Back to the drawing board. I will maybe add “sort” or something. But the general code you gave for comparing is working, and pretty sure it’s my toggle button input to array that needs the work. So again, I still send the million thank you’s :slight_smile:

CCLaw | 2022-02-14 14:13

Hmmm… That doesn’t sound right. Is your project available anywhere that I could take a closer look?

jgodfrey | 2022-02-14 14:41

I’d suggest that you print out the contents of each array just prior to calling arrays_have_same_content(). I’d guess they don’t contain what you think in the cases where the function is returning false

jgodfrey | 2022-02-14 14:48

Related, the below code returns True, as expected…

var arr1 = [1,2,3,4,5,6]
var arr2 = [3,6,5,2,1,4]
print (arrays_have_same_content(arr1, arr2))

jgodfrey | 2022-02-14 16:32

Okay, I took a “clear my head” break and am back at it.

As you suggested, on submit button pressed, I printed each array plus the function (arrays_have_same_content(array1, array2), they showed:
array1=[1, 2, 3, 4, 5, 6]
array2=[1, 2, 3, 4, 5, 6]
False

Idea 1: am I missing some kind of “save the array2 after it’s appended” kind of command? Like the user is adding/removing from array2, but is that being stored somewhere automatically or do I need to somehow save/store their final selection before I check if_same_content? I thought about “index” or “return the new array” somehow.

Idea 2: Looking at your code in the “related” box in the last reply, at the top of the script, am I supposed to start array2 with values 1-6 in it instead of starting it empty? Does that matter?
I have:

var array1 = [1, 2, 3, 4, 5, 6]
var array2 = []

I did this to be able to have the user add to var array2 with toggle button clicks, but maybe that’s wrong?
Tried this, works, sort of: I changed var array2 to [1, 2, 3, 4, 5, 6] and made “correct” buttons do nothing when toggled on (keeps array2 correct), and added a number to array if toggled back off (since that needs to return false bc it’s wrong). Then, “wrong” buttons append a letter if toggled on, erase it if toggled off again (that works). THIS WORKS. The only issue is if they toggle the correct one ON, then off, then ON AGAIN, I am out of if/else statements in that button (since the first toggle on doesn’t change the array).
(I feel like this should be WAY simpler…but I’m going with the filled array2 for now since it works unless they toggle/untoggle multiple times on correct buttons.)

found this How to get input from a button and fill an array with the sequence of the input? - Archive - Godot Forum Best Answer comment replies…tried null, null, null, and it printed “null” in each spot so that wasn’t it. Saw your answer but isn’t that more than I need?

Idea 3: My only other idea is if I should be using pop/pop back type methods on the toggle presses to add to/remove from array2, instead of insert/append and erase?

Side Note: Now, I’m getting SHADOWED_VARIABLE errors (the variable in line 6 is shadowing line 3/4 already defined array1 array2). FYI Line 3/4 is var array1 and var array2, line 6 is the func _arrays_have_same_content.
Tried: removing array1 then array2 from the var section at top, returned line 6 “var is not defined” so I put them back in. Not understanding why this is an error now since it wasn’t last week lol.

CCLaw | 2022-02-20 14:28

Here is the whole scene if that helps anyone lol.
https://drive.google.com/drive/folders/1d7D8YEiOMzp0BwuBTOBGFnhaKVqT-xQ4?usp=sharing

CCLaw | 2022-02-20 15:16

Can you make the entire project available for examination? It’s not possible to run your scene based on the content you posted above. For example, there’s not project.godot file in posted folder…

jgodfrey | 2022-02-20 15:30

Related to this:

Now, I’m getting SHADOWEDVARIABLE errors…

First, that’s a WARNING, not an ERROR. It’s telling you that you’re doing something that possibly confusing / dangerous, but it won’t cause any actual issues. That said, you should probably fix it for clarity.

The problem is that you have defined global copies of array1 and array2 (at the top of your script and you have a local copy of the same variable names defined in the arrays_have_same_content() function.

The easy fix is to rename the variables in the function to something different. For example, this would fix the warning:

func arrays_have_same_content(a1, a2):
	if a1.size() != a2.size(): return false
	for item in a1:
		if !a2.has(item): return false
		if a1.count(item) != a2.count(item): return false
	return true

Note, array1 and array2 have been renamed to a1 and a2 in the function.

jgodfrey | 2022-02-20 16:01

You are too kind …you have gone WAY above and beyond on helping me and I know I will get it all figured out if I go back to the basics on each thing I want to add. I really think you have done more than anyone ever should! Can I donate to something or give back in some way?

Entire Godot Game “Owen”

It is still uploading everything as I post it but should be done in 5 minutes :slight_smile:
(I had a couple unused/try out things in there so ignore anything about “cards” and scenechanger and main–MainScene is the main scene lol)

I will adjust the function to use a1/a2! Thank you for explaining what was causing that!

CCLaw | 2022-02-20 16:16

Just took a look at your project. The main problem is that your initializing your “answer” array with int values (1, 2, 3, 4, 5, 6), but you’re appending string values to the array that you’re comparing (“1”, “2”, “3”, “4”, “5”, “6”). When you eventually call arrays_have_same_content, that method is returning false because the int values in the answer array don’t match the string values in the match array.

To fix that, you need to use the same data type in both arrays. Either strings or ints will work, but they should be the same.

Since you’re using “letters” for incorrect choices (which can’t be an int), I’d recommend that you just use strings everywhere.

So, at the top, initialize your arrays like this:

var array1 = ["1", "2", "3", "4", "5", "6"]
var array2 = []

(notice, the 6 values added to array1 are string, not int)

And, notice that array2 is simply empty.

Then, you can code each *_toggled function like this, although obviously, append and erase the correct character in each function.

func _on_cardAGE_toggled(button_pressed):
	if button_pressed==true:
		array2.append("1")
	else:
		array2.erase("1")

Above, the given character is added to the array when the button is pressed and erased when the button is unpressed. That ensures that the array will always have only 0 or 1 copy of the character no matter how many times the button is pressed - which is important when you finally compare it to the answer array.

If you code all of the button handling functions like the above, your scene should work as you expect.

I would also say that, while what you have here will work, it’s laborious to create, error-prone to code, and just requires a lot of work to manage a single “quiz”. There are certainly better ways to do this kind of thing, but the above should get you working.

Let us know how you get along.

jgodfrey | 2022-02-21 01:05

You are the best. Thank you so much. I did it!! It works perfectly! The 0/1 copy was a stroke of genius, and of course works with strings in both arrays… exactly what I wanted to do in the first place. THANK you!!

The int/string thing makes so much sense now. I noticed it when I tried append vs. insert (how you need the index and the string), but kept focusing on array2 strings and completely spaced that there’s no reason to have index positions in array 1 instead of just strings!! Thank you so so much for everything you’ve done.

I agree wholly this is way too complex doing every button individually. I know there must be a much more cohesive way (like some sort of batch process for a quiz) and I will find it! At least it works for now!! My next “challenge” will be more complicated (JSON import for arrays), so I will find a better “base” for a quiz type thing. In my forum/video/tutorial googling, I found multiple choice quizzes (one answer is correct) and memory card games (flip/match one pair of cards) and couldn’t figure out how to adapt them to multiple “correct answers.” But that’s okay, because I am learning how to conceptualize my “learning checks” to fit better code practices! I am so happy because I can tell I am growing and learning by how much I go back and fix a parent scene (I’ve streamlined like 5 things in MainScene since I uploaded that project for you yesterday!).

Your willingness to help me understand has given me the determination that I will get there! Thank you again, very much. All the best to you and yours.

CCLaw | 2022-02-21 18:42