1

所以作为我在 Code Academy 之外的第一个 Python 项目,我决定在 pygame 上制作一个基本的分子动力学模拟器。它可以正常工作一段时间,但是一旦电子开始移动得太快,并且将所有其他电子从它们的原子中剥离出来,我就会在标题中看到 TypeError。我不知道这是从哪里来的,只有在程序运行了足够长的时间让我搞砸了所有物理之后才会出现。

现在我知道错误告诉我我正在尝试将列表传递到我不应该传递的地方,但是我查看了程序并且无法弄清楚在哪里。错误出现在告诉电子如何绕其原子运行的位中,该位angle = findA(particles[el], particles[nuc]) + 0.001由靠近末尾的代码块控制,该代码块告诉程序以何种顺序进行物理,每个电子的轨道列表是由另一个点控制,以此类推。

所以我决定只给你所有的代码。

import sys, pygame, math
from pygame.locals import *

pygame.init()
sizeScreen = width, height = 1000, 700
sizeMenu = width, height = 652, 700


e = 1.6 * 10 ** -19
particles = {}
mx, my = 0, 0
selected = []

def findOrbital(el):
    for a in particles:
        if a != el and particles[a][4] != 'el':
            if findD(particles[el], particles[a]) < 5 * 10 ** -11 and PTI[particles[a][4]][7] > len(particles[a][5]):
                particles[a][5].append(el)
                particles[el][5].append(a)



def searcher(List, item):
    for a in List:
        if a == item:
            return True
    return False

def moveAtEls(el, nuc):
    angle = findA(particles[el], particles[nuc]) + 0.001
    particles[el][0] = particles[nuc][0] + 50 * math.cos(angle)
    particles[el][1] = particles[nuc][1] + 50 * math.sin(angle)


def check(each):
    if particles[each][0] < 175:
        particles[each][2] = -particles[each][2]
        particles[each][0] = 175
    elif particles[each][0] > 1000:
        particles[each][2] = -particles[each][2]
        particles[each][0] = 1000
    if particles[each][1] < 0:
        particles[each][3] = -particles[each][3]
        particles[each][1] = 0
    elif particles[each][1] > 700:
        particles[each][3] = -particles[each][3]
        particles[each][1] = 700
    if particles[each][4] == 'el':
        a = 'n'
        findOrbital(each)
        if a != 'n':
            particles[each][5].append(a)
            particles[a][5].append(each)


def findD(self, other):
    return math.hypot((self[0] - other[0]), (self[1] - other[1])) * 0.62 * 10 ** -12
def findA(self, other):
    return math.atan2((self[1] - other[1]), (self[0] - other[0]))


def move(self):
    for other in particles:
        if particles[other] != self and self[5] != particles[other] [5] and not searcher(self[5], other):
            D = findD(self, particles[other])
            if D == 0:
                self[5].append(other)
                particles[other][5].append(self)
                break
            angle = findA(self, particles[other])
            F = 8987550000 * (PTI[self[4]][4] * PTI[particles[other][4]][4] * e ** 2)/D ** 2
            a = int(F/PTI[self[4]][5])
            ax = a * math.cos(angle)
            ay = a * math.sin(angle)
            self[2] += ax/(10 ** 16)
            self[3] += ay/(10 ** 16)
    self[0] += self[2]/(10 ** 8)
    self[1] += self[3]/(10 ** 8)


pressed = ''
press = {'Katom':[2,148,2,32,0],'Knuc':[2,148,36,66,0],'Kel':[2,148,70,100,0]}

PTI = {'el':[0, 0, 0, 0, -1, 9.11 * 10 ** -31, pygame.image.load("electron.png"), 2],
'HNuc' : [185, 214, 8, 37, 1, 1.7 * 10 ** -27, pygame.image.load("nuc/HNuc.png"), 2, 1],
'HeNuc': [586, 613, 8, 37, 2, 6.6 * 10 ** -27, pygame.image.load("nuc/HeNuc.png"), 2, 2],
'LiNuc': [185, 214, 40, 69, 1, 1.16 * 10 ** -26, pygame.image.load("nuc/LiNuc.png"), 8, 1],
'BeNuc': [216, 246, 40, 69, 2, 1.53 * 10 ** -26, pygame.image.load("nuc/BeNuc.png"), 8, 2],
'BNuc' : [428, 457, 40, 69, 3, 1.84 * 10 ** -26, pygame.image.load("nuc/BNuc.png"), 8, 3],
'CNuc' : [460, 489, 40, 69, 4, 2.04 * 10 ** -26, pygame.image.load("nuc/CNuc.png"), 8, 4],
'NNuc' : [492, 520, 40, 69, 5, 2.38 * 10 ** -26, pygame.image.load("nuc/NNuc.png"), 8, 5],
'ONuc' : [523, 551, 40, 69, 6, 2.72 * 10 ** -26, pygame.image.load("nuc/ONuc.png"), 8, 6],
'FNuc' : [554, 583, 40, 69, 7, 3.23 * 10 ** -26, pygame.image.load("nuc/FNuc.png"), 8, 7],
'NeNuc': [586, 613, 40, 69, 8, 3.43 * 10 ** -26, pygame.image.load("nuc/NeNuc.png"), 8, 8]}

