<jupyter_start><jupyter_text>Phase 2 - Créer des jeux Pour vérifier si votre code Python adhère aux recomendations PEP8 allez sur ce site: http://pep8online.com/  Utiliser le notebook JupyterLes cellules code dans un notebook Jupyter doivent être executable. Si vous voulez simplement montrer un bout de code pour en parler sans l'executer, placez-le entre triple-backquotes.```bout de code (exemple)```Toutes les cellules code doivent être executable et produire un résultat :* Pour executer une cellule appuyez sur `SHIFT-Return`* Avant de créer un PDF, recalculez toutes les cellules code* Choisissez le menu `Kernel > Restart & Run all`* Ceci renumérote automatiquement toutes les cellules à partir de 1* Si une variables ou fonctions ne sont pas définis, vous en êtes avertit* Selon la langue du système (Raspberry Pi settings), l'étiquette `In` ou `Entrée` est affichée<jupyter_code>from sense_hat import SenseHat
from gamelib import *
from random import randint, choice
from time import time, sleep
import numpy as np

sense = SenseHat()
sense.clear()<jupyter_output>module name = gamelib<jupyter_text>Le module `gamelib` contient les couleurs.<jupyter_code>colors = [BLACK, RED, GREEN, YELLOW, BLUE, CYAN, MAGENTA]<jupyter_output><empty_output><jupyter_text>Variables gobalesNous déclarons quelques variables commes globales. Ces variables seront accessible depuis partout dans Python.<jupyter_code>x, y = 0, 0    # cursor position
n = 8          # board size (n x n)
T = np.zeros((n, n), int)    # Matrix of the board (table)
colors = (BLACK, RED, GREEN, BLUE)  # color list
p = 1          # current player
score = [0, 0] # current score<jupyter_output><empty_output><jupyter_text>Le module NumPyPour cette deuxième phase, nous allons remplacer les matrices (listes 2D Python) par des matrices 2D NumPy. Voici les avantages:* les calculs sont beaucoup plus rapide* la matrice 2D peut être affiché avec `print` * il existent beaucoup de fonctions* Utiliser le module NumPy pour le calcul matriciel. C'est standard d'importer le module **NumPy** avec le raccourci `np`.<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>La fonction `np.array()` transforme une liste Python en matrice NumPy.<jupyter_code>L = np.array([[0, 1], [1, 1]])<jupyter_output><empty_output><jupyter_text>Regardons le type de cet objet. C'est un `numpy.ndarray` (numerical data array).<jupyter_code>type(L)<jupyter_output><empty_output><jupyter_text>Une matrice 2D peut être affiché avec `print`.<jupyter_code>print(L)<jupyter_output>[[0 1]
 [1 1]]<jupyter_text>Créer des matricesIl existent des fonctions pour créer des matrices<jupyter_code>A = np.zeros((8, 8), int)
A
B = np.ones((3, 8), int)
B
print(L*2)<jupyter_output>[[0 2]
 [2 2]]<jupyter_text>Afficher une matrice sur senshathttps://docs.scipy.org/doc/numpy/reference/generated/numpy.random.randint.html<jupyter_code>m = len(colors)
R = np.random.randint(0, m-1, (8, 8))
R<jupyter_output><empty_output><jupyter_text>Afficher sur le SenseHATPour afficher sur les LEDs du SenseHAT nous utilisons une matrice avec des entiers. Cest entiers sont également l'indice pour la liste `colors`<jupyter_code>def show_matrix(M):
    global colors
    n, m = M.shape
    for x in range(n):
        for y in range(m):
            col = colors[M[y, x]] # lines & columns are inversed
            sense.set_pixel(x, y, col)
show_matrix(R)
def show_cursor(x, y, p):
    """Show cursor for player p (1, 2)."""
    sense.set_pixel(x, y, colors[p])
