π
<-
Chat plein-écran
[^]

Un démineur en python pour la NumWorks

Re: Un démineur en python pour la NumWorks

Message non lude 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: Tout sélectionner
# 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()
Avatar de l’utilisateur
Arthur Jacquin
Niveau 4: MC (Membre Confirmé)
Niveau 4: MC (Membre Confirmé)
Prochain niv.: 56%
 
Messages: 14
Inscription: 07 Mar 2020, 21:05
Genre: Non spécifié
Calculatrice(s):
MyCalcs profile
Classe: MP* Lazaristes
GitHub: arthur-jacquin

Re: Un démineur en python pour la NumWorks

Message non lude critor » 07 Mar 2020, 21:17

Merci bien pour ton travail pertinent là-dessus. :)
Image
Avatar de l’utilisateur
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Prochain niv.: 42.2%
 
Messages: 41493
Images: 14577
Inscription: 25 Oct 2008, 00:00
Localisation: Montpellier
Genre: Homme
Calculatrice(s):
MyCalcs profile
YouTube: critor3000
Twitter/X: critor2000
GitHub: critor

Re: Un démineur en python pour la NumWorks

Message non lude cent20 » 07 Mar 2020, 21:30

Arthur Jacquin a écrit: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 a écrit: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 a écrit: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
Avatar de l’utilisateur
cent20VIP++
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Prochain niv.: 46.1%
 
Messages: 1013
Images: 64
Inscription: 17 Mai 2012, 09:49
Localisation: Avignon
Genre: Homme
Calculatrice(s):
MyCalcs profile
Twitter/X: nsi_xyz

Re: Un démineur en python pour la NumWorks

Message non lude Arthur Jacquin » 07 Mar 2020, 21:35

cent20 a écrit: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: Tout sélectionner
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)
Avatar de l’utilisateur
Arthur Jacquin
Niveau 4: MC (Membre Confirmé)
Niveau 4: MC (Membre Confirmé)
Prochain niv.: 56%
 
Messages: 14
Inscription: 07 Mar 2020, 21:05
Genre: Non spécifié
Calculatrice(s):
MyCalcs profile
Classe: MP* Lazaristes
GitHub: arthur-jacquin

Re: Un démineur en python pour la NumWorks

Message non lude 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. ;)
Avatar de l’utilisateur
DogmEcrivain
Niveau 12: CP (Calculatrice sur Pattes)
Niveau 12: CP (Calculatrice sur Pattes)
Prochain niv.: 44.3%
 
Messages: 117
Images: 7
Inscription: 14 Nov 2019, 18:53
Localisation: Lyon, France
Genre: Homme
Calculatrice(s):
MyCalcs profile
Classe: Terminale Math NSI
GitHub: Tim-ats-d

Re: Un démineur en python pour la NumWorks

Message non lude 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...
Avatar de l’utilisateur
BisamAdmin
Niveau 15: CC (Chevalier des Calculatrices)
Niveau 15: CC (Chevalier des Calculatrices)
Prochain niv.: 69.6%
 
Messages: 5665
Inscription: 11 Mar 2008, 00:00
Localisation: Lyon
Genre: Homme
Calculatrice(s):
MyCalcs profile

Re: Un démineur en python pour la NumWorks

Message non lude 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.
Avatar de l’utilisateur
Arthur Jacquin
Niveau 4: MC (Membre Confirmé)
Niveau 4: MC (Membre Confirmé)
Prochain niv.: 56%
 
Messages: 14
Inscription: 07 Mar 2020, 21:05
Genre: Non spécifié
Calculatrice(s):
MyCalcs profile
Classe: MP* Lazaristes
GitHub: arthur-jacquin

Re: Un démineur en python pour la NumWorks

Message non lude Dogm » 07 Mar 2020, 23:29

Arthur Jacquin a écrit: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.
Avatar de l’utilisateur
DogmEcrivain
Niveau 12: CP (Calculatrice sur Pattes)
Niveau 12: CP (Calculatrice sur Pattes)
Prochain niv.: 44.3%
 
Messages: 117
Images: 7
Inscription: 14 Nov 2019, 18:53
Localisation: Lyon, France
Genre: Homme
Calculatrice(s):
MyCalcs profile
Classe: Terminale Math NSI
GitHub: Tim-ats-d

Re: Un démineur en python pour la NumWorks

Message non lude 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 !
Avatar de l’utilisateur
Arthur Jacquin
Niveau 4: MC (Membre Confirmé)
Niveau 4: MC (Membre Confirmé)
Prochain niv.: 56%
 
Messages: 14
Inscription: 07 Mar 2020, 21:05
Genre: Non spécifié
Calculatrice(s):
MyCalcs profile
Classe: MP* Lazaristes
GitHub: arthur-jacquin

Re: Un démineur en python pour la NumWorks

Message non lude cent20 » 08 Mar 2020, 09:28

Arthur Jacquin a écrit: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
Avatar de l’utilisateur
cent20VIP++
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Prochain niv.: 46.1%
 
Messages: 1013
Images: 64
Inscription: 17 Mai 2012, 09:49
Localisation: Avignon
Genre: Homme
Calculatrice(s):
MyCalcs profile
Twitter/X: nsi_xyz

PrécédenteSuivante

Retourner vers Programmation Python

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 3 invités

-
Rechercher
-
Social TI-Planet
-
Sujets à la une
Comparaisons des meilleurs prix pour acheter sa calculatrice !
Aidez la communauté à documenter les révisions matérielles en listant vos calculatrices graphiques !
Phi NumWorks jailbreak
123
-
Faire un don / Premium
Pour plus de concours, de lots, de tests, nous aider à payer le serveur et les domaines...
Faire un don
Découvrez les avantages d'un compte donateur !
JoinRejoignez the donors and/or premium!les donateurs et/ou premium !


Partenaires et pub
Notre partenaire Jarrety Calculatrices à acheter chez Calcuso
-
Stats.
1318 utilisateurs:
>1276 invités
>37 membres
>5 robots
Record simultané (sur 6 mois):
6892 utilisateurs (le 07/06/2017)
-
Autres sites intéressants
Texas Instruments Education
Global | France
 (English / Français)
Banque de programmes TI
ticalc.org
 (English)
La communauté TI-82
tout82.free.fr
 (Français)