Je ne suis pas sûr de totalement comprendre le problème. Tu as une aire de jeu (un labyrinthe) dont chaque case est représentée par un seul caractère : '@'.
Tu veux placer un pion dessus, mais qui est représenté par deux caractères : 'x1'. Et du coup, si tu remplaces simplement un '@' par le 'x1', ça décale tout. C'est ça ?
Il y a plusieurs façons de régler ça. Personnellement, je le ferais avec des "layers".
Chaque layer est un tableau 8*8 de caractères.
Le premier layer représente le plan du labyrinthe. Son contenu de change pas.
Le second contient la position du pion. Son contenu est reconstruit à chaque "tour de jeu".
Pour finir, il faut une fonction capable d'empiler ces deux layers et d'écrire le résultat.
Par exemple :
layer_grid =
@@@@@@@@
@@@@@@@@
@@@@@@@@
@@@@@@@@
@@@@@@@@
@@@@@@@@
@@@@@@@@
@@@@@@@@
layer_pion =
........
........
........
........
........
....x1..
........
........
En vrai, on utilisera des espaces et non des points, pour représenter les cases vides du deuxième layer.
résultat final =
@@@@@@@@
@@@@@@@@
@@@@@@@@
@@@@@@@@
@@@@@@@@
@@@@x1@@
@@@@@@@@
@@@@@@@@
C'est assez générique. Cela te permettrait d'avoir plusieurs pions, des pions plus gros, plus de 2 layers, etc.
Mais il faut penser à gérer les cas particuliers (pion en dehors de la grille, plusieurs pions au même endroit, etc.).
Ci-dessous, un exemple de code, avec plein de commentaires.
LABY_SIZE_X = 8
LABY_SIZE_Y = 8
grid = [ [ '@' for x in range(LABY_SIZE_X) ] for y in range(LABY_SIZE_Y) ]
def move_down(pos_pion):
"""
"""
# TODO : prévoir le cas où le pion est déjà tout en bas de la grid. Au choix :
# - on refuse le mouvement
# - on génère une exception,
# - on se téléporte tout en haut,
# - on ne fait rien car on laisse à une autre fonction la responsabilité de faire cette vérif,
# - ...
pos_pion[1] = pos_pion[1] + 1
# TODO : faire les autres fonctions move_xxx.
# Ou bien une fonction move avec un paramètre supplémentaire indiquant la direction.
def build_layer_pion(pos_pion):
"""
renvoie un tableau de caractères (même taille que le labyrinthe), contenant
majoritairement des espaces, et le 'x1' du pion au bon endroit.
Exemple :
build_layer_pion([1, 4]) -->
[[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', 'x', '1', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']]
"""
# TODO : la fonction pourrait prendre une liste de pion en paramètre.
# et on placerait tout les pions sur le layer.
# On peut également imaginer des pions n'ayant pas tous la même représentation : x1, x2, ...
layer = [ [ ' ' for x in range(LABY_SIZE_X) ] for y in range(LABY_SIZE_Y) ]
x_pion, y_pion = pos_pion
# TODO : Attention, ça va planter si la position du pion n'est pas du tout dans le labyrinthe.
# Il faudrait faire un check, ou faire en sorte que ça ne puisse jamais arriver.
# Voir remarques dans la fonction move_down.
layer[y_pion][x_pion] = 'x'
if x_pion+1 < LABY_SIZE_X:
layer[y_pion][x_pion + 1] = '1'
return layer
def print_layers(layer_bottom, layer_top):
"""
Empile deux layers, et écrit le résultat sur la sortie standard.
Pour chaque case du jeu, si on a un caractère non-espace dans layer_top,
on écrira celui-là. Sinon, on prend le caractère du layer_bottom.
"""
# On pourrait imaginer plus que deux layers, qui s'affichent dans l'ordre.
# Un pour le décor de fond, un pour les pions, un pour des pions volants,
# un pour l'UI du jeu en lui-même (affichage du score, etc).
# Pour chaque case, on parcourt les layers du plus haut vers le plus bas.
# Dès qu'on trouve une tile qui n'est pas un espace, c'est ce qu'il faut afficher.
for y in range(8):
line_game = ''
for x in range(8):
tile_layer_top = layer_top[y][x]
if tile_layer_top != ' ':
tile = tile_layer_top
else:
tile = layer_bottom[y][x]
line_game += tile
print(line_game)
def print_game(layer_grid, pos_pion_x1):
"""
écrit sur la sortie standard la situation courante du jeu.
"""
layer_pion = build_layer_pion(pos_pion_x1)
print_layers(layer_grid, layer_pion)
def print_next_turn():
"""
Écrit une ligne de séparation à l'écran.
Ça permet de ne pas avoir la suite de tout les labyrinthe qui s'affiche d'un coup,
et de bien distinguer les différentes situations du jeu.
"""
print('')
print('-' * 20)
print('')
pos_pion_x1 = [0, 3]
print_game(grid, pos_pion_x1)
print_next_turn()
move_down(pos_pion_x1)
print_game(grid, pos_pion_x1)
print_next_turn()
move_down(pos_pion_x1)
print_game(grid, pos_pion_x1)
print_next_turn()
pos_pion_x1 = [ 7, 5 ]
print_game(grid, pos_pion_x1)
print_next_turn()