Jeu Ricosheep

Résolu/Fermé
Ak_j Messages postés 18 Date d'inscription dimanche 24 avril 2022 Statut Membre Dernière intervention 23 juin 2022 - Modifié le 24 avril 2022 à 11:29
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 - 26 avril 2022 à 16:52
Bonjour,



Je programme un jeu le Ricosheep. C'est un jeu de type casse-tête, inspiré principalement des jeux Ricochet Robots et 2048. Le jeu se joue sur une grille remplie de moutons, de touffes d’herbe, de buissons et de cases vides et le but du jeu est de placer un mouton sur chaque touffe d’herbe. Le problème, c'est que je dois créer une fonction jouer(plateau,moutons, direction) recevant en paramètre l’état du jeu et une direction représentée par la chaine 'Left', 'Right', 'Up' ou 'Down'. La fonction ne renvoie rien et met directement à jour les positions des moutons dans la liste de tuples,en respectant les règles du jeu. Les moutons se déplacent en groupe dans la direction indiquée jusqu’à rencontrer un obstacle.
J'aimerais avoir un peu d'aide, car je ne sais pas du tout comment faire.

Voici un exemple ci-dessous :



Je vous remercie d'avance.
Configuration: Windows / Chrome 100.0.4896.127

8 réponses

Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
Modifié le 26 avril 2022 à 17:34
Bonjour,

Bizarre ton dernier code: tu initialise à la fois une variable "plateau" et une variable "tableau"

Normalement, il s'agit de la même chose, non ?

Moi, je ferais ça: (je n'ai pas testé si on déborde du plateau dans la fonction premiere_case_vide)

Et effectivement, on peut balayer les 4 directions en une boucle sans utiliser 'up', 'down', etc ..
def init_plateau():

    plateau = [['V', 'B' , 'V', 'B' , 'V'],
               ['B' , 'B' , 'V', 'V', 'V'],
               ['V', 'G' , 'B' , 'B' ,'V'],
               ['V', 'B' , 'G' , 'V', 'V'],
               ['V', 'V', 'V', 'V' , 'V']]

    return(plateau)

def affiche_plateau(plateau):

    for k in range(5):
        for j in range(5): print(plateau[k][j], end = '  ')
        print('')

def premiere_case_vide(plateau, pos):
    ''' Retourne la 1ere case adjacente à 'pos' vide'''

    liste_dir = [[0,1],[0,-1],[1,0],[-1,0]]
    case_vide = []

    for _dir in liste_dir:
        case = plateau[pos[0]+_dir[0]][pos[1]+_dir[1]]
        if(case == 'V'):
            case_vide = [pos[0]+_dir[0],pos[1]+_dir[1]]
            break

    return(case_vide)

plateau = init_plateau()
affiche_plateau(plateau)

ligne_colonne = [1,1]
case_vide = premiere_case_vide(plateau, ligne_colonne)
print('\n1ere case vide adjacente à {} : {}'.format(ligne_colonne, case_vide))
1
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
Modifié le 24 avril 2022 à 12:06
Bonjour,

avec ton code, on y verrait plus clair...

avec les balises de code:

https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code

et sinon, c'est quoi le problème ?

C'est un projet de cours ?
0
Ak_j Messages postés 18 Date d'inscription dimanche 24 avril 2022 Statut Membre Dernière intervention 23 juin 2022
Modifié le 24 avril 2022 à 14:08
Oui, c'est un projet de cours, mais mon code est assez compliqué (j'aimerais en faire un beaucoup plus simple.) et le problème, c'est que mon programme ne déplace pas plusieurs moutons en même temps et lorsque la direction est 'up' il y a des moutons qui se retrouvent au même endroit qu'un buisson. (alors qu'il ne doit être que sur des cases vides ou sur la touffe d'herbe)

