How can I stop turtle from repeating the same movements?

Viewed 101

I was trying to create Pac-man game and set random movement to enemies. But when I run it. It repeats same movements how can I stop the enemies making same movements and make enemies move all around the map. Please slove my problem and tell me why this thing happen. """"""""Press "space bar" so that the game starts""""""""

from turtle import Screen, Turtle
import random
FONT = ('Arial', 18, 'bold')
runs=False
cruns=False
notout=True
def computermove(game):
    for i in game.enemy:
        a=game.enemy[i]
        random.choice([game.enemy[i].go_up(game),game.enemy[i].go_down(game),game.enemy[i].go_left(game),game.enemy[i].go_right(game)])
    
class Creator(Turtle):
    def __init__(self, row, col, sprite, colorcode, width, height, game):
        self.game=game
        super().__init__(shape=sprite)
        self.row = row
        self.col = col
        
        self.color(colorcode)
        self.shapesize(width, height, 3)
        self.penup()
        self.speed('fastest')
        self.goto(self.coords(row, col))
    @staticmethod
    def coords(row, col):
        x = col * 25 - 250
        y = 137.5 - row * 25

        return x, y
    
    @staticmethod
    def inv_coords(x, y):
        col = round((x + 250) / 25)
        row = round((137.5 - y) / 25)

        return row, col

    def go_left1(self):
        global runs
        if runs==False:
            runs=True
            position = self.xcor() - 25, self.ycor()

            key = self.inv_coords(*position)

            if key not in self.game.wall:

                if ((key in self.game.food)and(self.game.food[key].isvisible()==True)):
                    self.game.food[key].hideturtle()
                    self.game.score += 1
                    self.game.running.writer.clear()
                    self.game.running.writer.write("score:{}".format(self.game.score), font=FONT)
                    if self.game.score==102:
                        screen.clear()
                        self.game.running.writer.clear()
                        self.game.running.writer.goto(0,0)
                        slef.game.running.writer.write('game over')
                self.goto(self.coords(*key))
            runs=False


    def go_right1(self):
        global runs
        if runs==False:
            runs=True

            position = self.xcor() + 25, self.ycor()

            key = self.inv_coords(*position)

            if key not in self.game.wall:

                if ((key in self.game.food)and(self.game.food[key].isvisible()==True)):
                    self.game.food[key].hideturtle()
                    self.game.score += 1
                    self.game.running.writer.clear()
                    self.game.running.writer.write("score:{}".format(self.game.score), font=FONT)
                    if self.game.score==102:
                        screen.clear()
                        self.game.running.writer.clear()
                        self.game.running.writer.goto(0,0)
                        self.game.running.writer.write('game over')

                self.goto(self.coords(*key))

            runs=False
    def go_up1(self):
        global runs
        if runs==False:
            runs=True

            position = self.xcor(), self.ycor() + 25

            key = self.inv_coords(*position)

            if key not in self.game.wall:

                if ((key in self.game.food)and(self.game.food[key].isvisible()==True)):
                    self.game.food[key].hideturtle()
                    self.game.score += 1
                    self.game.running.writer.clear()
                    self.game.running.writer.write("score:{}".format(self.game.score), font=FONT)
                    if self.game.score==102:
                        screen.clear()
                        self.game.running.writer.clear()
                        self.game.running.writer.goto(0,0)
                        self.game.running.writer.write('game over')

                self.goto(self.coords(*key))
            runs=False

    def go_down1(self):
        global runs
        if runs==False:
            runs=True

            position = self.xcor(), self.ycor() - 25

            key = self.inv_coords(*position)

            if key not in self.game.wall:

                if ((key in self.game.food)and(self.game.food[key].isvisible()==True)):
                    self.game.food[key].hideturtle()
                    self.game.score += 1
                    self.game.running.writer.clear()
                    self.game.running.writer.write("score:{}".format(self.game.score), font=FONT)
                    if self.game.score==102:
                        screen.clear()
                        self.game.running.writer.clear()
                        self.game.running.writer.goto(0,0)
                        self.game.running.writer.write('game over')

                self.goto(self.coords(*key))
            runs=False

