π
<-

Un démineur en python pour la NumWorks

Re: Un démineur en python pour la NumWorks

Unread postby Arthur Jacquin » 07 Mar 2020, 21:11

Bonjour,

Voici ma version du démineur : https://workshop.numworks.com/python/ar ... n/demineur

Cette version est destinée à l’entretien et à la compréhension du code, donc elle est un peu lourde (6ko) et ne fonctionne que sur Omega. Le script peut donc aisément être réduit, ne serait que par la suppression des commentaires et de la documentation interne au code, mais j'attends l'ajout des dernières fonctionnalités avant de l'optimiser.

Deux fonctionnalités non présentes sur la version de @cent20 :
- impossible de perdre sur le premier clic,
- possibilité de relancer une partie facilement.

Des idées d'améliorations :
- modification du critère de victoire (actuellement pas parfait),
- affichages de toutes les bombes lors d'un échec,
- une fonction qui révèle toutes les cases mitoyennes non découvertes si l'on clique sur un chiffre (évite les clics répétitifs).

Vos commentaires/critiques sont bienvenus.

Code: Select all
# Démineur - Mars 2020
# Arthur Jacquin - arthur062318@gmail.com




# Commentaires

"""   Touches

Naviguation : flèches
Révéler une case : OK
Placer un drapeau : Flèche retour
Quitter : Accueil + spam Flèche retour
"""

"""   Valeurs des cases de la matrice

|        Contexte        | Bombe |                 Non bombe                  |
|     Non découvert      |   9   |    0 à 8 (nombre de bombes adjacentes)     |
|       Découvert        |  19   | 10 à 18 (nombre de bombes adjacentes + 10) |
| Couvert par un drapeau |  29   | 20 à 28 (nombre de bombes adjacentes + 20) |
"""

"""    Améliorations possibles

Gestion des variables
Critère de réussite
Fonction qui découvre toutes les cases non découvertes à côté si chiffre cliqué
Affichage des bombes lors d'un échec
"""

"""    Archives de dévellopement

def aff():
    to_print = ""
    for y in Yset:
        for x in Xset: to_print += ("  "+str(MAT[y][x]))[-3:]
        to_print += "\n"
    print(to_print)
"""




# Initialisation

# Modules
from kandinsky import set_pixel, draw_string, fill_rect
from random import choice
from ion import keydown

# Couleurs
imp = (0,0,0) # Titre, curseur, contenu
grey = (70,70,70) # Texte, bordures
light = (220,220,220) # Inconnus
none = (255,255,255) # Vide, background
curs = (0,0,255) # Curseur

# Paramètres et outils
Xdomain = range(16)
Ydomain = range(10)
mines = 20
prox = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]]
buttons = [0,1,2,3,4,5,6,52]




# Fonctions graphiques

def mine(x,y,b,a):
    fill_rect(x+2,y+2,9,9,b)
    fill_rect(x,y+6,13,1,b)
    fill_rect(x+6,y,1,13,b)
    fill_rect(x+4,y+4,2,2,(255,255,255))
    for p in [[9,2],[10,3],[10,9],[9,10],[3,10],[2,9],[2,3],[3,2]]:
        set_pixel(x+p[0],y+p[1],a)

def top():
    fill_rect(0,0,320,20,none)
    if etat == "MINESWEEPER":
        draw_string("Arthur J.",5,2,grey)
        draw_string(etat,105,2,imp)
        draw_string((" "+str(compteur)+"/20")[-5:],265,2,grey)
        mine(249,4,grey,none)
    else:
        if etat == "YOU WON !": draw_string(etat,28,2,(0,153,0))
        else: draw_string(etat,23,2,(255,0,0))
        draw_string("EXE to PLAY AGAIN",145,2,grey)