show_cursor(x, y, p)<jupyter_output><empty_output><jupyter_text>Indices Dans une matrice 2D nous utilisons les indices i, j. D'habitude on utilise i pour les lignes et j pour les colonnes. Donc les indices sont invertit:* i correspond à l'axe y* j correspond à l'axe x<jupyter_code>T[1, 4] = 3
T
T[2:4, 2:4] = L * 3
T<jupyter_output><empty_output><jupyter_text>Fonctions callbackDes fonctions peuvent être associé aux 5 directions du joystick. Les fonctions prennent comme argument l'événement `event`.* direction_left* direction_right* direction_up* direction_down* direction_middle* direction_anySi vous êtes intéressés dans les détails, ces fonctions utilisent un mécanismes qu'on appelle des **threads**. Vous pouvez aller regarder le code source de l'API sur GitHub:https://github.com/RPi-Distro/python-sense-hat/blob/master/sense_hat/stick.py<jupyter_code># dir(sense.stick)
def right(event):
    """Make display red."""
    sense.clear(RED)

def left(event):
    """Make display blue."""
    sense.clear(BLUE)
    
def up(event):
    """Make display green."""
    sense.clear(GREEN)

def down(event):
    """Make display yellow."""
    sense.clear(YELLOW)
    
def middle(event):
    """Clear display."""
    sense.clear()
    
sense.stick.direction_left = left
sense.stick.direction_right = right
sense.stick.direction_up = up
sense.stick.direction_down = down
sense.stick.direction_middle = middle<jupyter_output><empty_output><jupyter_text>ExerciceRedéfinir les fonctions `up` et `down` pour incrementer ou décrémenter un nombre qui change de couleur selon l'index dans `colors`.<jupyter_code>i = 0

def up(event):
    global i, n
    if event.action == 'pressed':
        i = (i+1) % len(colors)
        sense.show_letter(str(i), text_colour=colors[i])

def middle(event):
    pass

def down(event):
    global i, n
    if event.action == 'pressed':
        i = (i-1) % len(colors)
        sense.show_letter(str(i), text_colour=colors[i])<jupyter_output><empty_output><jupyter_text>Trouver des info sur une fonction callbackVerifier si une fonction callback et définie.<jupyter_code>print(sense.stick.direction_left)<jupyter_output><function left at 0x6ffa1e40><jupyter_text>Afficher le docstring de cette fonction.<jupyter_code>print(sense.stick.direction_left.__doc__)<jupyter_output>Make display blue.<jupyter_text>Afficher le nom de cette fonction.<jupyter_code>print(sense.stick.direction_left.__name__)
callbacks = (sense.stick.direction_up, sense.stick.direction_down, 
             sense.stick.direction_left, sense.stick.direction_right,
             sense.stick.direction_middle, sense.stick.direction_any)

for cb in callbacks:
    if cb != None:
        print(cb.__name__, cb.__doc__, sep='\t')<jupyter_output>up	Make display green.
down	Make display yellow.
left	Make display blue.
right	Make display red.
middle	Clear display.<jupyter_text>Déplacer un curseurBeaucoup de jeux necessitent le déplacement d'un curseur. Nous utilisons les 4 directions pour déplacer le curseur, et le boutons central pour faire la sélection.<jupyter_code>def move_cursor(event):
    """Deplace le curseur (x, y) sur un board (n x n)."""
    global x, y, n
    if event.direction == 'left':
        x = max(x-1, 0)
    elif event.direction == 'up':
        y = max(y-1, 0)
    elif event.direction == 'right':
        x = min(x+1, n-1)
    elif event.direction == 'down':
        y = min(y+1, n-1)
        
def play(event):
    if event.action == 'pressed':
        move_cursor(event)
        sense.clear()
        show_cursor(x, y, 1)