def detection_moutons_adjacents(moutons,mouton,direction):
    """
    Fonction recevant en paramètre un mouton et une direction vérifiant la présence d'un autre mouton
    sur une case à proximité dans une direction donnée.
    param: moutons : liste de tuple
    param: mouton : tuple
    param: direction : string
    return boolean

    >>>detection_moutons_adjacents([(0,4), (1,3), (2,4), (3,4)],(2,4),'Down')
       False
    >>>detection_moutons_adjacents([(0,4), (1,2), (1,4), (3,4)],(1,4),'Left')
       True
    """
    mouton_non_detecte = None
    ligne_mouton = mouton[0]
    colonne_mouton = mouton[1]
    mouton_de_rechange = copy.copy(moutons)
    for dead_mouton in range(len(mouton_de_rechange)) :
        if len(mouton_de_rechange) > dead_mouton :
            if moutons[dead_mouton] in mouton_de_rechange :
                mouton_de_rechange.pop(dead_mouton)
    if direction == 'Left' :
        for moutons_adjacent in mouton_de_rechange :
            if moutons_adjacent[0] == ligne_mouton :
                if moutons_adjacent[1] == colonne_mouton-1 :
                    return False
            else :
                mouton_non_detecte = True
    if direction == 'Right' :
        for moutons_adjacent in mouton_de_rechange :
            if moutons_adjacent[0] == ligne_mouton :           
                if moutons_adjacent[1] == colonne_mouton+1 :
                    return False
            else :
                mouton_non_detecte = True        
    if direction == 'Up' :
        for moutons_adjacent in mouton_de_rechange :
            if moutons_adjacent[1] == colonne_mouton :
                if moutons_adjacent[0] == ligne_mouton-1 :
                    return False
            else :
                mouton_non_detecte = True
    if direction == 'Down' :
        for moutons_adjacent in mouton_de_rechange :
            if moutons_adjacent[1] == colonne_mouton :
                if moutons_adjacent[0] == ligne_mouton+1 :
                    return False
            else :
                mouton_non_detecte = True
    return mouton_non_detecte


            

def jouer(plateau,moutons,direction):
   
    """
    recevant en paramètre l’état du jeu et une direction représentée par la
    chaine 'Left', 'Right', 'Up' ou 'Down'. La fonction ne renvoie rien et met directement à jour
    les positions des moutons dans la liste moutons en respectant les règles du jeu. 
    param: plateau : list
    param: moutons : list de tuple
    param: direction : string
    """
    for i in range (len(moutons)-1) :
        if direction == 'Left' :
            while moutons[i][1] != 0 and plateau[moutons[i][0]][moutons[i][1]-1] == None :
                if detection_moutons_adjacents(moutons,moutons[i],'Left'):
                    nouvelle_pos = (moutons[i][0],moutons[i][1]-1)
                    moutons[i] = nouvelle_pos
        if direction == 'Right' :
            while moutons[i][1] != len(plateau[moutons[i][0]])-1 and plateau[moutons[i][0]][moutons[i][1]+1] == None :
                if detection_moutons_adjacents(moutons,moutons[i],'Right'):
                    nouvelle_pos = (moutons[i][0],moutons[i][1]+1)
                    moutons[i] = nouvelle_pos
        if direction == 'Up' :
            while moutons[i][0] != 0 and plateau[moutons[i][0]-1][moutons[i][1]] == None :
                if detection_moutons_adjacents(moutons,moutons[i],'Up'):
                    nouvelle_pos = (moutons[i][0]-1,moutons[i][1])
                    moutons[i] = nouvelle_pos
        if direction == 'Down' :
            while moutons[i][0] != len(plateau)-1 and plateau[moutons[i][0]+1][moutons[i][1]] == None :
                if detection_moutons_adjacents(moutons,moutons[i],'Down'):
                    nouvelle_pos = (moutons[i][0]+1,moutons[i][1])
                    moutons[i] = nouvelle_pos
0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
24 avril 2022 à 14:04
Tu n'as pas utilisé les balises de code comme te l'explique le lien que je t'ai donné plus haut ...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Ak_j Messages postés 18 Date d'inscription dimanche 24 avril 2022 Statut Membre Dernière intervention 23 juin 2022
Modifié le 25 avril 2022 à 12:42
Ok c'est celle là que tu veux que j'utilise, pas de souci :
def detection_moutons_adjacents(moutons,mouton,direction):
    """
    Fonction recevant en paramètre un mouton et une direction vérifiant la présence d'un autre mouton
    sur une case à proximité dans une direction donnée.
    param: moutons : liste de tuple
    param: mouton : tuple
    param: direction : string
    return boolean

    >>>detection_moutons_adjacents([(0,4), (1,3), (2,4), (3,4)],(2,4),'Down')
       False
    >>>detection_moutons_adjacents([(0,4), (1,2), (1,4), (3,4)],(1,4),'Left')
       True
    """
    mouton_non_detecte = None
    ligne_mouton = mouton[0]
    colonne_mouton = mouton[1]
    mouton_de_rechange = copy.copy(moutons)
    for dead_mouton in range(len(mouton_de_rechange)) :
        if len(mouton_de_rechange) > dead_mouton :
            if moutons[dead_mouton] in mouton_de_rechange :
                mouton_de_rechange.pop(dead_mouton)
    if direction == 'Left' :
        for moutons_adjacent in mouton_de_rechange :
            if moutons_adjacent[0] == ligne_mouton :
                if moutons_adjacent[1] == colonne_mouton-1 :
                    return False
            else :
                mouton_non_detecte = True
    if direction == 'Right' :
        for moutons_adjacent in mouton_de_rechange :
            if moutons_adjacent[0] == ligne_mouton :           
                if moutons_adjacent[1] == colonne_mouton+1 :
                    return False
            else :
                mouton_non_detecte = True        
    if direction == 'Up' :
        for moutons_adjacent in mouton_de_rechange :
            if moutons_adjacent[1] == colonne_mouton :
                if moutons_adjacent[0] == ligne_mouton-1 :
                    return False
            else :
                mouton_non_detecte = True
    if direction == 'Down' :
        for moutons_adjacent in mouton_de_rechange :
            if moutons_adjacent[1] == colonne_mouton :
                if moutons_adjacent[0] == ligne_mouton+1 :
                    return False
            else :
                mouton_non_detecte = True
    return mouton_non_detecte


            

