Je fais un jeu de nim, où le joueur supprime tout non. de pierres d'une seule rangée parmi trois rangées. Celui qui choisit la dernière pierre gagne. Pour jouer le joueur saisissez a, b, c ... l pour enlever les pierres. Mais dans la fabrication du code, cela devient inutilement long. Je veux donc raccourcir mon code de 30 lignes. Voici le code original qui fonctionne:

# Nim Game

# Game Variables
row1 = ['a', 'b', 'c']
row2 = ['d', 'e', 'f', 'g']
row3 = ['h', 'i', 'j', 'k', 'l']

x = ['0', '0', '0']
y = ['0', '0', '0', '0']
z = ['0', '0', '0', '0', '0']


def board(x, y, z):
    print(x[0] + "  " + x[1] + "  " + x[2])
    print(y[0] + "  " + y[1] + "  " + y[2] + "  " + y[3])
    print(z[0] + "  " + z[1] + "  " + z[2] + "  " + z[3] + "  " + z[4])


def valid_move(a, b, c, d):  # Check for validity of moves
    flag = False
    if set(a).issubset(set(b)) or set(a).issubset(set(c)) or set(a).issubset(set(d)):
        flag = True
    return flag


def rules():  # Respond to input from players.
    if valid_move(move, row1, row2, row3) and not any(item in move for item in already_played):
        if 'a' in move:
            x[0] = " "
            already_played.append('a')
        if 'b' in move:
            x[1] = " "
            already_played.append('b')
        if 'c' in move:
            x[2] = " "
            already_played.append('c')
        if 'd' in move:
            y[0] = " "
            already_played.append('d')
        if 'e' in move:
            y[1] = " "
            already_played.append('e')
        if 'f' in move:
            y[2] = " "
            already_played.append('f')
        if 'g' in move:
            y[3] = " "
            already_played.append('g')
        if 'h' in move:
            z[0] = " "
            already_played.append('h')
        if 'i' in move:
            z[1] = " "
            already_played.append('i')
        if 'j' in move:
            z[2] = " "
            already_played.append('j')
        if 'k' in move:
            z[3] = " "
            already_played.append('k')
        if 'l' in move:
            z[4] = " "
            already_played.append('l')
    else:
        print("Invalid move")
    already_played.sort()
    print('Already played: ' + str(already_played))

already_played = []
while x != [' ', ' ', ' '] or y != [' ', ' ', ' ', ' '] or z != [' ', ' ', ' ', ' ', ' ']:
    board(x, y, z)
    move = list(input().lower())
    rules()
print("Game over!")

Maintenant, je veux raccourcir le code sous la fonction rules () en créant un dictionnaire de [a, b, c ...] avec les valeurs [x [0], x [1], x [2] ...]. Et maintenant, en utilisant des boucles for pour parcourir les clés et les valeurs. Mais un problème survient lorsque je règle la valeur (qui est un élément des listes x, y, z) sur "" (ce qui fait disparaître cet élément dans le tableau (x, y, z)), cela ne fonctionne pas de cette façon. Il ne fait pas la valeur = "" dans board (). Voici le code que j'ai essayé qui ne fonctionne pas:

# Nim Game

# Game Variables
row1 = ['a', 'b', 'c']
row2 = ['d', 'e', 'f', 'g']
row3 = ['h', 'i', 'j', 'k', 'l']

x = ['0', '0', '0']
y = ['0', '0', '0', '0']
z = ['0', '0', '0', '0', '0']


def board(x, y, z):
    print(x[0] + "  " + x[1] + "  " + x[2])
    print(y[0] + "  " + y[1] + "  " + y[2] + "  " + y[3])
    print(z[0] + "  " + z[1] + "  " + z[2] + "  " + z[3] + "  " + z[4])


def valid_move(a, b, c, d):  # Check for validity of moves
    flag = False
    if set(a).issubset(set(b)) or set(a).issubset(set(c)) or set(a).issubset(set(d)):
        flag = True
    return flag


def rules():  # Respond to input from users.
    rulebook = {'a': 'x[0]', 'b': 'x[1]', 'c': 'x[2]', 'd': 'y[0]', 'e': 'y[1]', 'f': 'y[2]', 'g': 'y[3]', 'h': 'z[0]',
                'i': 'z[1]', 'j': 'z[2]', 'k': 'z[3]', 'l': 'z[4]'}
    if valid_move(move, row1, row2, row3) and not any(item in move for item in already_played):
        for key, value in rulebook.items():
            if key in move:
                value = " "
                already_played.append(key)
    else:
        print("Invalid move")
    already_played.sort()
    print('Already played: ' + str(already_played))

already_played = []
while x != [' ', ' ', ' '] or y != [' ', ' ', ' ', ' '] or z != [' ', ' ', ' ', ' ', ' ']:
    board(x, y, z)
    move = list(input().lower())
    rules()
print("Game Over!")

Veuillez voir où est l'erreur. Et suggérez le moyen de le réparer. S'il existe un autre moyen de raccourcir le code, cela sera apprécié.

