2016-01-07 2 views
3

Im пишет алгоритм в Python, который играет this.Создание списка словарей, где каждый словарь содержит другой словарь как значения

Текущее состояние доски плитки в игре является словарем в виде:

{ 
    <tile_id>: { 
       'counters': <number of counters on tile or None>, 
       'player': <player id of the player who holds the tile or None>, 
       'neighbours': <list of ids of neighbouring tile> 
       }, 
       ... 
} 

У меня есть еще один словарь, который хранит все мои плитки, которые являются «полной» (то есть плиткой, которая имеет один счетчик меньше, чем его число соседей, и где player - это я). Этот словарь, full_tiles, в той же форме, что и словарь board выше.

Теперь я пытаюсь создать список, chains, где каждый элемент в списке - это словарь моих полных фрагментов, которые соседствуют по крайней мере с одной другой полной плиткой (т. Е. Цепочкой полных фрагментов). Так что это будет список всех моих отдельных цепочек на доске.

Вот мой код до сих пор:

for tile_id, tile in full_tiles.items(): #iterates through all full tiles 
    current_tile = {tile_id : tile}  #temporarily stores current tile 
    if not chains:      #if chains list is empty 
     chains.append(current_tile)  #begin list 
    else:        #if list is not empty 
     for index, chain in enumerate(chains):   #iterate though list of chains 
      if not (current_tile in chain):    #if current tile is not in current chain 
       for tile_id2, tile2 in chain.items():  #iterate through tiles in current chain 
        for neighbour in tile2["neighbours"]: #iterate through each neighbour of current tile 
                  #neighbour is in the form of tile_id 
         if neighbour in chain:   #if current tile's neighbour is in chain 
          chain[tile_id] = tile   #add tile to chain 

Это очень трудно для меня, чтобы проверить и отладить свой код и проверить, если он работает правильно, как код может быть запущен только в приложении, которое симулирует игра. Как вы можете видеть, в этом блоке кода довольно много происходит со всеми вложенными циклами, которые трудно выполнить. Кажется, я не могу сразу подумать, поэтому я не могу определить, будет ли этот беспорядок, честно говоря, работать, как я надеюсь.

Пока я пишу это, я только что понял, что - в строке 7 этого кода - я проверяю, не текут ли текущая плитка в текущей цепочке, и поэтому будут пересекающиеся цепи, которые, конечно, будут быть беспорядком. Вместо этого мне нужно сначала проверить, находится ли текущая плитка в любых цепей, а не только одна.

Помимо этой ошибки, мой код достигнет того, что я пытаюсь? Или вы можете порекомендовать более простой, быстрый способ сделать это? (Должно быть!)

Также, дайте мне знать, если я не дал достаточной информации о том, как выполняется код, или если мне нужно что-то объяснить, например, содержание словаря board.

Благодарим за любую помощь заранее.

EDIT: К сожалению, я был под ограничения времени для завершения этого проекта, и как это был мой первый раз когда-либо работать с Python, я в настоящее время не хватает знаний на языке, чтобы оптимизировать свое решение, используя источники, приведенные ниже , Вот мой окончательный крайне уродливый и грязный решение этой проблемы, которое в итоге отлично работало и не было ужасно неэффективным, учитывая небольшой набор данных, на котором работает код.

for x in range(0, len(my_hexplode_chains) - 1): 
    match_found = False 
    for y in range(x + 1, len(my_hexplode_chains)): 
     for tile_id_x, tile_x in my_hexplode_chains[x].items():    #compare each chain in list 
      for tile_id_y, tile_y in my_hexplode_chains[y].items():   #to every other chain 
       for neighbour in tile_x["neighbours"]:      #if tiles in different lists 
        if neighbour == tile_id_y:        #are neighbours 
         match_found = True 
         my_hexplode_chains[x].update(my_hexplode_chains[y]) #append one chain to the other 
         del my_hexplode_chains[y]       #delete appended chain 
       if match_found:            #continue loop at next chain 
        break             #very ugly way to do this 
      if match_found: 
       break 
     if match_found: 
      break 
    if match_found: 
     break 
+1

Это проблема графа. Графики в Python наиболее легко представлены в виде словарей узлов, пар пар элементов. Вероятно, вы могли бы сделать это, используя простые советы. – erip

+0

@erip К сожалению, я новичок в Python и только начал изучать его, чтобы завершить эту задачу. Я действительно не понимаю, что вы рекомендовали, но я буду исследовать его сейчас. Спасибо – KOB

+1

Определенно не прискорбно. :) Я рад видеть, что вы учитесь! [Это] (http://python-3-patterns-idioms-test.readthedocs.org/en/latest/Comprehensions.html) - довольно хорошее описание понятий. Если вы знакомы с нотацией set-builder в математике, это похоже на это. – erip

ответ

1

Как насчет этой оптимизации?

def find_match (my_hexplode_chains): 

    x = 0 
    len_chain = len(my_hexplode_chains) 
    while x <= len_chain: 
     y = x + 1 
     for tile_id_x, tile_x in my_hexplode_chains[x].items(): 
      for tile_id_y, tile_y in my_hexplode_chains[y].items(): 
       if tile_id_y in tile_x["neighbours"]: 
        my_hexplode_chains[x].update(my_hexplode_chains[y]) 
        del my_hexplode_chains[y] 
        return True 
     x += 1 
    return False 

Вы можете передать эту функцию после каждого хода в вашей игре и проследить выход.

+0

Это лучшее и наиболее эффективное решение, но я уверен, что существует определенно менее кластерный способ структурирования этого с использованием некоторой структуры данных. – KOB

Смежные вопросы