def jouer(plateau,moutons,direction):
   
    """
    recevant en paramètre l’état du jeu et une direction représentée par la
    chaine 'Left', 'Right', 'Up' ou 'Down'. La fonction ne renvoie rien et met directement à jour
    les positions des moutons dans la liste moutons en respectant les règles du jeu. 
    param: plateau : list
    param: moutons : list de tuple
    param: direction : string
    """
    for i in range (len(moutons)-1) :
        if direction == 'Left' :
            while moutons[i][1] != 0 and plateau[moutons[i][0]][moutons[i][1]-1] == None :
                if detection_moutons_adjacents(moutons,moutons[i],'Left'):
                    nouvelle_pos = (moutons[i][0],moutons[i][1]-1)
                    moutons[i] = nouvelle_pos
        if direction == 'Right' :
            while moutons[i][1] != len(plateau[moutons[i][0]])-1 and plateau[moutons[i][0]][moutons[i][1]+1] == None :
                if detection_moutons_adjacents(moutons,moutons[i],'Right'):
                    nouvelle_pos = (moutons[i][0],moutons[i][1]+1)
                    moutons[i] = nouvelle_pos
        if direction == 'Up' :
            while moutons[i][0] != 0 and plateau[moutons[i][0]-1][moutons[i][1]] == None :
                if detection_moutons_adjacents(moutons,moutons[i],'Up'):
                    nouvelle_pos = (moutons[i][0]-1,moutons[i][1])
                    moutons[i] = nouvelle_pos
        if direction == 'Down' :
            while moutons[i][0] != len(plateau)-1 and plateau[moutons[i][0]+1][moutons[i][1]] == None :
                if detection_moutons_adjacents(moutons,moutons[i],'Down'):
                    nouvelle_pos = (moutons[i][0]+1,moutons[i][1])
                    moutons[i] = nouvelle_pos
0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
Modifié le 24 avril 2022 à 18:27
Avant tout, je ferais un tableau 2D avec des 0:

tableau = [[0 for j in range(nb_colonnes)] for i in range(nb_lignes)]


Ensuite je remplirais avec des 1 si il y a un mouton dans la case, exemple:

tableau[2][3] = 1


Pour détecter si il y a des moutons adjacents, je ferais une fonction qui reçoit la position ligne/colonne d'un

mouton et la direction, et donc qui renvoie True ou False suivant que la case adjacente est libre ou pas
def case_libre(pos_mouton,dir):

    case_libre = False
 
    if(dir == 'right'):
        case = tableau[pos_mouton[0]][pos_mouton[1]+1]
        if case == 0: case_libre = True
    elif(dir == 'left'):

#   etc ...

    return(case_libre)

print(case_libre([2,2],'right'))

0
mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 7 748
25 avril 2022 à 12:58
Bonjour,

Comme l'indique Phil, il te faut une structure de donnée qui stocke l'état du plateau, typiquement un tableau 2D (par exemple une liste de listes) dont chaque élément est un entier qui caractérise l'état de la case. On aura donc probablement besoin d'une fonction qui initialise ce plateau de jeu :
  • def init_plateau(num_lignes, num_colonnes)
    ;
  • def get_num_lignes(plateau)
    ;
  • def get_num_colonnes(plateau)
    .


Il faut d'ailleurs te demander quels sont les états possibles (en l'occurrence une case peut avoir ou non une touffe d'herbe, un mouton, un buisson). Une fois ce choix fait, il serait sans doute pratique d'avoir des fonctions auxiliaires permettant de tester si une case contient ou pas un mouton, une touffe d'herbe, un buisson.
  • def contient_mouton(plateau, i, j)
    ;
  • def contient_buisson(plateau, i, j)
    ;
  • def contient_herbe(plateau, i, j)
    .


