In function kein Zugriff auf Global definierte Variablen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Huhngut
User
Beiträge: 4
Registriert: Donnerstag 26. September 2019, 14:55

Hallo,
Ich bin noch ein Python Anfänger aber eigentlich kann ich Programmieren

Also in meiner function eattry habe ich keinen Zugriff auf die fetten Variablen appleX und appleY.
Ich denke diese werden als Parameter angesehen.
Versucht habe ich schon Game.appleX etc Meine Datei heißt Game.py

Danke für jede Hilfe

/edit Die Variablen konnte ich in den Code Parametern nicht fett machen

Code: Alles auswählen

import pygame
import sys
import random

from Game import appleY

pygame.init()


def frame_event_manager(eventlist):
    for event in eventlist:
        if event.type == pygame.QUIT:
            exit()
        elif event.type == pygame.KEYDOWN:
            key_manager(event.key)


def key_manager(key):
    if key == pygame.K_w:
        move_up()
    elif key == pygame.K_a:
        move_left()
    elif key == pygame.K_s:
        move_down()
    elif key == pygame.K_d:
        move_right()


def move():
    for bodypart in reversed(range(1, len(snake))):
        newX = (snake[bodypart - 1][0])
        newY = (snake[bodypart - 1][1])
        snake[bodypart] = (newX, newY)


def move_up():
    move()
    newX = snake[0][0]
    newY = snake[0][1] - 50
    snake[0] = (newX, newY)


def move_down():
    move()
    newX = snake[0][0]
    newY = snake[0][1] + 50
    snake[0] = (newX, newY)


def move_left():
    move()
    newX = snake[0][0] - 50
    newY = snake[0][1]
    snake[0] = (newX, newY)


def move_right():
    move()
    newX = snake[0][0] + 50
    newY = snake[0][1]
    snake[0] = (newX, newY)


def exit():
    pygame.quit()
    sys.exit()


def eattry():
    if snake[0][0] ==appleX & snake[0][1] == appleY]:
        # newX = snake[len(snake)][0] - 50
        # newY = snake[len(snake)][1]
        snake.append((300, 300))
        appleX = random.randint(0, 19) * 50
        appleY = random.randint(0, 19) * 50


frame = pygame.display.set_mode((1000, 1000))
applecolor = (0, 255, 0)
bodycolor = (0, 0, 255)
headcolor = (255, 0, 0)
appleX = random.randint(0, 19) * 50
appleY = random.randint(0, 19) * 50

snake = [(0, 0), (0, 50), (0, 100)]

while True:
    print(appleX)
    frame_event_manager(pygame.event.get())
    frame.fill((0, 0, 0))
    pygame.draw.rect(frame, applecolor, (appleX, appleY, 50, 50))

    eattry()
    pygame.draw.rect(frame, headcolor, (snake[0][0], snake[0][1], 50, 50))
    for bodypart in range(1, len(snake)):
        x = snake[bodypart][0]
        y = snake[bodypart][1]
        pygame.draw.rect(frame, bodycolor, (x, y, 50, 50))

    pygame.display.update()
Huhngut
User
Beiträge: 4
Registriert: Donnerstag 26. September 2019, 14:55

Ok habe die Lösung gefunden
einfach
global appleX
global appleY
an den anfang der methode schreiben
Benutzeravatar
__blackjack__
User
Beiträge: 13069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Huhngut: Man verwendet keine globalen Variablen. ``global`` ist keine Lösung! Für nichts! Zumindest solange man Programmieranfänger ist. Und Du bist Anfänger, solange Du ``global`` für eine Lösung hältst! Egal für was! 🙂 Alles was Funktionen und Methoden ausser Konstanten benötigen sollte als Argument(e) übergeben werden.

Namenskonvention ist klein_mit_unterstrichen für alles ausser Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Also `apple_x` statt `appleX`, und so weiter. Die `move()`-Funktion macht etwas unpythonische: Per Index in einer Schleife auf Listenelemente zugreifen. An der Stelle würde man einfach eine neue Liste erstellen mittels „slicing“-Syntax. Oder man verwendet eine `queue.Queue` anstelle einer Liste, da kann man an beiden Enden effizient Elemente anfügen und entfernen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Huhngut hat geschrieben: Sonntag 13. Oktober 2019, 12:27

Code: Alles auswählen