def case(X,Y):
    value = MAT[Y][X]
    x, y = 20*X, 20*Y + 22
    fill_rect(x,y,20,20,grey) # Bordures
    fill_rect(x+1,y+1,18,18,none) # Vide
    if value < 10: fill_rect(x+1,y+1,18,18,light) # Inconnu
    elif value in range(11,19): draw_string(str(value-10),x+5,y+1,imp) # Valeur
    elif value == 19:
        fill_rect(x+1,y+1,18,18,(255,0,0))
        mine(x+4,y+4,imp,(255,0,0)) # Bombe
    elif value > 19: # Drapeau
        fill_rect(x+1,y+1,18,18,light)
        fill_rect(x+10,y+8,2,6,imp)
        fill_rect(x+6,y+14,8,2,imp)
        fill_rect(x+6,y+4,6,4,(0,153,0))
    if cursor == [X,Y]:
        fill_rect(x,y,20,3,curs)
        fill_rect(x,y,3,20,curs)
        fill_rect(x,y+17,20,3,curs)
        fill_rect(x+17,y,3,20,curs)




# Fonctionnement

def key():
    key = -1
    while key == -1:
        for k in buttons:
            if keydown(k): key = k
    while keydown(key): True
    return key

def search(old): # Recherche des cases adjacentes vides
    new = []
    for i in old:
        for p in prox:
            tX, tY = i[0]+p[0], i[1]+p[1]
            if tX in Xdomain and tY in Ydomain:
                if MAT[tY][tX] == 0: new.append([tX,tY])
                MAT[tY][tX] = (MAT[tY][tX])%10 + 10
                case(tX,tY)
    if new != []: search(new)




# Boucle principale

def play():
    # Initialisation
    global compteur, cursor, etat, cases, MAT
    compteur = mines # Décompte apparent du nombre de bombes restant
    decouv = 0 # Nombres réel de bombes déduites
    cursor = [8,5] # Coordonnées du curseur
    etat = "MINESWEEPER" # Etat de la partie
    MAT = [[0]*len(Xdomain)]*len(Ydomain) # Génération d'une matrice blanche
   
    # Dessin de l'interface
    top()
    fill_rect(0,21,320,1,grey)
    for Y in Ydomain:
        for X in Xdomain: case(X,Y)
   
    # Boucle principale
   
    while True:
        X, Y = cursor[0], cursor[1]
        result = key()
        if result < 4:
            if result==0 and cursor[0]-1 in Xdomain: cursor[0] -= 1
            elif result==1 and cursor[1]-1 in Ydomain: cursor[1] -= 1
            elif result==2 and cursor[1]+1 in Ydomain: cursor[1] += 1
            elif result==3 and cursor[0]+1 in Xdomain: cursor[0] += 1
            case(X,Y)
            case(cursor[0],cursor[1])
        elif result == 4:
            if MAT == [[0]*len(Xdomain)]*len(Ydomain):
                bombes = []
                for i in range(mines):
                    x, y = choice(Xdomain), choice(Ydomain)
                    while (x,y) in bombes or (x,y) == (X,Y):
                        x, y = choice(Xdomain), choice(Ydomain)
                    bombes.append((x,y))
                MAT = []
                for y in Ydomain:
                    column = []
                    for x in Xdomain:
                        if (x,y) in bombes: column.append(9)
                        else: column.append(sum([1*((x+t[0],y+t[1]) in bombes) for t in prox]))
                    MAT.append(column)
                for Y in Ydomain:
                    for X in Xdomain: case(X,Y)
                X, Y = cursor[0], cursor[1]
            if MAT[Y][X] > 19:
                compteur += 1
                draw_string((" "+str(compteur))[-2:],265,2,grey)
            MAT[Y][X] = (MAT[Y][X])%10 + 10
            case(X,Y)
            if MAT[Y][X] == 10: search([[X,Y]])
            elif MAT[Y][X] == 19:
                etat = "YOU LOSE !"
                break
        elif result == 5:
            if MAT[Y][X] < 20:
                compteur -= 1
                draw_string((" "+str(compteur))[-2:],265,2,grey)
            if MAT[Y][X] == 9: decouv += 1
            MAT[Y][X] = (MAT[Y][X])%10 + 20
            case(X,Y)
        elif result == 6: break
        if compteur == 0 and decouv == 20:
            etat = "YOU WON !"
            break
    top()
    result = -1
    while True:
        if result == 52: play()
        elif result == 6: break
        else: result = key()

