String error in a function in Python 3

1

When I try to run the def of an error in the part of texto[x][y-1] , giving the following:

erro:TypeError: 'str' object does not support item assignment

Could anyone help me please?

def moveJogador(mapa, mov):
    if mov == "c":
        for y in range(len (mapa)-1):
            for x in range(len(mapa[0])-1):
                if texto[x][y] == JOGADOR_NA_MARCA:
                    texto[x][y-1] = ("@")  #Aqui está o erro de string
                    texto[x][y] = " "
                    print(mapa)   
    return None

movimento = input("Digite d | e | c | b | v | s [dir, esq, cima, baixo, voltar, sair]: ")

moveJogador(texto, movimento)
    
asked by anonymous 06.05.2015 / 17:50

1 answer

2

The error demonstrates exactly what is happening: in Python, strings are immutable objects - this is in contrast to C, for example where "strings" are just a convenient name for a region of the memory that is treated as a data sequence the size of a byte. (You can then char *a = "abcde"; a[0] = 'f'; in C, it changes the byte in the first position of the pointed memory by the variable "a")

In Python there is another kind of data that can be used in the same way that strings in C: changeable, and with a mapping more or less and direct between numbers in the range 0-255 and objects string length "1" (this in Python 2.x - in Python 3.x, the mapping to text must be explicit) - is bytearray.

So instead of creating your lines on the map using something like:

texto.append ("@") use: text.append (bytearray ("@") and you can address and change individual values in there.

This is the fastest solution for the coigo that you already have ready - In fact, the best solution for your project is to create a new class for contain your map (instead of having a map composed of lists and strings, where external functions act to check content and make changes).

With a class itself, and implementing the methods __getitem__ and __setitem__ you can have a "smart" map that knows how to locate the player, if it goes out, if it fills in with a value.

Just be careful to assume that the addresses passed to get and set / item are sequences of two values, and you can do something straight like this:

TAMANHO = (80, 25)
class MeuMapa(object):
    def __init__(self, tamanho=TAMANHO):
        # estrutura de dados interna, composta de listas de listas, pré-preenchidas com espaços
        self.dados_internos = ([" ",] * tamanho[0]) * tamanho[1]
        self.tamanho = tamanho
    def __getitem__(self, index):
        return self.dados_internos[index[0]][index[1]]
    def __setitem__(self, index, valor):
        return self.dados_internos[index[0]][index[1]] = valor


texto = MeuMapa()
texto[10,10] = "@"

Note that with this minimal implementation, you can already reference objects on the map using a single index search rather than two in sequence - leaving your map access code much cleaner - a "find_player" or " can be written in an equally simple way, and be re-used for each comparison of your "move player" - -the code you posted implies making two "for" nested to each option movement - with the above class, plus a method like:

def encontra_jogador(self):
    for y, linha in enumerate(self.dados_internos):
        for x, valor in enumerate(linha):
            if valor == JOGADOR_NA_MARCA:
                return x, y

What will allow you to do:

x, y = texto.encontra_jogador()
print (x, y)
(10,10)
    
06.05.2015 / 19:24