sense.stick.__init__()
sense.stick.direction_any = play<jupyter_output><empty_output><jupyter_text>En posant $n=3$ nous pouvons restreindre le mouvement du curseur à une région 3x3.<jupyter_code>n=3<jupyter_output><empty_output><jupyter_text>Afficher le gagnantAprès chaque match nous affichons le gagnant (1 ou 2) dans sa couleur. Si c'est match nul nous affichons 0 en blanc.Pour donner d'importance, nous flashons 3 fois.<jupyter_code>def show_winner(p, n=3):
    """Show the winner (1, 2) in the player's color."""
    col = WHITE if p==0 else colors[p]
    for i in range(3):
        sense.show_letter(str(p), text_colour=col)
        sleep(0.2)
        sense.clear()
        sleep(0.2)
    
for i in range(3):
    show_winner(i)<jupyter_output><empty_output><jupyter_text>Afficher le scoreAprès chaque match nous affichons le score des deux jouer, ou le score simple.<jupyter_code>def show_score():
    """Display the score as scrolling text."""
    text = str(score[0]) + ':' + str(score[1])
    sense.show_message(text)

score = [2, 3]
show_score()<jupyter_output><empty_output><jupyter_text>Si le score est entre 0 et 9 on peut l'afficher comme lettre, un après l'autre, dans la couleur respective du joueur.<jupyter_code>def show_score2():
    """Display score as two numbers in different colors."""
    for i in range(2):
        sense.show_letter(str(score[i]),text_colour=colors[i+1])
        sleep(1)
    sense.clear()

show_score2()<jupyter_output><empty_output><jupyter_text>Si le score est entre 0 et 8 on peut aussi l'afficher de façon graphique avec une barre.<jupyter_code>def show_score3():
    """Display score as two colored bars."""
    M = np.zeros((8, 8), int)
    M[0:score[0], 3] = 1
    M[0:score[1], 4] = 2
    show_matrix(M)
    sleep(1)
    
show_score3()<jupyter_output><empty_output><jupyter_text>Cellules conséqutifs identiquesDans Morpion et Puissance 4 nous devons tester si une séquence de 3 ou 4 cellules sont identiques. Nous définissons une fonctions qui compare 3 ou 4 cellules à partir d'une position initiale et une direction.<jupyter_code>def is_equal(T, x, y, dx, dy, p, n):
    """Check if n cells starting at (x, y), 
    in direction (dx, dy) are all equal to p"""
    for i in range(n):
        if T[y, x] != p:
            return False
        x += dx
        y += dy
        
    return True<jupyter_output><empty_output><jupyter_text>Testons notre function dans les 4 directions.<jupyter_code>T = np.zeros((8, 8), int)
T[1:5, 3] = 1
T[7, 4:8] = 2
T[2, 0] = T[3, 1] = T[4, 2] = T[5, 3] = 3
T
print(is_equal(T, 3, 1, 0, 1, 1, 4))
print(is_equal(T, 4, 7, 1, 0, 2, 4))
print(is_equal(T, 0, 2, 1, 1, 3, 4))
def in_a_row(T, p, k):
    """Check if player p has k stones in a row."""
    n, m = T.shape
    # columns
    for x in range(m):
        for y in range(n-k+1):
            if is_equal(T, x, y, 0, 1, p, k):
                return True
    # lines
    for y in range(n):
        for x in range(m-k+1):
            if is_equal(T, x, y, 1, 0, p, k):
                return True
    # diagonals
    for y in range(n-k+1):
        for x in range(m-k+1):
            if  is_equal(T, x, y, 1, 1, p, k):
                return True
            if  is_equal(T, x+k-1, y, -1, 1, p, k):
                return True
    return False
T = np.array([[1, 2, 2], [2, 2, 1], [1, 2, 1]])
print(T)
print(in_a_row(T, 2, 3))<jupyter_output>[[1 2 2]
 [2 2 1]
 [1 2 1]]
True<jupyter_text>Fin du jeuLe jeu est terminé quand toutes les places sont occupées. La méthode `all()` est vrai si toutes les éléments sont différent de 0.<jupyter_code>def is_finished(T):
    """Returns True if all cells are occupied."""
    return T.all()<jupyter_output><empty_output><jupyter_text>On va tester la fonction avec deux cas.<jupyter_code>T = np.ones((3, 3), int)