play()
User avatar
Arthur Jacquin
Niveau 4: MC (Membre Confirmé)
Niveau 4: MC (Membre Confirmé)
Level up: 56%
 
Posts: 14
Joined: 07 Mar 2020, 21:05
Gender: Not specified
Calculator(s):
MyCalcs profile
Class: MP* Lazaristes
GitHub: arthur-jacquin

Re: Un démineur en python pour la NumWorks

Unread postby critor » 07 Mar 2020, 21:17

Merci bien pour ton travail pertinent là-dessus. :)
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 47.5%
 
Posts: 41976
Images: 15737
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
MyCalcs profile
YouTube: critor3000
Twitter: critor2000
GitHub: critor

Re: Un démineur en python pour la NumWorks

Unread postby cent20 » 07 Mar 2020, 21:30

Arthur Jacquin wrote:Voici ma version du démineur : https://workshop.numworks.com/python/ar ... n/demineur


J'ai beaucoup attendu mais tu as fini par publier ta version ! Je vais enfin pouvoir t'emprunter tes belles mines :)

Arthur Jacquin wrote:Deux fonctionnalités non présentes sur la version de @cent20 :
- impossible de perdre sur le premier clic,
- possibilité de relancer une partie facilement.


Je ne suis pas sûr d'intégrer l'impossibilité de perdre du premier cours, parce que la vie est injuste !
Pour la deuxième fonctionnalité, il suffit d'appuyer sur EXE pour recommencer immédiatement une partie sur ma version.

Arthur Jacquin wrote:Des idées d'améliorations :
- modification du critère de victoire (actuellement pas parfait),
- affichages de toutes les bombes lors d'un échec,
- une fonction qui révèle toutes les cases mitoyennes non découvertes si l'on clique sur un chiffre (évite les clics répétitifs).


Pour l'instant, sur la mienne celui qui perd peut continuer à jour et donc gagner ! :D La réciproque est aussi vraie.

Par contre, offrir ton adresse email aux robots de spam est une gentille attention que tu leur réserves. Ton dossier de SPAM va très vite se remplir !

J'ai mis à jour le premier post de ce topic, je mettrai à jour l'article de présentation ultérieurement.
Image
Enseignant de mathématiques et d'informatique. Spécialité NSI : Des projets, des tutos, mais aussi de l'art
Calculatrice NumWorks : Des applications et des jeux, scripts, 📙 Découvrir la NumWorks
User avatar
cent20VIP++
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Level up: 48.3%
 
Posts: 1047
Images: 67
Joined: 17 May 2012, 09:49
Location: Avignon
Gender: Male
Calculator(s):
MyCalcs profile
Twitter: nsi_xyz

Re: Un démineur en python pour la NumWorks

Unread postby Arthur Jacquin » 07 Mar 2020, 21:35

cent20 wrote:il suffit d'appuyer sur EXE pour recommencer immédiatement une partie sur ma version.

Au temps pour moi, désolé.

Les mines sont issues du démineur originel, en tout cas celui auquel j'ai joué pour la première fois.

Code: Select all
def mine(x,y,b,a): # Dessine une mine au pixel (x,y) de couleur b sur fond a
    fill_rect(x+2,y+2,9,9,b)
    fill_rect(x,y+6,9,1,b)
    fill_rect(x+6,y,1,9,b)
    fill_rect(x+4,y+4,2,2,(255,255,255))
    for p in [[9,2],[10,3],[10,9],[9,10],[3,10],[2,9],[2,3],[3,2]]: set_pixel(x+p[0],y+p[1],a)
User avatar
Arthur Jacquin
Niveau 4: MC (Membre Confirmé)
Niveau 4: MC (Membre Confirmé)
Level up: 56%
 