def eattry():
    if snake[0][0] ==appleX & snake[0][1] == appleY]:
        [...]
Das sieht falsch aus. Du möchtest vermutlich kein & für ein bitweises Und verwenden sondern mit and ein logisches Und haben.

Und nein, das führt nicht unbedingt zum gleichen Resultat:

Code: Alles auswählen

>>> 2 == 3 & 2
True
>>> 2 == 3 and 2
False
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Auf Modul-Ebene sollte es keinen ausführbaren Code geben, sondern nur Funktionsdefinitionen oder ähnliches. Alles ab Zeile 78 (und des pygame.init) sollten eine Funktion namens `main` wandern. Dann läufst Du auch nicht in Gefahr, aus Versehen globale Variablen zu benutzen. Denn globale Variablen haben in einem ordentlichen Programm nichts verloren, weil sie den Programmfluß undurchsichtig machen und Fehler schwer zu entdecken sind.

In Python gibt es Module und die Hauptdatei. Wenn die Hauptdatei `Game.py` auch noch als Modul importiert wird (so wie Du es versucht hast), dann sind das zwei unabhängige Namensräume, heißt, die globalen Variablen im einen Modul haben nichts mit den globalen Variablen im anderen zu tun. Das kann verwirrend sein und ist noch ein Grund, warum man keine globalen Variablen benutzen sollte.

sys.exit sollte in einem Programm auch nicht vorkommen. Der natürliche Weg, ein Programm zu beenden, ist, dass es am Ende der main-Funktion ankommt. Das kann man einfach dadurch machen, dass die while-Schleife eine Abbruchbedingung bekommt.
Fixe Zahlenwerte schreibt man am besten als KONSTANTEN an den Anfang der Datei, dann kann man sie leicht ändern und muß, nicht wie bei der Pixel-Größe, diese an 18 Stellen im Programm verstreut ändern.

Die `move_xxx`-Funktionen sind fast identisch und könnten mit zwei Parametern für die Richtung zu einer zusammengefasst werden.

Alles in allem könnte das dann so aussehen:

Code: Alles auswählen

import pygame
import random
from collections import deque

APPLE_COLOR = (0, 255, 0)
BODY_COLOR = (0, 0, 255)
HEAD_COLOR = (255, 0, 0)
TILE_SIZE = 10
FIELD_SIZE = 20

def move(snake, dx, dy):
    """ Note: snake is modified """
    x, y = snake[0]
    snake.appendleft((x + dx, y + dy))
    snake.pop()

def key_manager(snake, key):
    """ Note: snake is modified """
    if key == pygame.K_w:
        move(snake, 0, -1)
    elif key == pygame.K_a:
        move(snake, -1, 0)
    elif key == pygame.K_s:
        move(snake, 0, 1)
    elif key == pygame.K_d:
        move(snake, 1, 0)

def frame_event_manager(snake, eventlist):
    """ Note: snake is modified """
    for event in eventlist:
        if event.type == pygame.QUIT:
            return False
        elif event.type == pygame.KEYDOWN:
            key_manager(snake, event.key)
    return True

def eattry(snake, apple):
    """ Note: snake is modified """
    if snake[0] == apple:
        snake.append((300, 300))
        apple = (random.randrange(FIELD_SIZE), random.randrange(FIELD_SIZE))
    return apple

def main():
    pygame.init()
    frame = pygame.display.set_mode((FIELD_SIZE * TILE_SIZE, FIELD_SIZE * TILE_SIZE))

    snake = deque([(0, 0), (0, 1), (0, 2)])
    apple = (random.randrange(FIELD_SIZE), random.randrange(FIELD_SIZE))
    while frame_event_manager(snake, pygame.event.get()):
        frame.fill((0, 0, 0))
        pygame.draw.rect(frame, APPLE_COLOR, (apple[0]*TILE_SIZE, apple[1]*TILE_SIZE, TILE_SIZE, TILE_SIZE))

        apple = eattry(snake, apple)
        color = HEAD_COLOR
        for x,y in snake:
            pygame.draw.rect(frame, color, (x*TILE_SIZE, y*TILE_SIZE, TILE_SIZE, TILE_SIZE))
            color = BODY_COLOR
        pygame.display.update()
    pygame.quit()

if __name__ == '__main__':
    main()
Antworten