is_finished(T)
T[0, 0] = 0
is_finished(T)<jupyter_output><empty_output><jupyter_text>MorpionDans le jeu morpion les joueurs dovent placer en alternance une pièce sur un plateau de 3x3 cellules. Celui qui a placé en premier 3 pièces sur une ligne, colonne ou diagonale gagne.<jupyter_code>n = 3
T = np.zeros((n, n), int)
print(T)<jupyter_output>[[0 0 0]
 [0 0 0]
 [0 0 0]]<jupyter_text>La fonction `init` prépare le jeu.<jupyter_code>def init(reset=False):
    global x, y, p, n, score, colors, T
    x, y = 1, 1
    n = 3
    T = np.zeros((n, n), int)
    colors = [BLACK, BLUE, YELLOW]
    if reset:
        score = [0, 0]
        p = 1
    show_board()
    show_cursor3()<jupyter_output><empty_output><jupyter_text>La fonction `show_board` affiche le tableau.<jupyter_code>def show_board():
    """Show a 3x3 matrix on the 8x8 board."""
    for x in range(8):
        for y in range(8):
            if x % 3 == 2 or y % 3 == 2:
                sense.set_pixel(x, y, GRAY)
            else:
                val = T[y//3, x//3]
                sense.set_pixel(x, y, colors[val])
def show_cursor3():
    """Scale the cursor from 3x3 matrix to 8x8 board."""
    global x, y, p
    col = colors[p] if T[y, x] != p else BLACK
    sense.set_pixel(3*x, 3*y, col)<jupyter_output><empty_output><jupyter_text>The following implements the `play` function.<jupyter_code>def play(event):
    """Place a stone on the board if the position is empty."""
    global x, y, p
    if event.action == 'pressed':
        move_cursor(event)
        if event.direction == 'middle':
            if T[y, x] == 0:
                T[y, x] = p
                if in_a_row(T, p, 3):
                    show_winner(p)
                    score[p-1] += 1
                    show_score3()
                    init()
                elif is_finished(T):
                    show_winner(0)
                    show_score3()
                    init()
                p = 3 - p
        show_board()
        show_cursor3()

sense.stick.__init__()
sense.stick.direction_any = play
init(True)<jupyter_output><empty_output><jupyter_text>m, n, k gameLe m, n, k game est joué sur un tableau m x n, par deux joueurs qui placent une pièce en alternance. Le but est de placer k pièces en ligne, colonne ou en diagonale.https://en.wikipedia.org/wiki/M,n,k-game<jupyter_code>def init(reset=False, size=8):
    global x, y, p, n, score, T
    n = size
    T = np.zeros((n, n), int)
    x, y = 0, 0
    if reset:
        score = [0, 0]
        p = 1
    show_matrix(T)
    show_cursor(x, y, p)
def play(event):
    """Use 4 directions keys to move cursor, middle to play."""
    global x, y, p
    if event.action == 'pressed':
        move_cursor(event)
        if event.direction == 'middle':
            if T[y, x] == 0:
                T[y, x] = p
                if is_finished(T):
                    show_winner(0)
                    show_score3()
                elif in_a_row(T, p, 4):
                    show_winner(p)
                    score[p-1] += 1
                    show_score3()
                    init()
                p = 3 - p
                
        show_matrix(T)
        show_cursor(x, y, p)

sense.stick.__init__()
sense.stick.direction_any = play
init(True)<jupyter_output><empty_output><jupyter_text>Puissance 4Le but du jeu est d'aligner une suite de 4 pions de même couleur sur une grille comptant 7 rangées et 8 colonnes.Tour à tour les deux joueurs placent un pion dans la colonne de leur choix, le pion coulisse alors jusqu'à la position la plus basse possible dans la dite colonne à la suite de quoi c'est à l'adversaire de jouer. Le vainqueur est le joueur qui réalise le premier un alignement (horizontal, vertical ou diagonal) consécutif d'au moins quatre pions de sa couleur. Si, alors que toutes les cases de la grille de jeu sont remplies, aucun des deux joueurs n'a réalisé un tel alignement, la partie est déclarée nulle.<jupyter_code>def init(reset=False):
    """Initialize global parameters for Connect4."""
    global x, y, p, dt, colors, T
    x, y = 3, 0
    if reset:
        score = [0, 0]
        p = 1
    dt = 0.2
    colors = [BLUE, RED, YELLOW, BLACK]
    T = np.zeros((8, 8), int)
    T[0] = 3

    show_matrix(T)
    show_cursor(x, y, p)
init()
T<jupyter_output><empty_output><jupyter_text>Ceci sont les fonctions pour le jeu Puissance 4.<jupyter_code>def show(event):
    if event.action == 'pressed':
        show_matrix(T)
        show_cursor(x, y, p)

def left(event):
    """Move cursor to the left."""
    global x
    if event.action == 'pressed':
        x = max(x-1, 0)
    
def right(event):
    """Move cursor to the right."""
    global x
    if event.action == 'pressed':
        x = min(x+1, 7)
    
def down(event):
    """Move disc downwards."""
    global x, y, p
    if event.action == 'pressed':
        while (y < 7 and T[y+1, x] == 0):
            y += 1
            show_matrix(T)
            show_cursor(x, y, p)
            sleep(.1)
        T[y, x] = p
        if in_a_row(T[1:], p, 4):
            show_winner(p)
            show_score3()
            init()
        elif is_finished(T):
            show_winner(0)
            show_scores3()
            init()
            
        y = 0
        p = 3 - p
    
sense.stick.__init__()
sense.stick.direction_left = left
sense.stick.direction_right = right
sense.stick.direction_down = down
sense.stick.direction_up = init
sense.stick.direction_middle = show_score()
sense.stick.direction_any = show
init()<jupyter_output><empty_output><jupyter_text>TetrisDéfinissons les formes des base: L, O, I.<jupyter_code>L = np.array([[1, 0], [1, 1]], int)
print(L)
O = np.ones((2, 2), int)
print(O)
I = np.ones((3, 1), int)
print(I)<jupyter_output>[[1]
 [1]
 [1]]<jupyter_text>Rotation des matrices<jupyter_code>np.rot90(L)
np.rot90(L, 2)
np.rot90(L, 3)
np.rot90(I)<jupyter_output><empty_output><jupyter_text>Check if space is empty<jupyter_code>def overlap(T, S, x, y):
    pass<jupyter_output><empty_output><jupyter_text>Add a shape<jupyter_code>def add(T, S, x, y):
    """Add shape S to T at (x, y)."""
    n, m = S.shape
    T[y:y+n, x:x+m] = S
add(T, L, 0, 0)
add(T, O*2, 5, 0)
add(T, L*3, 6, 0)
print(T)
show_matrix(T)
show_matrix(T)
def rem(T, S, x, y):
    """Remove shape S at (x, y)."""
    n, m = S.shape
    for i in range(n):
        for j in range(m):
            T[y+i, x+j] = 0
rem(T, O, 0, 0)
add(T, O, 1, 0)
show_matrix(T)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11936063010366595, 'fraction_numerical': 0.018590374703191057, 'mean_word_length': 3.213762811127379, 'pattern_counts': {'":': 0, '<': 142, '<?xml version=': 0, '>': 142, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '37', 'dir': 'jupyter-structured-clean-dedup', 'id': '129599', 'license': 'MIT', 'n_tokens_mistral': 6447, 'n_tokens_neox': 6169, 'n_words': 1889, 'path': 'games/xxy/Games2.ipynb', 'repo_name': 'Bugnon/oc-2018', 'size': '17267'}