À toi de voir si tu veux que plateau encode la position des moutons, ou si tu préfères que cette information soit mémorisée dans une structure dédiée. La première approche est à mon avis plus simple à coder et la seconde est plus élégante, quoi qu'il en soit les deux approches sont possibles.

Ces choix faits, on peut commencer à réfléchir à l'algorithme de déplacement. Un mouton se déplace jusqu'à rencontrer un obstacle, qui est soit un buisson, soit un mouton qui ne peut pas se déplacer. Cela suggère que si tu te déplaces disons vers la droite, tu as intérêt à traiter les moutons de la droite vers la gauche. Ainsi, il suffit de tester, au moment de déplacer un mouton, si la case à sa droite est libre (c'est-à-dire ne contient ni mouton, ni buisson) et dans le plateau. Si c'est le cas, le mouton se décale à droite et on répète jusqu'à ce que ce critère d'arrêt soit faux. Puis on passe au mouton suivant.

Cet algorithme met en évidence que tu as besoin des primitives supplémentaires suivantes (ajouter
moutons
si ceux-ci sont stockés dans une structure dédiée) :
  • def est_case_libre(plateau, i, j)
    ;
  • def iter_moutons(plateau, direction)
    ;
  • def deplacer_mouton(plateau, i, j, direction)
    ;


Bonne chance
0
Ak_j Messages postés 18 Date d'inscription dimanche 24 avril 2022 Statut Membre Dernière intervention 23 juin 2022
Modifié le 26 avril 2022 à 15:04
Re Bonjour,

J'ai encore un problème : lorsque la direction est
'Down'
, au lieu d'avoir le résultat attendu :

moutons = [(2, 4), (1, 3), (3, 4), (4, 4)]


... les moutons se retrouvent tous au même endroit et j'obtiens :

moutons = [(4, 4), (1, 3), (4, 4), (4, 4)] 


Pouvez, vous m'aider s'il vous plait ?

plateau = [[None, 'B' , None, 'B' , None],
['B' , 'B' , None, None, None],
[None, 'G' , 'B' , 'B' , None],
[None, 'B' , 'G' , None, None],
[None, None, None, None , None]]

moutons = [(0, 4), (1, 3), (2, 4), (4, 4)]

def init_plateau(nb_colonnes, nb_lignes):
    tableau = [[0 for j in range(nb_colonnes)] for i in range(nb_lignes)]
    return tableau

def contient_moutons(case,case_moutons,direction):
    if direction == 'Left' or direction == 'Right':
        pass
   
    if direction == 'Down' or direction == 'Up':
        if case == None or case  == 'G'  and case_moutons == 0:
            return True
        else:
            return False
    
    
def jouer(plateau,moutons,direction):
    coord_x = 0
    danger = 0
    plateau_moutons = init_plateau(len(plateau[0]), len(plateau[0]))
    if direction == 'Down':
        for i in range(len(moutons) - 1, -1, -1):
            for colonne in range(moutons[i][0], len(plateau[0])):
                if danger <= 0:
                    if contient_moutons(plateau[colonne][moutons[i][1]], plateau_moutons[colonne][moutons[i][1]], 'Down'):
                        coord_x = colonne
                    else:
                        danger += 1
            moutons[i] = coord_x,moutons[i][1]
            plateau_moutons[colonne][moutons[i][1]]= 1
            danger = 0
    if direction == 'Up':
        for i in range(len(moutons)):
            for colonne in range(moutons[i][0], -1, -1):
                if contient_moutons(plateau[colonne][moutons[i][1]],plateau_moutons[colonne][moutons[i][1]], 'Up'):
                    coord_x = colonne
            moutons[i] = coord_x , moutons[i][1]
            plateau_moutons[colonne][moutons[i][1]] = 1
    return moutons
0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
26 avril 2022 à 11:15
Bonjour,
les couleurs de ton code sont bizarres, tu utilise vraiment les balises Python ?
0
mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 7 748
Modifié le 26 avril 2022 à 15:09
Bonjour,

Pour qu'on soit sûr de comprendre ton code, ce serait pas mal de nous dire ce que signifie
'B'
(buisson ?) et (
'G'
grass pour herbe ?).

Ensuite, je pense qu'une direction devrait être définie comme un couple d'entiers
(di, dj)
à valeur dans dans {-1, 1} x {-1, 1}. Ainsi, calculer
(i, j) + (di, dj)
permet de déterminer la case cible à partir de la case de départ
(i, j)
sans se avoir à traiter spécifiquement chaque direction. Ça simplifierait grandement ton code, car tu traiterais d'un coup les 4 directions.

Bonne chance
0