♟2026.05.22
Spirales
et chevaliers | 5. finitions et visualisations
Nous sommes arrivés, fonctionnellement, au bout de l’exercice en produisant cette figure-ci lors de l’épisode précédent:
Restent quelques finitions, à commencer par le fait de pouvoir utiliser un fichier JSON pour décrire la figure attendue. Ensuite, on pourra essayer de générer des images sympa!
Configuration
On cherche à décrire la configuration dans un fichier avec cette structure:
{
"n_layers": 20,
"players": [
{"color": "r", "offsets": [[1, 2], [-1, 2], [2, 1], [-2, 1], [1, -2], [-1, -2], [2, -1], [-2, -1]]},
{"color": "k", "offsets": [[1, 2], [-1, 2], [2, 1], [-2, 1], [1, -2], [-1, -2], [2, -1], [-2, -1]]}
]
}Créons une dataclass pour la configuration:
# spiral.py
@dataclass
class Config:
n_layers: int
players: list[Player]
@classmethod
def from_json(cls, path: pathlib.Path):
with path.open("r", encoding="utf-8") as fp:
data = json.load(fp)
if not ("n_layers" in data and "players" in data):
raise ValueError("Config: missing n_layers or players")
players = [Player.from_dict(p) for p in data['players']]
return cls(int(data['n_layers']), players)En modifiant Player pour pouvoir aussi être créé
à partir d’un dictionnaire:
# player.py
@dataclass
class Player:
# ...
@classmethod
def from_dict(cls, data: dict):
if not ("color" in data and "offsets" in data):
raise ValueError("Player: missing color or offsets")
return cls(str(data["color"]), [(int(offset[0]), int(offset[1])) for offset in data['offsets']])Le main, enfin, va lire le fichier JSON passé en
paramètre de l’appel au programme, ou fourni par l’utilisateur
via un input:
# spiral.py
if __name__ == "__main__":
if len(sys.argv) >= 2:
path = pathlib.Path(sys.argv[1])
else:
path = pathlib.Path(input("Path to config file: "))
config = Config.from_json(path)
board = Board(config.n_layers, config.players)
show_board(board, save_as=pathlib.Path(str(path).replace('.json', '.png')))Si on lance python spiral.py two_knights.json
(avec bien sûr la configuration ci-dessus dans
two_knights.json!), on obtient bien notre
figure:
Parfait. Voyons ce qu’on peut faire de plus.
Visualisations
Prenons notre configuration à quatre cavaliers, et remplaçons deux des cavaliers par des “super-cavaliers”, capable d’aller deux fois plus loin. Donc, au lieu de (1, 2), ils ont un offset de (2, 4), etc:
Un cavalier, un super-cavalier, et un super-super-cavalier, avec un offset (3, 6):
Un cavalier, un super-cavalier, et un “vizir” (offsets en “croix” (1, 0), (0, 1), (-1, 0), (0, -1)):
Jusqu’à présent, nous n’avons fait que des pièces “symétriques”, mais rien ne nous empêche de définir des pattern plus arbitraires pour les déplacements des pièces. Prenons la configuration suivante:
{
"n_layers": 500,
"players": [
{"color": "r", "offsets": [[-1, -1], [-1, 1], [1, 2], [2, 1], [1, -2], [2, -1]]},
{"color": "k", "offsets": [[1, -1], [1, 1], [-1, 2], [-2, 1], [-1, -2], [-2, -1]]},
{"color": "y", "offsets": [[1, 0], [-1, 0], [0, 2], [0, -3]]}
]
}On a une pièce qui va plus loin à droite que à gauche, une autre qui va plus loin à gauche que à droite, et une dernière qui avance plus loin en vertical qu’en horizontal. Le résultat:
Je pense qu’on peut dire que l’expérience est réussie !
Aller, un dernier pour la route, faisons se batailler les sept cavaliers de l’arc-en-ciel sur une spirale à 1000 couches:
{
"n_layers": 1000,
"players": [
{"color": "red", "offsets": [[1, 2], [-1, 2], [2, 1], [-2, 1], [1, -2], [-1, -2], [2, -1], [-2, -1]]},
{"color": "orange", "offsets": [[1, 2], [-1, 2], [2, 1], [-2, 1], [1, -2], [-1, -2], [2, -1], [-2, -1]]},
{"color": "yellow", "offsets": [[1, 2], [-1, 2], [2, 1], [-2, 1], [1, -2], [-1, -2], [2, -1], [-2, -1]]},
{"color": "green", "offsets": [[1, 2], [-1, 2], [2, 1], [-2, 1], [1, -2], [-1, -2], [2, -1], [-2, -1]]},
{"color": "cyan", "offsets": [[1, 2], [-1, 2], [2, 1], [-2, 1], [1, -2], [-1, -2], [2, -1], [-2, -1]]},
{"color": "blue", "offsets": [[1, 2], [-1, 2], [2, 1], [-2, 1], [1, -2], [-1, -2], [2, -1], [-2, -1]]},
{"color": "violet", "offsets": [[1, 2], [-1, 2], [2, 1], [-2, 1], [1, -2], [-1, -2], [2, -1], [-2, -1]]}
]
}
Bon, ça met quelques minutes à tourner et je ne pense pas qu’on me demandera de designer le drapeau de la prochaine Pride… mais ça marche.