class Enemy_creator(Turtle):
    def __init__(self, row, col, sprite, colorcode, width, height):
        super().__init__(shape=sprite)
        self.row = row
        self.col = col
        
        self.color(colorcode)
        self.shapesize(width, height, 3)
        self.penup()
        self.speed('slowest')
        self.goto(self.coords(row, col))
    @staticmethod
    def coords(row, col):
        x = col * 25 - 250
        y = 137.5 - row * 25

        return x, y
    
    @staticmethod
    def inv_coords(x, y):
        col = round((x + 250) / 25)
        row = round((137.5 - y) / 25)

        return row, col

    def go_left(self,game):
        global cruns, notout
        if cruns==False:
            cruns=True
            self.game=game
            position = self.xcor() - 25, self.ycor()

            key = self.inv_coords(*position)
            if position == (game.player[9,9].xcor(),game.player[9,9].ycor()):
                screen.clear()
                notout=False
            if key not in game.wall:

                
                self.goto(self.coords(*key))
            
            
            cruns=False
    def go_right(self,game):
        global cruns,notout
        
        if cruns==False:
            cruns=True
            self.game=game

            position = self.xcor() + 25, self.ycor()

            key = self.inv_coords(*position)
            if position == (game.player[9,9].xcor(),game.player[9,9].ycor()):
                screen.clear()
                notout=False

            if key not in game.wall:

                
                self.goto(self.coords(*key))
            cruns=False
    def go_up(self,game):
        global cruns,notout
        
        if cruns==False:
            cruns=True
            self.game=game

            position = self.xcor(), self.ycor() + 25

            key = self.inv_coords(*position)
            if position == (game.player[9,9].xcor(),game.player[9,9].ycor()):
                screen.clear()
                notout=False

            if key not in game.wall:

                

                self.goto(self.coords(*key))
            cruns=False
    def go_down(self,game):
        global cruns,notout
        
        if cruns==False:
            cruns=True
            self.game=game

            position = self.xcor(), self.ycor() - 25

            key = self.inv_coords(*position)
            if position == (game.player[9,9].xcor(),game.player[9,9].ycor()):
                screen.clear()
                notout=False

            if key not in game.wall:

                

                self.goto(self.coords(*key))
            
            cruns=False
class Running:
    def __init__(self, game):
        self.game = game

        self.writer = Turtle(visible=False)
        self.writer.penup()
        self.writer.color('blue')
        self.writer.goto(200, 170)
        self.writer.write("score:{}".format(game.score), font=FONT)

        screen.onkey(game.player[9, 9].go_left1, 'a')
        screen.onkey(game.player[9, 9].go_right1, 'd')
        screen.onkey(game.player[9, 9].go_up1, 'w')
        screen.onkey(game.player[9, 9].go_down1, 's')
        screen.onkey(self.movingcomputer,'space')
        screen.onkey(self.exit,'q')
        screen.listen()
    def exit(self):
        global notout
        notout=False
        exit()
    def movingcomputer(self):
        while notout:
            computermove(self.game)

class Pacman:
    def __init__(self):
        self.wall = {}
        self.player = {}
        self.food = {}
        self.enemy = {}

        self.score = 0
        screen.tracer(0)
        self.setup()
        screen.tracer(1)
        self.running = Running(self)
    def setup(self):
        for row in range(11):
            for col in range(20):
                if level[row][col] == 1:
                    self.wall[(row, col)] = Creator(row, col, 'square', 'blue', 1, 1, self)
                elif level[row][col] == 2:
                    color=random.choice(['red','green','skyblue','gray'])
                    self.enemy[(row, col)] = Enemy_creator(row, col, 'triangle', color, 1, 1)
                elif level[row][col] == 3:
                    self.player[(row, col)] = Creator(row, col, 'circle', 'yellow', 1, 1, self)
                else:
                    self.food[(row, col)] = Creator(row, col, 'circle', 'white', 0.1, 0.1, self)


level = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    [1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1],
    [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1],
    [1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1],
    [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
    [1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1],
    [1, 2, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]

screen = Screen()
screen.bgcolor('black')
game = Pacman()
screen.mainloop()
4 Answers

I finally found the solution

def computermove(game):
    for i in game.enemy:
        normal_move_logic(game.enemy[i], game)


def normal_move_logic(enemy_in, game_in):
    rn = 0
    if enemy_in.last_dir is not None and enemy_in.last_key is not None:
        if enemy_in.last_key in game_in.wall:
            random.seed(time.time())
            rn = random.randint(0, 3)
        else:
            rn = enemy_in.last_key
    else:
        random.seed(time.time())
        rn = random.randint(0, 3)
    if rn == 0:
        enemy_in.go_up(game_in)
    elif rn == 1:
        enemy_in.go_down(game_in)
    elif rn == 2:
        enemy_in.go_left(game_in)
    else:
        enemy_in.go_right(game_in)

and changed Enemy class a little bit

class Enemy_creator(Turtle):
    def __init__(self, row, col, sprite, colorcode, width, height):
        super().__init__(shape=sprite)
        self.row = row
        self.col = col

        self.color(colorcode)
        self.shapesize(width, height, 3)
        self.penup()
        self.speed('slowest')
        self.goto(self.coords(row, col))

        self.last_key = None
        self.last_dir = None

    @staticmethod
    def coords(row, col):
        x = col * 25 - 250
        y = 137.5 - row * 25

        return x, y

    @staticmethod
    def inv_coords(x, y):
        col = round((x + 250) / 25)
        row = round((137.5 - y) / 25)

        return row, col

    def go_left(self, game):
        global cruns, notout
        if cruns == False:
            cruns = True
            self.game = game
            position = self.xcor() - 25, self.ycor()

            key = self.inv_coords(*position)
            if position == (game.player[9, 9].xcor(), game.player[9, 9].ycor()):
                screen.clear()
                notout = False
            if key not in game.wall:
                self.goto(self.coords(*key))
            self.last_key = key
            self.last_dir = 2

            cruns = False

    def go_right(self, game):
        global cruns, notout

        if cruns == False:
            cruns = True
            self.game = game

            position = self.xcor() + 25, self.ycor()

            key = self.inv_coords(*position)
            if position == (game.player[9, 9].xcor(), game.player[9, 9].ycor()):
                screen.clear()
                notout = False

            if key not in game.wall:
                self.goto(self.coords(*key))

            self.last_key = key
            self.last_dir = 3
            cruns = False

    def go_up(self, game):
        global cruns, notout

        if cruns == False:
            cruns = True
            self.game = game

            position = self.xcor(), self.ycor() + 25

            key = self.inv_coords(*position)
            if position == (game.player[9, 9].xcor(), game.player[9, 9].ycor()):
                screen.clear()
                notout = False

            if key not in game.wall:
                self.goto(self.coords(*key))

            self.last_key = key
            self.last_dir = 0
            cruns = False

    def go_down(self, game):
        global cruns, notout

        if cruns == False:
            cruns = True
            self.game = game

            position = self.xcor(), self.ycor() - 25

            key = self.inv_coords(*position)
            if position == (game.player[9, 9].xcor(), game.player[9, 9].ycor()):
                screen.clear()
                notout = False

            if key not in game.wall:
                self.goto(self.coords(*key))
            self.last_key = key
            self.last_dir = 1
            cruns = False

And it works great!

It looks like

def computermove(game):
    for i in game.enemy:
        a=game.enemy[i]
        random.choice([game.enemy[i].go_up(game),game.enemy[i].go_down(game),game.enemy[i].go_left(game),game.enemy[i].go_right(game)])
    

runs every movement option once (e.g. game.enemy[i].go_up(game)), gathers all the return values (which are all None) and then chooses a random None from a list of four None values ;-)

maybe try

movement = random.choice([a.go_up, a.go_down, a.go_left, a.go_right])
movement(game)

so that you first select the method at random, and then execute it.

When you add () after the name of a defined function, you are telling python to call it when the program reaches that line. Yes, even if you store it in a list, like how

[print("test")]

returns

test
[None]

where the outputted test is the result of the print() function, and the None is the returned value of the print() call.

So simply move the brackets to the outside of the random.choice() function. I've also made use of the dict.values() function, as the keys weren't used in the code:

def computermove(game):
    for a in game.enemy.values():
        random.choice([a.go_up, a.go_down, a.go_left, a.go_right])(game)

Note that in your code, you defined the a variable, but never used it in the function.

Insert

random.seed()

before your

random.choice([game.enemy[i].......

command to put the random generator to a random state.

Related