[PYTHON] Programmation graphique

Écrivons un programme avec une image

Écrivez l'image suivante (picntu.png).

image

Vous pouvez analyser et exécuter cette image. Le côté supérieur est la zone de stockage des pièces. Exécutez le côté inférieur. Allez de haut à gauche et descendez. Comme Python, les retraits représentent des blocs. Comme les graphiques de tortues, il est d'abord aux coordonnées (x = 0, y = 0) et fait face au nord. Vous pouvez le déplacer avec une commande.

Exécuter un échantillon

bash


docker run -it --rm tsutomu7/picntu ./picntu picntu.png
>>>
0 0
0 2
2 2
2 0

Description de la pièce

--go: Faites un pas. (D'abord à (0, 0).) --back: Recule d'une étape. --gauche: tourner vers la gauche. (Première face au nord.) --droite: tourner vers la droite. --def Number: définit un sous-programme numérique. La portée de la définition est déterminée par le tiret. --run Number: Exécute un sous-programme numérique. --lop Number: Répéter pour le numéro. La plage de répétition est déterminée par l'indentation. --pri Number: génère un nombre. --if = Number: détermine si le nombre est égal à la valeur en mémoire. La plage est déterminée par le retrait. --if <nombre: détermine si le nombre dépasse la valeur en mémoire. --if> Number: détermine si le nombre est inférieur à la valeur de la mémoire. --set Number: définit le numéro en mémoire. --add Number: ajoute un numéro à la mémoire. --sub Number: soustrait le nombre de la mémoire. --Si vous laissez le nombre vide, la valeur de la mémoire sera utilisée. Vous ne pouvez avoir qu'un seul numéro en mémoire.

  • Les nombres vont de 0 à 9 et 10 revient à 0. ――Les littéraux suivants peuvent être utilisés à la place des nombres.

littéral

--Nombre: les nombres vont de 0 à 9, 10 revenant à 0. --i, j: compteur de lop. La première boucle est i et la deuxième boucle est j. --x, y: représente les coordonnées. --r: indique l'orientation. Nord = 0, Est = 1. Sud = 2, Ouest = 3.

Exemple de description

échantillon


def 0 | pri x | pri y
lop 4 | run 0
      | lop 2 | go
      | right

La description

  • Ce qui suit est le sous-programme 0
  • Sortie x et y
  • Répétez les 4 fois suivantes --Appeler le sous-programme 0 ――Deux fois en avant (2 pas en avant)
  • Regarde à droite

Exécuter n'importe quelle image

Si vous placez le fichier image dans / tmp, vous pouvez l'exécuter comme suit. Vous pouvez changer la taille de l'image, mais ne changez pas la position des pièces.

bash


docker run -it --rm -v /tmp:/tmp tsutomu7/picntu ./picntu /tmp/Nom du fichier image

Si vous spécifiez un deuxième argument, vous pouvez voir le python créé à partir de l'image.

bash


docker run -it --rm tsutomu7/picntu ./picntu picntu.png 0
>>>
i, j, x, y, r, c = 0, 0, 0, 0, 0, 0
dx, dy = [0, 1, 0, 9], [1, 0, 9, 0]
def f0():
    print("\n%d" % x, end="");print(" %d" % y, end="");
for i in range(4):
    f0();
    for j in range(2):
        globals()["x"], globals()["y"] = (x + dx[r]) % 10, (y + dy[r]) % 10;
    globals()["r"] = (r + 1) % 4;

0 0
0 2
2 2
2 0

Exécuter dans le navigateur

Faites ce qui suit, spécifiez le fichier et appuyez sur "Exécuter".

bash


docker run -it -d -p 5000:5000 tsutomu7/picntu
firefox localhost:5000

image

Programme d'analyse

picntu.py


import cv2, sys, unionfind

if len(sys.argv) <= 1:
    print('%s image_file' % sys.argv[0][:-3])
    exit()
im = cv2.imread(sys.argv[1])
imtop = im[5:13, 4:86] # top of card
r1 = cv2.matchTemplate(im[160:], imtop, cv2.TM_CCOEFF_NORMED)
scom = 'go back lop if_eq set ' \
       'left right else if_lt add ' \
       'def run pri if_gt sub'.split()
slit = '0 1 i 2 3 j 4 5 x 6 7 y 8 9 r'.split()
coms = [] # command list
for y, x in [(i, j) for i, p in enumerate(r1 >= 0.999)
                    for j, q in enumerate(p) if q]:
    imcom = im[y+173:y+197,x+9:x+49]
    r2 = cv2.matchTemplate(im[:150,:460], imcom, cv2.TM_CCOEFF_NORMED)
    _, v, _, (x2, y2) = cv2.minMaxLoc(r2)
    if v < 0.999:
        continue
    i = (x2+33)//92 + (y2+8)//52*5
    arg = 'c'
    if i > 7 or (i+1)%6 > 2:
        r3 = cv2.matchTemplate(im[9:147,465:545], im[y+173:y+193,x+53:x+70],
                               cv2.TM_CCOEFF_NORMED)
        _, v, _, (x3, y3) = cv2.minMaxLoc(r3)
        if v >= 0.999:
            arg = slit[(x3+8)//26 + (y3+7)//25*3]
    coms.append([-1, -1, scom[i], arg, x, y])

n = len(coms)
ux = unionfind.unionfind(n)
uy = unionfind.unionfind(n)
for i in range(n):
    coi = coms[i]
    for j in range(i+1, n):
        coj = coms[j]
        if abs(coi[4] - coj[4]) < 12:
            ux.unite(i, j)
        if abs(coi[5] - coj[5]) < 12:
            uy.unite(i, j)
for i, g in enumerate(sorted(ux.groups(), key=lambda g: coms[g[0]][4])):
    for j in g:
        coms[j][1] = i
for i, g in enumerate(sorted(uy.groups(), key=lambda g: coms[g[0]][5])):
    for j in g:
        coms[j][0] = i

ex = []
ex.append('i, j, x, y, r, c = 0, 0, 0, 0, 0, 0\n')
ex.append('dx, dy = [0, 1, 0, 9], [1, 0, 9, 0]\n')
pr, s, lp = 0, ' ', []
for v, t, com, a, _, _ in sorted(coms):
    if v > pr or s[-1] == ':':
        ex.append('\n' + '    '*t)
    if com == 'go':
        s = 'globals()["x"], globals()["y"] = (x + dx[r]) % 10, (y + dy[r]) % 10;'
    elif com == 'back':
        s = 'globals()["x"], globals()["y"] = (x + dx[(r + 2) % 4]) % 10, (y + dy[(r + 2) % 4]) % 10;'
    elif com == 'left':
        s = 'globals()["r"] = (r + 3) % 4;'
    elif com == 'right':
        s = 'globals()["r"] = (r + 1) % 4;'
    elif com == 'def':
        s = 'def f%s():' % a
    elif com == 'run':
        s = 'f%s();' % a
    elif com == 'lop':
        while lp and lp[-1] >= t:
            lp.pop()
        s = 'for %s in range(%s):' % ('ijklmn'[len(lp)], a)
        lp.append(t)
    elif com == 'else':
        s = 'else:'
    elif com == 'pri':
        s = 'print("%s%%d" %% %s, end="");' % (' ' if v == pr and s[0] == 'p' else '\\n', a)
    elif com == 'if_eq':
        s = 'if c == %s:' % a
    elif com == 'if_lt':
        s = 'if c < %s:' % a
    elif com == 'if_gt':
        s = 'if c > %s:' % a
    elif com == 'set':
        s = 'globals()["c"] = %s;' % a
    elif com == 'add':
        s = 'globals()["c"] += %s;' % a
    elif com == 'sub':
        s = 'globals()["c"] -= %s;' % a
    ex.append(s)
    pr = v
if len(sys.argv) > 2:
    print(''.join(ex))
exec(''.join(ex))
print()

référence: Jouer avec une tortue avec des graphiques de tortue (Partie 1) «Cubetto» où même les enfants de 3 ans peuvent apprendre la programmation avec des jouets