How does the Python’s * operator work? [duplicate] - list

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 9 years ago.
I use the python's * to create a 2-dimetion list [[0]*10]*10 with a default value 0.
But when I set the first element to 1,all the elements of the first colum happend to be 1,why?
This does not happen when I create the list using append(see below variable data ).
#!/bin/env python
#encoding=utf8
width = 10
height = 10
data = []
for i in xrange(width):
data.append([0 for j in xrange(height)])
data2 = [[0]*width]*height
print "before:",data == data2
data[0][0] = 1
data2[0][0] = 1
print "after:",data == data2
print "actually:"
print data
print data2
output:
before: True
after: False
actually:
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

The * operator on a list will repeat the objects in the list. But it doesn't make copies of the objects, it repeats the actual objects themselves.
The distinction is subtle, and many times you won't notice it. If the objects are immutable such as numbers or strings, all you can do is replace the object with a different object, and then the members of the list will no longer be the same object.
When the objects in the list can be modified, such as another list, any modification to that object is reflected in all the other repeated references in the list.
There's an awkward workaround:
data3 = [[0]*width for i in range(height)]

Here:
[[0]*width]
you only create a single list [0], and then you create another list containing width references to that single object. The key point is that the * operator only evaluates its operands once.
Here:
for i in xrange(width):
data.append([0 for j in xrange(height)])
you are creating a new list on each iteration that you then append.

Related

How do I create multiple levels in pygame?