menu = pygame.display.set_mode(sizeMenu)
screenColor = pygame.Color(255, 255, 220)
screen = pygame.display.set_mode(sizeScreen)
edgeObj = pygame.image.load("edge.png")
addEl = [pygame.image.load('addElectron1.png'), pygame.image.load('addElectron2.png')]
addAtom = [pygame.image.load("addAtom1.png"), pygame.image.load("addAtom2.png"), pygame.image.load("atomTable.png")]
addNucleus = [pygame.image.load("addNuc1.png"), pygame.image.load("addNuc2.png"), pygame.image.load("NucTable.png")]

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit(0)

        elif event.type == MOUSEMOTION:
            mx, my = event.pos

        mouseState = pygame.mouse.get_pressed()
        if mouseState[0]:
            for key in press:
                if press[key][0] < mx <press[key][1] and press[key][2] < my < press[key][3]:
                    pressed = key
                    press[key][4] = 1

        if not mouseState[0] and pressed == 'Kel':
            particles[len(particles)] = [mx, my, 0, 0, 'el', []]
            pressed = ''
            press['Kel'][4] = 0

        if pressed != '':
            if not mouseState[0]:
                if press[pressed][0] < mx <press[pressed][1] and press[pressed][2] < my < press[pressed][3]:
                    press[pressed][4] = 2
                    pressed = ''

        if press['Knuc'][4] == 2 or press['Katom'][4] == 2:
            if  mouseState[0]:
                if 621 < mx < 651 and 2 < my < 14:
                    press['Knuc'][4] = 0
                    press['Katom'][4] = 0
                if press['Knuc'][4] == 2:
                    for nuc in PTI:
                        if PTI[nuc][0] < mx < PTI[nuc][1] and PTI[nuc][2] < my < PTI[nuc][3]:
                            press['Knuc'][4] = 0
                            selected.append(nuc)
                if press['Katom'][4] == 2:
                    for nuc in PTI:
                        if PTI[nuc][0] < mx < PTI[nuc][1] and PTI[nuc][2] < my < PTI[nuc][3]:
                            a = 0
                            selected.append(nuc)
                            while a < PTI[nuc][8]:
                                selected.append('el')
                                a += 1
                            press['Katom'][4] = 0
        if selected != []:
            if not mouseState[0]:
                a = len(particles)
                particles[a] = [mx, my, 0, 0, selected[0], [b for b in range(a+1, len(selected)-1)]]
                for item in selected:
                    if item != selected[0]:
                        particles[len(particles)] = [mx, my, 0, 0, item, [a]]
                selected = []


    for each in particles:
        check(each)
        move(particles[each])
        check(each)
        if len(particles[each][5]) > 0 and particles[each][4] == 'el':
            moveAtEls(each, particles[each][5][0])
        particles[each][5] = []

    screen.fill(screenColor)
    for a in particles:
        screen.blit(PTI[particles[a][4]][6], (particles[a][0] - 29, particles[a][1] - 31))
    menu.blit(edgeObj, (0, 0))
    menu.blit(addNucleus[press['Knuc'][4]], (2, 2))
    menu.blit(addAtom[press['Katom'][4]], (2, 2))
    menu.blit(addEl[press['Kel'][4]], (2, 2))

    pygame.display.flip()

抱歉,如果我发布所有代码会造成麻烦,但我是一个完整的 n00b,我很惊讶我在没有帮助的情况下走到了这一步。我知道整个事情很不整洁,但如果你能帮助解决这个错误,我将不胜感激。

下次我会坚持print("Hello, World!")

4

1 回答 1

1

所以,我相信正在发生的是,当执行 line 时angle = findA(particles[el], particles[nuc]) + 0.001el变量或nuc变量是某种列表,而不是单个对象。

这会引发错误,因为particles它是 dict,并且您不能将列表或任何可变类型作为 dict 中的键。

因此,鉴于此错误不会立即执行,我怀疑在某处,在一段未立即执行的代码中,您不小心传入了list某种类型的 a。


particles如果您确实打算通过使用列表作为键在 dict 中查找内容,那么您应该将列表转换为tuple第一个:元组类似于列表,但不可变,因此可以散列并用作 a 的键字典。

于 2013-10-06T16:15:35.640 回答