Typeerror in Python, I need to modify a string

Asked

Viewed 42 times

0

I’m making a very simple chessboard with no rules, just changing the positions to play. I made a list of the available houses on the board and with the move function I change the positions, anyway, it’s very simple. the problem is that I can’t change the previous position to an empty one, preventing the pieces from duplicating. get the bug:

boardnumFrom[positionFrom] = '[]'
TypeError: 'str' object does not support item assignment 

I need to define the exit positions of the piece for an empty house and I don’t know how. Board code:

board8 = {
    'a8': [], 'b8': [], 'c8': [], 'd8': [], 'e8': [], 'f8': [], 'g8': [], 'h8': []
}
board7 = {
    'a7': [], 'b7': [], 'c7': [], 'd7': [], 'e7': [], 'f7': [], 'g7': [], 'h7': []
}
board6 = {
    'a6': [], 'b6': [], 'c6': [], 'd6': [], 'e6': [], 'f6': [], 'g6': [], 'h6': []
}
board5 = {
    'a5': [], 'b5': [], 'c5': [], 'd5': [], 'e5': [], 'f5': [], 'g5': [], 'h5': []
}
board4 = {
    'a4': [], 'b4': [], 'c4': [], 'd4': [], 'e4': [], 'f4': [], 'g4': [], 'h4': []
}
board3 = {
    'a3': [], 'b3': [], 'c3': [], 'd3': [], 'e3': [], 'f3': [], 'g3': [], 'h3': []
}
board2 = {
    'a2': [], 'b2': [], 'c2': [], 'd2': [], 'e2': [], 'f2': [], 'g2': [], 'h2': []
}
board1 = {
    'a1': [], 'b1': [], 'c1': [], 'd1': [], 'e1': [], 'f1': [], 'g1': [], 'h1': []
}


def setBoard():
    # white
    board1['a1'] = 'T'
    board1['b1'] = 'B'
    board1['c1'] = 'N'
    board1['d1'] = 'Q'
    board1['e1'] = 'K'
    board1['f1'] = 'N'
    board1['g1'] = 'B'
    board1['h1'] = 'T'
    board2['a2'] = 'P'
    board2['b2'] = 'P'
    board2['c2'] = 'P'
    board2['d2'] = 'P'
    board2['e2'] = 'P'
    board2['f2'] = 'P'
    board2['g2'] = 'P'
    board2['h2'] = 'P'
    # black
    board8['a8'] = 'T'
    board8['b8'] = 'B'
    board8['c8'] = 'N'
    board8['d8'] = 'K'
    board8['e8'] = 'Q'
    board8['f8'] = 'N'
    board8['g8'] = 'B'
    board8['h8'] = 'T'
    board7['a7'] = 'P'
    board7['b7'] = 'P'
    board7['c7'] = 'P'
    board7['d7'] = 'P'
    board7['e7'] = 'P'
    board7['f7'] = 'P'
    board7['g7'] = 'P'
    board7['h7'] = 'P'

while True:

    def mover(boardnumFrom, boardnumTo, positionFrom, positionTo):
        boardnumFrom[positionFrom] = '[]'
        boardnumTo[positionTo] = piece


    def start():
        setBoard()
        print(board8)
        print(board7)
        print(board6)
        print(board5)
        print(board4)
        print(board3)
        print(board2)
        print(board1)


    start()
    piece = input("""
Digite 'sair' ou digite 
Qual peça deseja mover? 
>""")
    if (piece == 'sair'):
        print('Adeus, obrigado por jogar.')
        break
    else:
        boardnumFrom = input('Qual fileira voce esta? ')
        boardnumTo = input('Para qual fileira voce vai? ')
        positionFrom = input('Qual casa voce esta? ')
        positionTo = input('Para qual casa voce vai? ')
        mover(boardnumFrom, boardnumTo, positionFrom, positionTo)

it’s big but it’s very simple.

  • My recommendation for you to use matrix instead of multiple dictionaries.. It will be easier to do what you want.. (ex video: https://www.youtube.com/watch?v=EGmlFdwD4C4)

1 answer

1

In doing:

boardnumFrom = input('Qual fileira voce esta? ')

The variable boardnumFrom will be a string, because that’s what input returns. Then, you pass this string to the function mover:

mover(boardnumFrom, boardnumTo, positionFrom, positionTo)

And inside this function, try to change a position of this string:

boardnumFrom[positionFrom] = '[]'

Only in Python strings are immutable and you cannot change any position of it. Any attempt to do so will give that error you saw. Ex:

s = 'uma string qualquer'
s[1] = 'x' # TypeError: 'str' object does not support item assignment

Anyway, that’s the cause of the mistake. That said, I think you should review everything you’re doing.

First, the board should not be divided into 8 different dictionaries. Why not simply use a list of lists?

Also, to denote an empty position, you are using [], which is an empty list (and not a string). But since pieces are strings, why not make the empty position a string as well? It could be a blank space, for example (' '). Would look like this:

def setBoard():
    def peoes():
        return ['P'] * 8
    def pecas(): # desculpe, não sei se essa fileira tem um nome específico
        return ['T', 'N', 'B', 'Q', 'K', 'B', 'N', 'T']

    # tabuleiro 8 x 8: é uma lista com 8 elementos, sendo que cada elemento é uma lista com 8 espaços em branco

    # primeiro cria as 4 fileiras vazias do "meio"
    tabuleiro = [[' '] * 8 for _ in range(4)]
    # white
    tabuleiro.insert(0, pecas())
    tabuleiro.insert(1, peoes())
    # black
    tabuleiro.append(peoes())
    tabuleiro.append(pecas())
    return tabuleiro

def imprime(tabuleiro):
    def separador():
        print('+'.join(['---'] * 9))

    def letras():
        print(' ', ' | '.join(chr(ord('a') + i) for i in range(8)), sep='', end=' |\n')
        separador()

    letras()
    i = 7
    while i >= 0:
        linha = tabuleiro[i]
        print(' ', ' | '.join(linha), sep='', end='')
        print(f' | {i + 1}')
        separador()
        i -= 1

def mover(tabuleiro, colunaFrom, linhaFrom, colunaTo, linhaTo):
    def converteColuna(c): # converte a-h para 0-7
        return ord(c) - ord('a')

    colOrig = converteColuna(colunaFrom)
    linOrig = int(linhaFrom) - 1
    # move a peça para a nova posição
    tabuleiro[int(linhaTo) - 1][converteColuna(colunaTo)] = tabuleiro[linOrig][colOrig]
    # deixa a posição original vazia
    tabuleiro[linOrig][colOrig] = ' '

tabuleiro = setBoard()
while True:
    imprime(tabuleiro)
    piece = input("Deseja sair? s/n > ")
    if piece == 's':
        print('Adeus, obrigado por jogar.')
        break
    else:
        colunaFrom = input('Qual coluna você está? (a-h) ')
        linhaFrom = input('Qual linha você está? (1-8) ')
        colunaTo = input('Para qual coluna você vai? (a-h) ')
        linhaTo = input('Para qual linha você vai? (1-8) ')
        mover(tabuleiro, colunaFrom, linhaFrom, colunaTo, linhaTo)

Of course, there’s a lot to improve on. I do not check if the positions typed are valid, nor if the origin position has a part, or if the destination position is already occupied (not to mention that I would need to check if the movement is valid for the chosen part, and only present the valid movements as options, for example).

But just having the more organized board helps a lot. Choosing the right data structure is halfway towards better code.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.