I can't get my "world_data2" and "world_data3" to draw to the screen. only the "world_data" at index position 0 of the "levels" list draws. Everything else seems to be working. The bats and the doors change in every level, but the tile layout stays exactly the same. Is it possibly something to do with my "reset_level" function? or my world class?
Improved code:
# Importing the pygame library
import pygame
# Initializing pygame
pygame.init()
# Clock and frame rate
clock = pygame.time.Clock()
fps = 60
# Creating the game window
screen_width = 1500
screen_height = 1000
screen = pygame.display.set_mode((screen_width, screen_height))
# Setting game window caption
pygame.display.set_caption('Castle Escape')
# Define game variables
tile_size = 50
game_over = 0
main_menu = True
current_level_index = 0
total_levels = 2
# Loading images
background_img = pygame.image.load('Assets/Images/purplebackground.jpg')
restart_img = pygame.image.load('Assets/Images/Sprites/Buttons/restart.png')
restart_img = pygame.transform.scale(restart_img, (80, 40))
play_img = pygame.image.load('Assets/Images/Sprites/Buttons/play.png')
play_img = pygame.transform.scale(play_img, (350, 190))
exit_img = pygame.image.load('Assets/Images/Sprites/Buttons/exit.png')
exit_img = pygame.transform.scale(exit_img, (350, 190))
controls_img = pygame.image.load('Assets/Images/Sprites/Buttons/controls.png')
controls_img = pygame.transform.scale(controls_img, (350, 190))
settings_img = pygame.image.load('Assets/Images/Sprites/Buttons/settings.png')
settings_img = pygame.transform.scale(settings_img, (350, 190))
menu_img = pygame.image.load('Assets/Images/Sprites/Buttons/menu.png')
menu_img = pygame.transform.scale(menu_img, (80, 40))
# Instances for groups
bat_group = pygame.sprite.Group()
door_group = pygame.sprite.Group()
# Function to draw grid
def draw_grid():
for line in range(0, 30):
pygame.draw.line(screen, (255, 255, 255), (0, line * tile_size), (screen_width, line * tile_size))
pygame.draw.line(screen, (255, 255, 255), (line * tile_size, 0), (line * tile_size, screen_height))
# Function to reset levels
def reset_level(current_level_index):
# Reset player position
player.reset(100, screen_height - 130)
# Empty groups
bat_group.empty()
door_group.empty()
# Load in level data and create world
if current_level_index <= total_levels:
level = levels[current_level_index]
world = World(level)
return world
# Class for world map
class World:
# Constructor
def __init__(self, data):
# List to store locations of tiles
self.tile_list = []
# Load images
ground_img = pygame.image.load('Assets/Medieval Tileset/PNG/Tiles/tile59.png')
ground2_img = pygame.image.load('Assets/Medieval Tileset/PNG/Tiles/tile34.png')
leftwall_img = pygame.image.load('Assets/Medieval Tileset/PNG/Tiles/tile56.png')
rightwall_img = pygame.image.load('Assets/Medieval Tileset/PNG/Tiles/tile58.png')
ceiling_img = pygame.image.load('Assets/Medieval Tileset/PNG/Tiles/tile146.png')
# Loop to run through each row of world grid
row_count = 0
for row in data:
# Loop to run through each column in each row of world grid
col_count = 0
for tile in row:
if tile == 1:
# Scale images to 50 x 50px
img = pygame.transform.scale(ground_img, (tile_size, tile_size))
# Take rectangle
img_rect = img.get_rect()
# x and y coordinates for rectangle
img_rect.x = col_count * tile_size
img_rect.y = row_count * tile_size
tile = (img, img_rect)
self.tile_list.append(tile)
if tile == 2:
# Scale images to 50 x 50px
img = pygame.transform.scale(leftwall_img, (tile_size, tile_size))
# Take rectangle
img_rect = img.get_rect()
# x and y coordinates for rectangle
img_rect.x = col_count * tile_size
img_rect.y = row_count * tile_size
tile = (img, img_rect)
self.tile_list.append(tile)
if tile == 3:
# Scale images to 50 x 50px
img = pygame.transform.scale(rightwall_img, (tile_size, tile_size))
# Take rectangle
img_rect = img.get_rect()
# x and y coordinates for rectangle
img_rect.x = col_count * tile_size
img_rect.y = row_count * tile_size
tile = (img, img_rect)
self.tile_list.append(tile)
if tile == 4:
# Scale images to 50 x 50px
img = pygame.transform.scale(ceiling_img, (tile_size, tile_size))
# Take rectangle
img_rect = img.get_rect()
# x and y coordinates for rectangle
img_rect.x = col_count * tile_size
img_rect.y = row_count * tile_size
tile = (img, img_rect)
self.tile_list.append(tile)
if tile == 5:
# Scale images to 50 x 50px
img = pygame.transform.scale(ground2_img, (tile_size, tile_size))
# Take rectangle
img_rect = img.get_rect()
# x and y coordinates for rectangle
img_rect.x = col_count * tile_size
img_rect.y = row_count * tile_size
tile = (img, img_rect)
self.tile_list.append(tile)
if tile == 6:
# Create instance of bat enemy
bat = Enemy(col_count * tile_size, row_count * tile_size)
bat_group.add(bat)
if tile == 7:
# Create instance of door
door = Doors(col_count * tile_size, row_count * tile_size - 50)
door_group.add(door)
col_count += 1
row_count += 1
# Method to draw tiles to screen
def drawWorld(self):
# Loop to iterate through tile_list
for tile in self.tile_list:
screen.blit(tile[0], tile[1])
pygame.draw.rect(screen, (255, 255, 255), tile[1], 2)
# Class for buttons
class Button:
def __init__(self, x, y, image):
self.image = image
# Create rectangle
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Check whether mouse click occurs
self.clicked = False
# Draw method
def draw(self):
# Variable holds whether restart button been clicked or not
action = False
# Get mouse position
pos = pygame.mouse.get_pos()
# Check mouseover and clicked conditions
if self.rect.collidepoint(pos):
if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False:
self.clicked = True
action = True
# Make sure button can only be clicked once
if pygame.mouse.get_pressed()[0] == 0:
self.clicked = False
# Draw button
screen.blit(self.image, self.rect)
return action
# Class for player (sprite)
class Player:
# Spawn Player
def __init__(self, x, y):
# Call reset method
self.reset(x, y)
def updatePlayer(self, game_over):
dx = 0 # move along x
dy = 0 # move along y
run_slowDown = 5 # Slow down run animation
if game_over == 0:
# Key controls
key = pygame.key.get_pressed()
# Move player left
if key[pygame.K_LEFT]:
dx -= 3
self.counter += 1
self.direction = -1
# Move player right
if key[pygame.K_RIGHT]:
dx += 3
self.counter += 1
self.direction = 1
# Show idle image if no keys are being pressed
if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False:
self.counter = 0
self.index = 0
if self.direction == 0 or self.direction == 1:
self.image = pygame.image.load('Assets/Images/Sprites/Warrior/Idle/idle1.png')
self.image = pygame.transform.scale(self.image, (60, 90))
if self.direction == -1:
self.image = pygame.image.load('Assets/Images/Sprites/Warrior/Idle/idle1.png')
self.image = pygame.transform.scale(self.image, (60, 90))
self.image = pygame.transform.flip(self.image, True, False)
# Make player jump
self.rect.y += self.vel_y
if key[pygame.K_SPACE] and self.jumped == False and self.in_air == False:
self.vel_y = -12
self.jumped = True
if not key[pygame.K_SPACE]:
self.jumped = False
# Handle animations
if self.counter > run_slowDown:
self.counter = 0
self.index += 1
if self.index >= len(self.transformed_rightRun):
self.index = 0
if self.direction == 1:
self.image = self.transformed_rightRun[self.index]
if self.direction == -1:
self.image = self.images_leftRun[self.index]
# Add gravity
self.vel_y += 1
# Add terminal velocity
if self.vel_y > 2:
self.vel_y = 2
dy += self.vel_y
# Check for collision with tiles
self.in_air = True
for tile in world.tile_list:
# Check for collision in x-direction
if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height):
dx = 0
# Check for collision in y-direction
if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
# Check if hitting head on tile (jumping)
if self.vel_y < 0:
dy = tile[1].bottom - self.rect.top
self.vel_y = 0
# Check if landing on tile (falling)
elif self.vel_y >= 0:
dy = tile[1].top - self.rect.bottom
self.vel_y = 0
# Make sure player can only jump once
self.in_air = False
# Check for collision with enemies
if pygame.sprite.spritecollide(self, bat_group, False):
game_over = -1 # Value of -1 triggers game over
# Check collision with doors
if pygame.sprite.spritecollide(self, door_group, False):
game_over = 1 # Value of 1 means player has completed level
# update player coordinates
self.rect.x += dx
self.rect.y += dy
elif game_over == -1:
# Turn player into ghost
self.image = self.dead_image
# Make ghost float up
if self.rect.y > 200:
self.rect.y -= 5
# Draw player to screen
screen.blit(self.image, self.rect)
# Draw rectangle
pygame.draw.rect(screen, (255, 255, 255), self.rect, 2)
return game_over
# Method to reset game
def reset(self, x, y):
# Right run animation list
self.images_rightRun = []
# Append all right run animation images to list
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run1.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run2.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run3.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run4.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run5.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run6.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run7.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run8.png'))
# New transformed right run list
self.transformed_rightRun = []
for img in self.images_rightRun:
self.transformed_rightRun.append(pygame.transform.scale(img, (60, 90)))
# Left run animation list
self.images_leftRun = []
for img in self.transformed_rightRun:
self.images_leftRun.append(pygame.transform.flip(img, True, False))
# Set index and counter of lists to 0
self.index = 0
self.counter = 0 # Counter controls speed of animation
# Load and scale ghost image
self.dead_image = pygame.image.load('Assets/Images/Sprites/Ghost/ghost.png')
self.dead_image = pygame.transform.scale(self.dead_image, (40, 60))
# Statement to display current sprite animation on screen
self.image = self.transformed_rightRun[self.index]
# Create player rectangle
self.rect = self.image.get_rect()
# Get x coordinate
self.rect.x = x
# Get y coordinate
self.rect.y = y
# Width and height for rectangle
self.width = self.image.get_width()
self.height = self.image.get_height()
# Set velocity in y direction to 0
self.vel_y = 0
# Player jump
self.jumped = False
# Player direction
self.direction = 0
# Check if player is in air
self.in_air = True
# Class for enemies
class Enemy(pygame.sprite.Sprite):
def __init__(self, x, y):
# Calling constructor from super class
pygame.sprite.Sprite.__init__(self)
# Load and scale bat images
self.image = pygame.image.load('Assets/Images/Sprites/Bat/Fly/fly2.png')
self.image = pygame.transform.scale(self.image, (50, 40))
# Flip bat image
self.left_image = pygame.transform.flip(self.image, True, False)
# Create rectangle
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Variables for movement
self.move_direction = 1
self.move_counter = 0
def update(self):
# Move bats left and right
self.rect.x += self.move_direction
self.move_counter += 1
if abs(self.move_counter) > 100:
self.move_direction *= -1
self.move_counter *= -1
# Flip bat images
if self.move_direction == -1:
self.image = self.left_image
if self.move_direction == 1:
self.image = pygame.transform.flip(self.left_image, True, False)
# Draw bat rectangle to screen
pygame.draw.rect(screen, (255, 255, 255), self.rect, 2)
# Class for enemies
class Doors(pygame.sprite.Sprite):
def __init__(self, x, y):
# Calling constructor from super class
pygame.sprite.Sprite.__init__(self)
# Load and scale door images
self.image = pygame.image.load('Assets/Medieval Tileset/PNG/Objects/door4.png')
self.image = pygame.transform.scale(self.image, (80, 100))
# Create rectangle
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Level 1 map
world_data1 = [
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 1, 1, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 1, 5, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 7, 0, 1, 5, 5, 5, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
]
# Level 2 map
world_data2 = [
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 6, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
]
# Level 3 map
world_data3 = [
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 1, 5, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 3],
[1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
]
# Store level maps in list
levels = [
world_data1,
world_data2,
world_data3,
]
# Load in level data and create world
if current_level_index <= total_levels:
level = levels[current_level_index]
world = World(level)
# Create instance of button class
restart_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, restart_img)
play_button = Button(screen_width // 2 - 550, screen_height // 2 - 220, play_img)
exit_button = Button(screen_width // 2 - 550, screen_height // 2 + 50, exit_img)
controls_button = Button(screen_width // 2 + 150, screen_height // 2 - 220, controls_img)
settings_button = Button(screen_width // 2 + 150, screen_height // 2 + 50, settings_img)
menu_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, menu_img)
# Create instance of player class
player = Player(100, 800)
# main game loop
run = True
while run:
# Set internal clock
clock.tick(fps)
# Draw background to screen
screen.blit(background_img, (0, 0))
# Display buttons on main menu
if main_menu:
# If exit button is clicked, close game
if exit_button.draw():
run = False
# If play button is clicked, start game
if play_button.draw():
main_menu = False
controls_button.draw()
settings_button.draw()
else:
# Draw levels to screen
world.drawWorld()
# if the player dies, stop updating bats
if game_over == 0:
bat_group.update()
# Draw bats to screen
bat_group.draw(screen)
# Draw doors to screen
door_group.draw(screen)
# Draw player to screen and return game_over value
game_over = player.updatePlayer(game_over)
# if player dies, display restart button
if game_over == -1:
if restart_button.draw():
# Send player back to level 1
current_level_index = 0
reset_level(current_level_index)
game_over = 0
# If player has completed level, move to next level
if game_over == 1:
current_level_index += 1
if current_level_index <= total_levels:
reset_level(current_level_index)
game_over = 0
else:
# If player has completed final level, open main menu
if menu_button.draw():
main_menu = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.update()
pygame.quit()
Any help would be greatly appreciated. Thank you!
Keep in mind that your main loop logic is run at each frame, so here, at each frame you run level 1, then if game over == 1 you run level2 etc, so everything is reset all the time. I think your problem is there.
You could define a state that would hold the current level and use this.
For example:
levels= ( # store your levels in some convenient structure
World(world_data1),
World(world_data2),
World(world_data2),
)
current_level_index = 0 # The level state, initalized with the index of the first level
game_over = 0
while True:
level = levels[current_level_index] # use your state to get the level instead of naming it directly
level.drawWorld()
# whatever you need to do to update your level logic, move things etc
if game_over == 1:
# This just is a simplistic example implementation to illustrate a change of level
current_level_index += 1
This is just a trivial example but you can try to structure your code in this kind of way.

how to print 2-D array row by row in GDB?

map[22][22];
I want to see 'map(2-D array)' by GDB and the result was like this
$1 = {{-1 repeats 22 times}, {-1, 4, 4, 4, 4, 2, 3, 2, 1, 0, 4, -1 repeats 11 times}, {-1, 1, 1, 2, 2, 5, 2, 0, 0, 0, 2, -1 repeats 11 times}, {-1, 3, 0, 0, 1, 1, 1, 0, 0, 0, 0, -1 repeats 11 times}, {-1, 1, 0, 0, 0, 0, 0, -1, 4, 4, 1, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 repeats 11 times>}, {-1 repeats 22 times} repeats 11 times>}
and it was so unuseful to see..
I want to see like this
{-1,-1,-1,-1,-1,-1,-1,1}
{1,2,3,4,5,2,4,}
{2,1,4,5,3,4,2,2}
...
can you tell how to print 2-D array row by row??
I want to see like this
There are 2 ways to achieve this:
Implement debug_print() function in your program, call it from GDB with the call command.
Implement Python pretty-printer. Documentation. Tutorial.
The first solution is trivial to implement, but (unlike the second) doesn't work when you don't have a live process (e.g. for core postmortem debugging).

Reverse an array with preprocessor

I want to use pre-processor to fill some arrays in some ways. I can use preprocessor only for newly declared arrays. However, I need to change the array p which I declared and used before. Time optimization is very important for my purpose.
#define Reverse(x) {x[63], x[62], x[61], x[60], x[59], x[58], x[57], x[56], x[55], x[54], x[53], x[52], x[51], x[50], x[49], x[48], x[47], x[46], x[45], x[44], x[43], x[42], x[41], x[40], x[39], x[38], x[37], x[36], x[35], x[34], x[33], x[32], x[31], x[30], x[29], x[28], x[27], x[26], x[25], x[24], x[23], x[22], x[21], x[20], x[19], x[18], x[17], x[16], x[15], x[14], x[13], x[12], x[11], x[10], x[9], x[8], x[7], x[6], x[5], x[4], x[3], x[2], x[1], x[0] }
int main()
{
int p[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int q[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
//doThings
p= Reverse(q); // line A - Gives error
int s[64] = Reverse(q); // line B - Works properly
//doThings
}
I got this error:
Error 11 error C3079: an initializer-list cannot be used as the right operand of this assignment operator c:\users\ferda\documents\visual studio 2013\projects\consoleapplication3\consoleapplication3\consoleapplication3.cpp 39‌​3 1 ConsoleApplication3
Built in array type does not allow to assign to it another array or use aggregate initialization on already initialized array, you would have to use memcpy or for loop to update it with new values. Your code will compile if you use std::array instead. It provides operator=:
operator= (implicitly declared) overwrites every element of the
array with the corresponding element of another array (public member
function)
http://coliru.stacked-crooked.com/a/8e664210b7f7f73b
i am not sure if this will work as fast as you expect, gcc will generate lots of mov instructions : https://godbolt.org/g/tzUqC3. I suppose it might be faster to use a for loop which will require less cache memory. As always profile your code.

Translating array pointer access from C++ to Delphi

I'd like to know if I translated a piece of code correctly from C++ to Delphi.
It looks like it is working, but I have a feeling that I'm reading and writing into memory that I'm not supposed to using Delphi.
Given C++ code:
struct tile_map
{
int32 CountX;
int32 CountY;
uint32 *Tiles;
};
inline uint32
GetTileValueUnchecked(tile_map *TileMap, int32 TileX, int32 TileY)
{
uint32 TileMapValue = TileMap->Tiles[TileY*TileMap->CountX + TileX];
return(TileMapValue);
}
uint32 Tiles00[9][17] =
{
{1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
// More tile map declarations ...
// uint32 Tiles01[9][17] = ...
// uint32 Tiles10[9][17] = ...
// uint32 Tiles11[9][17] = ...
tile_map TileMaps[2][2];
TileMaps[0][0].CountX = 17;
TileMaps[0][0].CountY = 9;
TileMaps[0][0].Tiles = (uint32 *)Tiles00;
TileMaps[0][1] = TileMaps[0][0];
TileMaps[0][1].Tiles = (uint32 *)Tiles01;
TileMaps[1][0] = TileMaps[0][0];
TileMaps[1][0].Tiles = (uint32 *)Tiles10;
TileMaps[1][1] = TileMaps[0][0];
TileMaps[1][1].Tiles = (uint32 *)Tiles11;
// Usage
int32 PlayerTileX = 2;
int32 PlayerTileY = 2;
uint32 TileMapValue = GetTileValueUnchecked(&TileMap[1][1], PlayerTileX, PlayerTileY);
Delphi translation:
program Project1;
{$APPTYPE CONSOLE}
type
Puint32 = ^uint32;
tile_map = record
CountX : int32;
CountY : int32;
Tiles : Puint32;
end;
Ptile_map = ^tile_map;
{$POINTERMATH ON}
function GetTileValueUnchecked(TileMap : Ptile_map; TileX, TileY : int32) : uint32; inline;
begin
result := TileMap^.Tiles[TileY * TileMap^.CountX + TileX];
end;
const //in the future these will be read from file, so const for now
Tiles00: array [0..8, 0..16] of uint32 =
(
(1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
);
// More tile map declarations ...
//Tiles01: array [0..8, 0..16] of uint32 = ...
//Tiles10: array [0..8, 0..16] of uint32 = ...
//Tiles11: array [0..8, 0..16] of uint32 = ...
var
TileMaps : array [0..1, 0..1] of tile_map;
PlayerTileX, PlayerTileY : int32;
TileMapValue : uint32;
begin
TileMaps[0][0].CountX := 17;
TileMaps[0][0].CountY := 9;
TileMaps[0][0].Tiles := Addr(Tiles00);
TileMaps[0][1] := TileMaps[0][0];
TileMaps[0][1].Tiles := Addr(Tiles01);
TileMaps[1][0] := TileMaps[0][0];
TileMaps[1][0].Tiles := Addr(Tiles10);
TileMaps[1][1] := TileMaps[0][0];
TileMaps[1][1].Tiles := Addr(Tiles11);
// Usage
PlayerTileX := 2;
PlayerTileY := 2;
TileMapValue = GetTileValueUnchecked(#TileMaps[1][1], PlayerTileX, PlayerTileY);
end.
David Heffernan's comments has been helpful and others seem to agree that the code is correct, so I will mark this as answered.

Why is the size and values of this OpenCV Matrix incorrect?

I use the following function to return a weight matrix of values between 0 and 1 depending on how close to the center a particular matrix position is. Also after a threshold the values are all 1 (it is like plateau with the points closer to center having value 1 and points away from center after a threshold of distance linearly fall from 1 to 0 at the edges)?
cv::Mat2f getWeightsMatrix(int N, int M, float r){
cv::Mat2f weights = cv::Mat2f(N,M);
int i,j;
for(i=0;i<N;i++){
for(j=0;j<M;j++){
if(i<=floor(N*(1-r)/2)){
if(j<=floor(M*(1-r)/2)){
weights[i][j]=((float)(i/N-j/M)/(1-r));
}
else{
weights[i][j]=(2*(float)(i/N)/(1-r));
}
}
else if (i>=floor(N*(1+r)/2)){
if(j>=floor(M*(1+r)/2)){
weights[i][j]=(((float)((N-i)/N))-((float)((M-j)/M)))/(1-r);
}
else{
weights[i][j]=(2*(float)((N-i)/N)/(1-r));
}
}
else{
if(j<=floor(M*(1-r)/2)){
weights[i][j]=(2*(float)(j/M)/(1-r));
}
else if(j>=floor(M*(1+r)/2)){
weights[i][j]=(2*(float)((M-j)/M)/(1-r));
}
else{
weights[i][j]=1;
}
}
}
}
cout << weights << endl;
return weights;
}
Now my problem is that I am having some casting issues and only values 0 and 1 are being returned (no floats). Also my matrix size displayed by the cout is 20x10 when I call the function with N=10, M=10 and r=0.5.
Please helP!
EDIT: This is the output
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Your matrix consists only if integers because when you do basic operations on integers, the results gets rounded automatically.
For example: when you write
weights[i][j]=((float)(i/N-j/M)/(1-r));
The result of i/N is rounded to a integer, j/M is also rounded to an integer, and finally, the division by (1-r) is also rounded. Your (float) cast is a good idea but it's applied too late.
You can do several things:
Cast inside elementary operations, for instance, float(i)/N instead of i/N
Use float numbers instead of integers: write 1.0 instead of 1
Use floats inside your loops and statements
For example:
for(float i = 0; i < N-0.5; i++) {
for(float j = 0; j < M-0.5; j++) {
if(i <= floor(N*(1.0-r)/2.0)) {
// ...
It's important you understand that because of floating point precision, a test such as i < N might or might not pass when float i = N. This is why I did a little trick by substracting 0.5 from your loop bounds N and M.