Posts: 14
Joined: 07 Mar 2020, 21:05
Gender: Not specified
Calculator(s):
MyCalcs profile
Class: MP* Lazaristes
GitHub: arthur-jacquin

Re: Un démineur en python pour la NumWorks

Unread postby Dogm » 07 Mar 2020, 22:33

Bravo pour ton travail. :#top#:

Ajouter le support de la couleur comme sur la version de Cent20 serait une belle amélioration pour augmenter la lisibilité. :)

Enfin la fonctionnalité qui ferait de cette version l'itération ultime serait la possibilité de déminer la zone autour d'une case dans laquelle toutes les mines ont été découvertes. C'est assez difficile à expliquer mais si vous appuyez sur espace sur une mine ici vous devriez comprendre. :)

Les mines sont jolies aussi. ;)
User avatar
DogmEcrivain
Niveau 12: CP (Calculatrice sur Pattes)
Niveau 12: CP (Calculatrice sur Pattes)
Level up: 44.3%
 
Posts: 117
Images: 7
Joined: 14 Nov 2019, 18:53
Location: Lyon, France
Gender: Male
Calculator(s):
MyCalcs profile
Class: Terminale Math NSI
GitHub: Tim-ats-d

Re: Un démineur en python pour la NumWorks

Unread postby Bisam » 07 Mar 2020, 22:43

Joli programme, bien commenté.

J'en viens à me demander si on utiliserait moins de mémoire avec de la programmation objet...
User avatar
BisamAdmin
Niveau 15: CC (Chevalier des Calculatrices)
Niveau 15: CC (Chevalier des Calculatrices)
Level up: 69.6%
 
Posts: 5670
Joined: 11 Mar 2008, 00:00
Location: Lyon
Gender: Male
Calculator(s):
MyCalcs profile

Re: Un démineur en python pour la NumWorks

Unread postby Arthur Jacquin » 07 Mar 2020, 23:26

Merci beaucoup pour ces commentaires positifs !

Je fais la fonction "déminage automatique", c'était déjà sur la liste de fonctionnalités, et la coloration des chiffres dès maintenant.
User avatar
Arthur Jacquin
Niveau 4: MC (Membre Confirmé)
Niveau 4: MC (Membre Confirmé)
Level up: 56%
 
Posts: 14
Joined: 07 Mar 2020, 21:05
Gender: Not specified
Calculator(s):
MyCalcs profile
Class: MP* Lazaristes
GitHub: arthur-jacquin

Re: Un démineur en python pour la NumWorks

Unread postby Dogm » 07 Mar 2020, 23:29

Arthur Jacquin wrote:Merci beaucoup pour ces commentaires positifs !

Je fais la fonction "déminage automatique", c'était déjà sur la liste de fonctionnalités, et la coloration des chiffres dès maintenant.


Bonne chance, :) tiens-nous au courant.
User avatar
DogmEcrivain
Niveau 12: CP (Calculatrice sur Pattes)
Niveau 12: CP (Calculatrice sur Pattes)
Level up: 44.3%
 
Posts: 117
Images: 7
Joined: 14 Nov 2019, 18:53
Location: Lyon, France
Gender: Male
Calculator(s):
MyCalcs profile
Class: Terminale Math NSI
GitHub: Tim-ats-d

Re: Un démineur en python pour la NumWorks

Unread postby Arthur Jacquin » 08 Mar 2020, 01:43

Le déminage automatique est terminé ! C'est tellement pratique qu'on a l'impression de tricher, surtout une fois couplée à la fonction de recherche automatique de cases sans bombes mitoyennes.

Les couleurs des chiffres ont été ajoutées, vous êtes libres de les changer mais il me semble que c'est celles du démineur originel.

J'ai également soigné la fin de partie, que ce soit dans la victoire comme dans l'échec.

Victoire :
- affiche les cases non affichées.
Défaite :
- affiche toutes les bombes,
- barre les drapeaux erronés.

Je vous laisse tester tout ça : https://workshop.numworks.com/python/ar ... n/demineur

