【问题标题】:Why isn't this code working properly? [closed]为什么这段代码不能正常工作? [关闭]
【发布时间】:2014-03-16 01:37:37
【问题描述】:

这快把我逼疯了,我正在开发一个电路仿真程序,每次我提出有关它的问题时它都会关闭。

我非常需要帮助,但我的问题在任何人帮助我回答之前就解决了。

不管怎样,问题出在这里: 其实我也不知道是什么问题,这段代码有问题,我也不知道是什么问题?一切看起来都很好,我找不到任何错误,但它就是无法正常工作。

在这个程序中,有电线和电源,当我将电源放在电线旁边时,我希望它有电,并且所有连接的电线也有电,但是这个程序表现出非常奇怪的行为除了我认为它会做的事情之外,做所有事情。我希望电线在有电源连接时点亮,并在没有电源时禁用。当我放置电源时它们会亮起,但当我放置更多电线时,它们都会被禁用,我似乎无法弄清楚为什么。

(深红色=通电黑色=未通电) 这是当我在电源旁边放置一根电线时:

然后我添加更多:

代码如下:

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()

请帮帮我!我很伤心。

【问题讨论】:

  • 尽量具体。您收到的确切错误消息是什么?
  • “除了我认为它会做的事情之外,做所有事情”是极其无信息的。我们无事可做。
  • 您生气/不高兴的事实与此无关。您的问题将一直关闭,直到您愿意根据the guidelines 发布它。
  • 发布一个非常简单的示例,清楚地展示了问题......以及问题的确切含义
  • for b in [b for b in blocks if b is not self] 可以缩短为 for b in blocks if b is not self

标签: python pygame circuit


【解决方案1】:

这里有几个问题。首先,眼前的问题。

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 中已撤消。

不要尝试在any 调用之外使用b,而是将测试放在里面:

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 来确定哪些块被供电。

【讨论】:

  • 从现在开始,这已经是一大堆了!谢谢!太糟糕了,很多人已经对这个问题投了反对票。
  • @SamTubb:老实说,在你编辑之前这是一个非常糟糕的问题。如果您将编辑中的信息包含在原始版本中,您会得到更好的响应。
  • 好的,在我继续之前的最后一个问题,我不明白你为什么要测试 if not b.rect.collidepoint(self.rect.left,self.rect.top-5): 对不在它上面的块进行测试实际上有什么作用?
  • @SamTubb:我认为这是我犯的一个错误。正在修复...
  • @SamTubb:我在说“修复”后再次编辑,因为我搞砸了两次。第二次忘记删了一些nots。
猜你喜欢
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 2017-08-22
相关资源
最近更新 更多