0

I am currently making a snake game but I have come across something I do not understand.

def moveHead():
    global snakeList
    lenlist = list(range(1,len(snakeList)))
    lenlist.reverse()
    for i in lenlist:
        snakeList[i] = snakeList[i-1]
    snakeList[0][1] += 30
    print("AF")
    print(snakeList)

Basically, snakeList is a list of coordinates. For example [[25,25],[0,0]]

What's supposed to happen is that is that the item shifted to the right except of the element in index 0. In the example mentioned, [0,0] would turn into [25,25], and the line below the for loop would change the whole thing to [[25,55],[25,25]].

For some reason the second item would also copy the changed item in the front, turning snakeList into [[25,55],[25,55]].

David
  • 8,113
  • 2
  • 17
  • 36
Tay
  • 27
  • 2

3 Answers3

0

With snakeList[i] = snakeList[i-1], you don't actually have two sub-lists. The assignment just copies the reference to the sub-list, not the actual sub-list, so both snakeList[i] and snakeList[i-1] refer to the same sub-list after the assignment, thus when changing one element the other changes respectively.

In order to get the desired result you should use the builtin list.copy() method:

snakeList[i] = snakeList[i-1].copy()

Which after running your code with the above correction the result is:

AF
[[25, 55], [25, 25]]
David
  • 8,113
  • 2
  • 17
  • 36
0

Hey it seems you're taking a very long way of doing something that python has built-in functionality for

So it seems you'd like every item in the list except the first item?

You can achieve this by some manipulation with the ':' in the array

# first we can get the last index of the array, e.g. snakeList
last_i = len(snakeList)
# then we can use the part of the array we'd like, in this case everything else except the first
snake_list_copy = snakeList[1:last_i]
# you can then make use of python's simple array manipulation to add any new items to the array
snakeList = snake_list_copy + [ new_items ] # this will create a new array with new items at the end

As a quick example, consider the following

a = [2, 4, 6, 8]
last_i = len(a)
b = a[1:last_i] # b is now [4, 6, 8]
b = [0,2] + b + [10,12] # b is now [0, 2, 4, 6, 8, 10, 12]
steff_bdh
  • 1,108
  • 2
  • 15
  • 32
0

The following code will solve your issue:

def moveHead():
    global snakeList
    snakeList.insert(0, snakeList[0].copy())
    del snakeList[-1]
    snakeList[0][1] += 30

What's supposed to happen is that is that the item shifted to the right except of the element in index 0. In the example mentioned, [0,0] would turn into [25,25], and the line below the for loop would change the whole thing to [[25,55],[25,25]].

No. Note the indices are reversed by:

lenlist = list(range(1,len(snakeList)))
lenlist.reverse()

If len(snakeList) is 4, then after this 2 lines the content of lenlist is [3, 2, 1].

So the for loop operates in reverse order. If the content of snakeList is [[0,0],[25,0],[50,0],[75,0]], then after processing the loop

for i in lenlist:
   snakeList[i] = snakeList[i-1]

the content of the list is [[0, 0], [25, 0], [50, 0], [75, 0]]

What now happens is, that the 1st and 2nd element of the list refer to the same object.

So after the line

snakeList[0][1] += 30

The content of the list is [[0, 30], [0, 30], [25, 0], [50, 0]].

If you repeat the process, then the content of the list will change to [[0, 60], [0, 60], [0, 60], [25, 0]] and further [[0, 90], [0, 90], [0, 90], [0, 90]]. Now all the elements of the list refer to the same list object.

You can get rid of that, by doing a shallow copy (list.copy()) of the list element (each element of the list is a list, too):

snakeList[i] = snakeList[i-1].copy()

If you want to move the elements of the list to the right, then appending a new element at the head of the list and deleting the tail element of the list will do the job, too:

snakeList.insert(0, snakeList[0].copy())
del snakeList[-1]
Rabbid76
  • 202,892
  • 27
  • 131
  • 174