0
Rishabh Semwal 18 juin 2020 à 09:05

3 réponses

Meilleure réponse

J'ai apporté de petits changements à votre tableau. Je change le coup joué avec 'x' donc lors de l'impression, il montrera qui sont terminés ou pas encore terminés.

row1 = 'abc'
row2 = 'defg'
row3 = 'hijkl'

rulebook = dict(zip((row1 + row2 + row3), ['0'] * 12))

already_played = []

def board():
    val = list(rulebook.values())
    x = 0
    for row in [row1, row2, row3]:
        print(' '.join(val[x: x + len(row)]))



def valid_move(a, b, c, d):  # Check for validity of moves
    return any(set(a).issubset(row) for row in [b, c, d])

def rules(move):  # Respond to input from users.
    if valid_move(move, row1, row2, row3) and not any(item in move for item in already_played):
        for x in move:
            rulebook[x] = 'x'
            already_played.append(x)
    else:
        print("Invalid move")
    already_played.sort()
    print('Already played: ' + str(already_played))

while ''.join(rulebook.values()) != 'x' * len(rulebook):
    board() 
    rules(input().lower())
print("Game over!")

Vous ne pouvez pas modifier les éléments de la liste en utilisant une expression de chaîne comme 'x[0]'. Si vous modifiez votre chaîne pour aimer ceci 'x[0] = " "'. et utilisez maintenant exec() pour exécuter l'expression de chaîne. Il mettra à jour la valeur de x[0].

def rules():  # Respond to input from users.
    rulebook = {'a': 'x[0]=" "', 'b': 'x[1]=" "', 'c': 'x[2]=" "', 'd': 'y[0]=" "', 
                'e': 'y[1]=" "', 'f': 'y[2]=" "', 'g': 'y[3]=" "', 'h': 'z[0]=" "',
                'i': 'z[1]=" "', 'j': 'z[2]=" "', 'k': 'z[3]=" "', 'l': 'z[4]=" "'}
    if valid_move(move, row1, row2, row3) and not any(item in move for item in already_played):
        for key, value in rulebook.items():
            if key in move:
                exec(value)
                already_played.append(key)
    else:
        print("Invalid move")
    already_played.sort()
    print('Already played: ' + str(already_played))
1
komatiraju032 18 juin 2020 à 08:30

J'ai fait un code avec des pandas et numpy, jetez-y un œil! J'ai réussi à le réduire à 31 lignes de code, presque ce que vous vouliez.

J'ai créé une classe (Board) dans laquelle il y a un dataframe (board variable) qui définit les positions dans votre board, dans la méthode move (self), il vérifie si le déplacement est valide en recherchant la valeur d'entrée dans le dataframe ( board), si elle est trouvée, mettez à jour la valeur sur '', sinon elle revient à l'entrée. Un peu difficile pour accéder à la méthode game_over mais je suis sûr que vous pouvez suivre le code. J'espère que vous apprécierez ce code!

import pandas as pd
import numpy as np
# Nim Game

class Board:
    def __init__(self):
        self.board = pd.DataFrame(np.array([['a',2,3],[4,5,6],[7,8,9]]), columns=['one','two','three'])
        print(self.board)
    def show_board(self):
        print(self.board)
    def move(self,move):
        if move[0] != ' ':
            for index,row in self.board.iterrows():
                if move[0] in row.tolist():

                    column = row.tolist().index(move[0])
                    self.board.at[index,list(self.board)[column]] = ' '
                    self.show_board()
                    if not self.game_over():
                        return False
                    return True
        print('not possible move')
        self.show_board()
        return self.game_over()
    def game_over(self):
        a = self.board.to_numpy()
        return not (a[0] == a).all()



board = Board()
not_game_over = True
while not_game_over:
    print('provide an input')
    move = list(input().lower())
    not_game_over = board.move(move)
print("Game Over!")
1
T. Novais 18 juin 2020 à 07:29

L'optimisation du code appartient généralement au site code review. Juste quelques entrées ...

Je ne sais pas si j'ai toutes vos intentions mais cette approche semble trop compliquée.

  1. N'ayez qu'un seul objet qui représente votre tableau, j'aurais choisi un List[List], puis au lieu de mapper un caractère sur chaque champ (ce qui vous limite dans la taille de votre champ), j'ai laissé l'utilisateur entrer deux entiers pour identifier le champ choisi.
  2. Pas besoin de garder une trace des éléments joués dans une autre liste, vérifiez simplement si le champ de votre plateau est toujours jouable.
  3. Je réduirais au minimum l'utilisation de variables globales dans les fonctions, cela vous permet par ex. déplacez-les vers des fichiers séparés.
  4. Vous effectuez beaucoup de conversions de type inutiles, pourquoi move doit-il être de type List?

Ou votre valid_move pourrait être simplifié en

def valid_move(a, b, c, d):  # Check for validity of moves
    return (a in b or a in c or a in d)
1
po.pe 18 juin 2020 à 06:33