Как исправить переопределение значения словаря, не меняющее значение другого списка? - PullRequest
0 голосов
/ 18 июня 2020

Я делаю игру в ним, где игрок удаляет любое нет. камней из одного ряда в три ряда. Выигрывает тот, кто выберет последний камень. Чтобы проиграть, введите a, b, c ... l, чтобы убрать камни, но при создании кода он становится излишне длинным. Поэтому я хочу сократить свой код на 30 строк. Ниже приведен исходный код, который работает:

# 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!")

Теперь я хочу сократить код функции rules (), создав словарь [a, b, c ...] со значениями [x [0], x [1], x [2] ...]. А теперь используем циклы for для перебора ключей и значений. Но проблема возникает, когда я устанавливаю значение (которое является элементом списков x, y, z) на «» (что заставляет этот элемент исчезать на доске (x, y, z)), это не работает. Это не делает value = "" в board (). Вот код, который я пробовал, но он не работает:

# 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!")

Пожалуйста, посмотрите, где ошибка. И подскажи, как это исправить. Если есть другой способ сократить код, это будет оценено.

Ответы [ 3 ]

1 голос
/ 18 июня 2020

Я внес небольшие изменения в вашу доску. Я меняю воспроизводимый ход на 'x', поэтому при печати он будет показывать, какие из них завершены, а какие еще не завершены.

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!")

Вы не можете изменять элементы списка, используя строковое выражение, например 'x[0]'. Если вы измените свою строку на такую ​​'x[0] = " "'. и теперь используйте exec() для выполнения строкового выражения. Будет обновлено значение 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 голос
/ 18 июня 2020

Я сделал код с pandas и numpy, взгляните на него! Мне удалось сократить его до 31 строки кода, почти то, что вы хотели.

Я создал класс (Board), в котором есть фрейм данных (переменная доски), который определяет позиции на вашей доске, в методе move (self) он проверяет, действителен ли ход, ища входное значение в фрейме данных (доске), если оно найдено, обновите значение до '', иначе оно вернется к входу. Немного сложно добраться до метода game_over, но я уверен, что вы сможете следить за кодом. Надеюсь, вам понравится этот код!

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 голос
/ 18 июня 2020

Оптимизация кода обычно принадлежит сайту code review. Всего несколько входов ...

Не уверен, что я понял все ваши намерения, но этот подход кажется слишком сложным.

  1. Просто имейте один объект, который представляет вашу доску, я ' d выбрал List[List], а затем вместо сопоставления символа с каждым полем (что ограничивает вас в размере поля) позволяет пользователю вводить два целых числа для идентификации выбранного поля.
  2. Нет необходимости отслеживать воспроизводимые элементы в другом списке, просто проверьте, можно ли играть в поле на вашей доске.
  3. Я бы сократил использование глобальных переменных в функциях до минимума, это позволяет вам, например, перемещать их в отдельные файлы.
  4. Вы делаете много ненужных преобразований типов, почему move должен иметь тип List?

Или ваш valid_move можно было бы упростить до

def valid_move(a, b, c, d):  # Check for validity of moves
    return (a in b or a in c or a in d)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...