Altair
Altair

Reputation: 47

Instantiation fails in a python object

I have a little problem with my first experience in python. I'm working on a little game, like labyrinth. I create a class Map, when I instantiate it, works. When I tried to instantiate two times the same class I got some problems.

This is the code :

from random import randint
class Map:
    """Class that generates map"""
    width = 0
    height = 0
    map = list()
    dictLine = dict()

    def __init__(self, width, height):
        """Constructor takes width and height in input"""
        self.width = width
        self.height = height
        for i in range(0, self.width * self.height):
            self.map.append('.')
        self.__defineMap()
        self.__defineEntrance()

    def __defineMap(self):
        """Defines Map in a dict"""
        index = 0
        for i in range(0,self.height):
            self.dictLine[index] = self.map[index:index + self.width]
            index = index + self.width

    def printMap(self):
        """Function that prints Wumpus World Map"""
        for i in range(0, self.width * self.height):
            if(i % self.width == 0):
                print()
            print(self.map[i], end='   ')
        print()

    def __defineEntrance(self):
        """Random entrance defined at game start"""
        state = False
        while state is False:
            randomEntrance = randint(0,(self.width * self.height)-1)
            self.map[-self.width:]
            if randomEntrance in range(0,self.width):
                #if entrance is at the first line
                self.map[randomEntrance] = 'E'
                return True
            elif randomEntrance % self.width == 0:
                #if entrance is on the left side
                self.map[randomEntrance] = 'E'
                return True
            for key in self.dictLine.keys():
                #da vedere
                if key + self.width - 1 == randomEntrance:
                    self.map[randomEntrance] = 'E'
                    return True
            l = list()
            for key in self.dictLine.keys():
                l.append(key)
            l.sort()
            l.reverse()
            if randomEntrance in range(l[0], l[0] + self.width):
                self.map[randomEntrance] = 'E'
                return True
        return False

    def reset(self):
        self.__init__(self.width, self.height)

This is the result:

>>> map = Map(6,6)
>>> map.printMap()

.   .   .   E   .   .   
.   .   .   .   .   .   
.   .   .   .   .   .   
.   .   .   .   .   .   
.   .   .   .   .   .   
.   .   .   .   .   .  

>>> map2 = Map(7,7)
>>> map2.printMap()

.   .   .   E   .   .   .   
.   .   .   .   .   .   .   
.   .   .   .   .   .   .   
.   .   .   .   .   .   .   
.   .   .   .   .   .   .   
.   .   .   .   .   .   .   
.   .   .   E   .   .   .  

How can i solve this problem? Thank you all!

Upvotes: 1

Views: 663

Answers (2)

Fabio Menegazzo
Fabio Menegazzo

Reputation: 1249

Well, first things first.

As Max said, all your variables were created as class attribute instead of instance so any changes you make in one instance will affect the others (even those you will create). The solution is moving them to __init__.

Also, try not to use "reserved" words. map is a used as a built-in. Maybe change it to maze.

I made some quick changes on your code. There are some room for improvements but it will serve you well:

from random import randint


class Maze(object):
    """Class that generates maze"""

    def __init__(self, columns, rows):
        """Constructor takes columns and rows in input"""
        self.columns = columns
        self.rows = rows
        self.reset()

    def reset(self):
        # Building maze.
        self.__maze_cell_mapping = []
        for i in xrange(self.columns):
            for j in xrange(self.rows):
                self.__maze_cell_mapping.append((i, j))

        # Defining entrance.
        self.__entrance = None
        self.__define_entrance()

    def __define_entrance(self):
        """Random entrance defined at game start"""
        while self.__entrance is None:
            cell_id = randint(0, len(self.__maze_cell_mapping))
            if self.__is_boundary(cell_id):
                self.__entrance = self.__maze_cell_mapping[cell_id]

    def __is_boundary(self, cell_id):
        """
        :param int cell_id:
            ID of the cell to check.

        :rtype: bool
        :returns:
            ``True`` if given ``cell_id`` is at maze boundary.
        """
        column, row = self.__maze_cell_mapping[cell_id]
        if column == 0 or column == self.columns - 1:
            return True
        elif row == 0 or row == self.rows - 1:
            return True
        else:
            return False

    def print_maze(self):
        """Function that prints Wumpus World Maze"""
        result = [
            ['.'] * self.columns
            for _i in xrange(self.rows)
        ]

        column, row = self.__entrance
        result[column][row] = 'E'

        for row in result:
            print('   '.join(row))

Hope it helps!

Upvotes: 0

Max Noel
Max Noel

Reputation: 8910

map is a class attribute (shared between all instances of the class), not an instance attribute.

If that's not the behavior you want, change it so that it's an instance attribute -- that is, move the map = list() part to inside __init__. You'll probably want to do the same to width, height and dictLine.

Upvotes: 1

Related Questions