Démineur

Contenu du snippet

J'ai codé un classique jeu du démineur en python 2.7 mais en console afin d'éviter de creer une interface graphique. Il marche sur Arch Linux et Windows 8 (sous reserve d'avoir installé au préalable colorama et python 2.7).

#!/usr/bin/python2.7
# -*- coding: utf-8 -*-

#25/04/15
"""
installation :
WINDOWS
- telecharger le module colorama (https://pypi.python.org/packages/source/c/colorama/colorama-0.3.3.tar.gz)
- l'installer (decompresser avec 7-zip deux fois puis executer dans une console "...distcolorama-0.x.x>python setup.py install"
GNU/LINUX
- "# apt-get install colorama" ou "# pacman -Sy colorama" (sur sys debian ou arch linux)
execution :
- "...>demineur-2.py" ou "... $ demineur-2.py"

#Pour les matrices !
# i : n° ligne
# j : n° colonne
# A[i][j]
# point de coord (x,y) -> A[y][x]

#Pour les vecteurs !
# i : n° ligne
# transpose(u[i]) = U[i][0]
"""

import os, sys
from random import *
from math import *
from colorama import init, Fore, Back

def decouvrir(d,n,w,h,grille):
 if 0<=d[X] and d[X]<w and 0<=d[Y] and d[Y]<h and grille[d[Y]][d[X]][VIRT]!='':#si dans grille et que case est etudiee pour la 1ere fois
  grille[d[Y]][d[X]][VIRT]=''
  n += 1
  if grille[ d[Y] ][ d[X] ][ REEL ] == TABLE[NEANT] :
   for i in range(-1,2):#lignes
    for j in range(-1,2):#colonnes
      n = decouvrir( [ d[X] + j , d[Y] + i ] , n , w, h , grille )
   return n
 return n

def detecter(n,grille,d,w,h):
 if len(d)==2:
  if grille[d[Y]][d[X]][REEL]==TABLE[MINE]:#mine detectee
   for i in range(h):#lignes
    for j in range(w):#colonnes
     grille[i][j][VIRT]=''
   n = w * h
  elif grille[d[Y]][d[X]][REEL]==TABLE[NEANT]:
   n=decouvrir(d,n,w,h,grille)#decouvrir les espaces
  else:
   grille[d[Y]][d[X]][VIRT]=''#afficher zone numerotee
   n += 1
 else:
  if d[MARQUEUR]==TABLE[AS_MIN]:
   grille[d[Y]][d[X]][VIRT]=TABLE[AS_MIN]
  elif d[MARQUEUR]==TABLE[INCONNU]:
   grille[d[Y]][d[X]][VIRT]=TABLE[INCONNU]
  else:
   grille[d[Y]][d[X]][VIRT]=TABLE[AS_INC]
 return n

def color(a):
 if a==TABLE[MINE]:
  sys.stdout.write(Fore.RED+a+Fore.RESET)
 elif a=='1':
  sys.stdout.write(Fore.BLUE+a+Fore.RESET)
 elif a=='2':
  sys.stdout.write(Fore.GREEN+a+Fore.RESET)
 elif a=='3':
  sys.stdout.write(Fore.YELLOW+a+Fore.RESET)
 elif a=='4':
  sys.stdout.write(Fore.MAGENTA+a+Fore.RESET)
 else:
  sys.stdout.write(a)
 
def flip(grille,w,h):
 os.system('cls' if os.name == 'nt' else 'clear')
 sys.stdout.write("  ")
 
 for i in range( 97 , w + 97 ) :
  sys.stdout.write(chr(i))#affiche caractere n°j de la table ASCII
 sys.stdout.write('n')
 
 for i in range(h):#lignes
  sys.stdout.write( chr( i + 97 ) + ' ' )
  for j in range(w):#colonnes
   if j%2==0 and i%2==0 or (j+1)%2==0 and (i+1)%2==0:#affiche un damier en fond cyan
    sys.stdout.write(Back.CYAN)
    
   if grille[i][j][VIRT] == '' :#affiche la grille reel s'il n'y a rien à afficher de la grille virtuelle
    color(grille[i][j][REEL])
   else:
    color(grille[i][j][VIRT])
    
   if j%2==0 and i%2==0 or (j+1)%2==0 and (i+1)%2==0:
    sys.stdout.write(Back.RESET)
  sys.stdout.write('n')

def marquerGrille(mine,w,h,grille):
 for i in range(-1+mine[Y],2+mine[Y]):
  for j in range(-1+mine[X],2+mine[X]):
   if 0<=i and i<h and 0<=j and j<w and (i!=mine[Y] or j!=mine[X]) and not(grille[i][j][REEL]==TABLE[MINE]):
    if grille[i][j][REEL]==TABLE[NEANT]:
     grille[i][j][REEL]='1'
    else:
     grille[i][j][REEL] = str( int( grille[i][j][REEL] ) + 1 )

def main():
 w = randint(3,26)#longueur horizontale de la grille
 h = randint(3,20)
 x = randint( 0 , w - 1 )
 y = randint( 0 , h - 1 )
 nbMines = ( w * h / 10 ) + 1#facile : pas bcp de mines
 nbCasesDeminees = 0
 grille = [ [ [ '' , '' ] for j in range(w) ] for i in range(h) ]
 
 #affiche la grille reel s'il n'y a rien à afficher de la grille virtuelle
 for i in range(h):#init 2 tabl à 2 dimensions : grille[][][0]->grille reel, grille[][][1]->grille virtuelle (qui sera visible par l'utilisateur)
  for j in range(w):   
   grille[i][j][REEL] = TABLE[NEANT]
   grille[i][j][VIRT] = TABLE[INCONNU]

 for k in range(nbMines):#positionnement des mines
  while grille[y][x][REEL] == TABLE[MINE] :
   x = randint( 0 , w - 1 )
   y = randint( 0 , h - 1 )
  grille[y][x][REEL] = TABLE[MINE]#on place la mine
  marquerGrille( [ x , y ], w , h , grille )

 init()
 sys.stdout.write(Fore.RESET)

 flip(grille,w,h)
 
 while nbCasesDeminees < w * h - nbMines :
  while 1:
   detecteur=raw_input("Entrer les coordonnées d'une zone à étudier ou à marquer (xy[?/f]) : ")#demande coord detecteur
   detecteur=list(detecteur)
   detecteur[X]=ord(detecteur[0][0])-97#n° colonne
   detecteur[Y]=ord(detecteur[1][0])-97#n° ligne
   if 0<=detecteur[X] and detecteur[X]<w and 0<=detecteur[X] and detecteur[Y]<h and len(detecteur) <= 3 :
    break
  nbCasesDeminees=detecter(nbCasesDeminees,grille,detecteur,w,h)
  flip(grille,w,h)
  
 if nbCasesDeminees == w * h - nbMines :
  sys.stdout.write("Bravo ! Vous avez gagné !n")
 else:
  sys.stdout.write("Bouh ! Vous avez perdu !n")

 exit(0)
 
#cstes
TABLE=['X','*',' ','?','f']#inconnu, mine, néant, marquer comme inconnu, marquer comme mine

#enum
X,Y=0,1
MARQUEUR=2
REEL,VIRT=0,1
INCONNU,MINE,NEANT,AS_INC,AS_MIN=0,1,2,3,4

if __name__ == '__main__' : main()

Compatibilité : 1.0

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.