J'ai rempli mon cahier de charge (et la mémoire de la calculatrice :)), dites moi si vous pensez à d'autres fonctionnalités.

Et je finis à 1h42 !
User avatar
Arthur Jacquin
Niveau 4: MC (Membre Confirmé)
Niveau 4: MC (Membre Confirmé)
Level up: 56%
 
Posts: 14
Joined: 07 Mar 2020, 21:05
Gender: Not specified
Calculator(s):
MyCalcs profile
Class: MP* Lazaristes
GitHub: arthur-jacquin

Re: Un démineur en python pour la NumWorks

Unread postby cent20 » 08 Mar 2020, 09:28

Arthur Jacquin wrote:J'ai rempli mon cahier des charges (et la mémoire de la calculatrice :)),


As tu eut des messages d'erreur avec la mémoire ou c'est juste une blague pour relancer sur la limite des 16ko ?

J'ai imaginé hier soir un système où l'on stocke les bombes dans les couleurs des pixels, un tel système remplacerait la matrice 15*10 ou 17*10 dans ton cas et occuperait inévitablement moins de mémoire.

Si un pixel de la grille est par exemple codé en RGB en (192,192,192) je me demande si on verrait la différence avec (192,193,192) par exemple, et comme il existe une instruction get_pixel(x,y) on peut interroger les couleurs des différents pixels...

Je ne sais plus où j'ai lu cette astuce (surement sur ce site) et initialement je l'ai imaginé pour savoir si une case à un drapeau ou non, il suffit de tester la présence d'un pixel rouge (dans ton cas) et d'un pixel gris (dans le mien, à cause du "!" en gris).

Reste à savoir si interroger la couleur d'un pixel est plus long que parcourir une matrice, et je dirais intuitivement que c'est bien le cas. En tout cas je ne vais pas intégrer ceci (sauf peut être pour le drapeau), c'est juste une expérience de pensée qui permet de libérer plus de 6ko dans mon cas près de 7ko dans ton cas.
Image
Enseignant de mathématiques et d'informatique. Spécialité NSI : Des projets, des tutos, mais aussi de l'art
Calculatrice NumWorks : Des applications et des jeux, scripts, 📙 Découvrir la NumWorks
User avatar
cent20VIP++
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Level up: 48.3%
 
Posts: 1047
Images: 67
Joined: 17 May 2012, 09:49
Location: Avignon
Gender: Male
Calculator(s):
MyCalcs profile
Twitter: nsi_xyz

PreviousNext

Return to Programmation Python

Who is online

Users browsing this forum: ClaudeBot [spider] and 0 guests

-
Search
-
Social TI-Planet
-
Featured topics
Comparaisons des meilleurs prix pour acheter sa calculatrice !
"1 calculatrice pour tous", le programme solidaire de Texas Instruments. Reçois gratuitement et sans aucune obligation d'achat, 5 calculatrices couleur programmables en Python à donner aux élèves les plus nécessiteux de ton lycée. Tu peux recevoir au choix 5 TI-82 Advanced Edition Python ou bien 5 TI-83 Premium CE Edition Python.
Enseignant(e), reçois gratuitement 1 exemplaire de test de la TI-82 Advanced Edition Python. À demander d'ici le 31 décembre 2024.
Aidez la communauté à documenter les révisions matérielles en listant vos calculatrices graphiques !
1234
-
Donations / Premium
For more contests, prizes, reviews, helping us pay the server and domains...
Donate
Discover the the advantages of a donor account !
JoinRejoignez the donors and/or premium!les donateurs et/ou premium !


Partner and ad
Notre partenaire Jarrety Calculatrices à acheter chez Calcuso
-
Stats.
808 utilisateurs:
>751 invités
>50 membres
>7 robots
Record simultané (sur 6 mois):
6892 utilisateurs (le 07/06/2017)
-
Other interesting websites
Texas Instruments Education
Global | France
 (English / Français)
Banque de programmes TI
ticalc.org
 (English)
La communauté TI-82
tout82.free.fr
 (Français)