2014-02-16 4 views
-3

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

Мне очень нужна помощь, но мои вопросы закрываются, прежде чем кто-нибудь сможет мне помочь.

В любом случае, вот в чем проблема: На самом деле, я не знаю, в чем проблема, что-то не так с этим кодом, и я понятия не имею, что это такое? Все выглядит отлично, я не могу найти никаких ошибок, но он просто не работает.

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

(темно-красный = питание черный = не работает) Здесь когда я помещаю один провод рядом с источником питания:

enter image description here

Но потом я добавить еще и:

enter image description here

Вот код:

import pygame 
from pygame.locals import * 

pygame.init() 

screen=pygame.display.set_mode((640,480)) 
blocks=[] 
class PowerSource(object): 
    def __init__(self,pos): 
     self.posx=pos[0] 
     self.posy=pos[1] 
     self.rect=pygame.Rect(self.posx,self.posy,32,32) 
     self.powered=True 
    def update(self): 
     pygame.draw.rect(screen, (255,0,0), self.rect, 0) 
    def repos(self): 
     pass 
class Circuit(object): 
    def __init__(self,pos): 
     self.powered=False 
     self.posx=pos[0] 
     self.posy=pos[1] 
     self.rect=pygame.Rect(self.posx,self.posy,32,32) 
     self.topped=False 
     self.lefted=False 
     self.righted=False 
     self.bottomed=False 
    def update(self): 
     self.powered=False 
     if any(b.rect.collidepoint(self.rect.left,self.rect.top-5) for b in [b for b in blocks if b is not self]): 
      if b.powered==True: 
       self.powered=True 
     if any(b.rect.collidepoint(self.rect.left,self.rect.top+38) for b in [b for b in blocks if b is not self]): 
      if b.powered==True: 
       self.powered=True 
     if any(b.rect.collidepoint(self.rect.left-5,self.rect.top) for b in [b for b in blocks if b is not self]): 
      if b.powered==True: 
       self.powered=True 
     if any(b.rect.collidepoint(self.rect.right+5,self.rect.top) for b in [b for b in blocks if b is not self]): 
      if b.powered==True: 
       self.powered=True 
     if not self.powered: 
      pygame.draw.rect(screen, (0,0,0), self.rect, 0) 
     else: 
      pygame.draw.rect(screen, (200,0,0), self.rect, 0) 
while True: 
    place=1 
    screen.fill((255,255,255)) 
    mse=pygame.mouse.get_pos() 
    mse=((mse[0]/32)*32,(mse[1]/32)*32) 
    pressed=pygame.mouse.get_pressed() 
    if pressed==(1,0,0): 
     pressed='L' 
    elif pressed==(0,0,1): 
     pressed='R' 
    for b in blocks: 
     b.update() 
    pygame.draw.rect(screen, (255,0,0), (mse[0],mse[1],32,32), 2) 
    for e in pygame.event.get(): 
     if e.type==QUIT: 
      exit() 
    key=pygame.key.get_pressed() 
    if key[K_SPACE]: 
     for b in blocks: 
      if b.rect.collidepoint(mse): 
       place=0 
     if place==1: 
      blocks.append(PowerSource(mse)) 
    if pressed=='L': 
     for b in blocks: 
      if b.rect.collidepoint(mse): 
       place=0 
     if place==1: 
      blocks.append(Circuit(mse)) 

    elif pressed=='R': 
     for b in blocks: 
      if b.rect.collidepoint(mse): 
       blocks.remove(b) 
    pygame.display.flip() 

Пожалуйста, помогите мне! Я очень расстроен.

+0

Старайтесь быть как можно более конкретными. Какое точное сообщение об ошибке вы получаете? –

+3

«Делая все, кроме того, что я думал, что это будет делать», мучительно неинформативно. Нам нечего делать дальше. – mhlester

+0

Я задал несколько вопросов по этому вопросу, я думаю, люди начнут путаться. Позвольте мне отредактировать его, пожалуйста, не закрывайте это. –

ответ

2

Здесь есть несколько проблем. Во-первых, ближайшая проблема.

В update, где, как вы думаете, b исходит из этой строки?

 if b.powered==True: 

Это не исходит от одной из этих частей:

if any(b.rect.collidepoint(self.rect.left,self.rect.top-5) for b in [b for b in blocks if b is not self]): 
     ^             ^

Это идет от последней итерации этого списка понимания:

[b for b in blocks if b is not self] 

Последние не-я блок в блоке список используется для всех тестов if b.powered == True. Переменная цикла выражения генератора недоступна вне выражения генератора, а переменная цикла для понимания списка доступна только вне понимания списка из-за конструктивного решения, принятого по соображениям производительности, и отменена на Python 3.

Вместо того, чтобы пытаться использовать b вне any вызова, поставить тест внутри:

if any(b.powered and b is not self and b.rect.collidepoint(self.rect.left,self.rect.top-5) for b in blocks): 

или так как это довольно огромная очередь, разделить это на явную петлю вместо any вызова.Пока вы на него, вы можете объединить 4 any вызовов в один проход по списку:

for b in blocks: 
    if not b.powered: 
     continue 
    if b is self: 
     # You don't actually need this test. 
     continue 

    adjacent = False 
    if b.rect.collidepoint(self.rect.left,self.rect.top-5): 
     adjacent = True 
    if b.rect.collidepoint(...): 
     adjacent = True 
    # and the other two adjacency checks 
    ... 
    if adjacent: 
     self.powered = True 
     break 

Теперь, другие проблемы. Логика включения питания проверяет только смежные блоки. Это означает, что если блок размещен отдельно от источника питания и затем подключен, может потребоваться много обновлений для блока, чтобы реализовать его мощность приема. Кроме того, если блок отключен от питания или блок питания удален, блок никогда не может отключиться, так как всякий раз, когда он выглядит, все его соседи питаются. Это потребует изменения вашего алгоритма. Я рекомендую использовать flood fill от источников питания, чтобы определить, какие блоки питаются.

+0

С этого момента это делает намного больше! Спасибо! Слишком плохие тонны людей уже проголосовали за этот вопрос. –

+0

@SamTubb: Честно говоря, это был довольно плохой вопрос, прежде чем вы его отредактировали. Если бы вы включили информацию из редактирования в исходной версии, вы бы получили лучший ответ. – user2357112

+0

Хорошо, последний вопрос, прежде чем двигаться дальше, я не понимаю, почему вы тестируете 'if not b.rect.collidepoint (self.rect.left, self.rect.top-5):' что делает тестирование для блока не будучи выше этого на самом деле? –

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