Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4258344
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 21, 20262026-05-21T05:38:11+00:00 2026-05-21T05:38:11+00:00

I’ve just implemented a very rudimentary game of tetris in python using pygame and

  • 0

I’ve just implemented a very rudimentary game of tetris in python using pygame and would like anybody to constuctively criticize me.

It’s my first program of substantial length so there are bound to be bugs. I also have not been able to wrap my head fully around the pygame event handling so keyboard controls might be dodgy but please do give it a try.

Any constructive criticism or advice will be highly valued.

###############################################################################
## an implementation of a ***very*** basic tetris game in python using pygame
###############################################################################
'''rotate --- r
   pause ---- p
   direction buttons for movement'''


import sys
import pygame
import random

size = width, height = 200, 400
color = {'black': (0, 0, 0), 'white':(255, 255, 255)}
sqrsize = 20
occupied_squares = []
top_of_screen = (0, 0)
top_x, top_y = top_of_screen[0], top_of_screen[1]
num_block = 4
pen_size = 1
mov_delay, r_delay = 300, 50
board_centre = 80
no_move = 0
events = {276: 'left', 275: 'right', 112: 'pause'}


pygame.init()
screen = pygame.display.set_mode(size)
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((color['white']))
screen.blit(background, top_of_screen)
pygame.display.flip()


def tetris():
    ''' this is the controller of the whole game for now, maybe changed
    later on as game architecture changes.'''
    global mov_delay
while True:
    curr_shape = create_newshape(board_centre)
    l_of_blcks_ind = blck_x_axis = 0
    shape_name_ind = blck_y_axis = 1

    move_dir = 'down' #default move direction
    game = 'playing'  #default game state play:- is game paused or playing

    shape_blcks = [pygame.Rect(block[blck_x_axis], block[blck_y_axis],
        sqrsize, sqrsize) for block in curr_shape[l_of_blcks_ind]]
    if legal(shape_blcks):
        draw_shape(shape_blcks)
    else:
        break  #game over
    while True:
        if game == 'paused':
            for event in pygame.event.get(pygame.KEYDOWN):
                if event.key == pygame.K_p:
                    game = 'playing'            
        else:
            for event in pygame.event.get((pygame.KEYDOWN, pygame.KEYUP,
                                           pygame.QUIT)):
                if event.type == pygame.QUIT:
                    sys.exit()
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_DOWN:
                        mov_delay = 50
                        continue
                    elif event.key == pygame.K_r:
                        shape_blcks = rotate(shape_blcks, curr_shape[shape_name_ind])
                        draw_shape(shape_blcks)
                        pygame.time.delay(r_delay)
                        continue

                    elif event.key == pygame.K_p:
                        game = 'paused'
                        move_dir = events[event.key]
                        break

                    else:
                        if event.key in events.keys():
                            mov_delay = 50
                            move_dir = events[event.key]
                            move (shape_blcks, move_dir)   
                            draw_shape(shape_blcks)
                            pygame.time.delay(mov_delay) 
                            continue  
                elif event.type == pygame.KEYUP:
                    if mov_delay != 300:
                        mov_delay = 300
                    move_dir  = 'down'        
            moved = move(shape_blcks, move_dir)
            draw_shape(shape_blcks)
            pygame.time.delay(mov_delay)

            '''if block did not move and the direction for movement is down
            then shape has come to rest so we can exit loop and then a new
            shape is generated. if direction for movement is sideways and
            block did not move it should be moved down rather'''
            if not moved and move_dir == 'down':
                for block in shape_blcks:
                    occupied_squares.append((block[blck_x_axis],
                                             block[blck_y_axis]))
                break
            else:
                draw_shape(shape_blcks)
                pygame.time.delay(mov_delay)
            for row_no in range (height - sqrsize, 0, -sqrsize):
                if row_filled(row_no):
                    delete_row(row_no)


def draw_shape(shp_blcks):
'''this draws list of blocks or a block to the background and blits
background to screen'''
if isinstance(shp_blcks, list):
    for blck in shp_blcks:
        pygame.draw.rect(background, color['black'], blck, pen_size)
else:
    pygame.draw.rect(background, color['black'], shp_blcks, pen_size)
screen.blit(background, top_of_screen)
pygame.display.update()


def row_filled(row_no):
'''check if a row is fully occupied by a shape block'''
for x_coord in range(0, width, sqrsize):
    if (x_coord, row_no) in occupied_squares:
        continue
    else:
        return False
return True


def delete_row(row_no):
'''removes all squares on a row from the occupied_squares list and then
moves all square positions which have y-axis coord less than row_no down
board'''
global occupied_squares
new_buffer = []
x_coord, y_coord = 0, 1
background.fill(color['white'])
for sqr in occupied_squares:
    if sqr[y_coord] != row_no:
        new_buffer.append(sqr)
occupied_squares = new_buffer
for index in range(len(occupied_squares)):
    if occupied_squares[index][y_coord] < row_no:
        occupied_squares[index] = (occupied_squares[index][x_coord],
                                occupied_squares[index][y_coord] + sqrsize)
for sqr in occupied_squares:
    rect = pygame.Rect(sqr[x_coord], sqr[y_coord], sqrsize, sqrsize)
    draw_shape(rect)


def move(shape_blcks, direction):
'''input:- list of blocks making up a tetris shape
output:- list of blocks making up a tetris shape
function moves the input list of blocks that make up shape and then checks
that the  list of blocks are all in positions that are valide. position is
valid if it has not been occupied previously and is within the tetris board.
If move is successful, function returns the moved shape and if move is not
possible, function returns a false'''
directs = {'down':(no_move, sqrsize), 'left':(-sqrsize, no_move),
    'right':(sqrsize, no_move), 'pause': (no_move, no_move)}
delta_x, delta_y = directs[direction]
for index in range(num_block):
    shape_blcks[index] = shape_blcks[index].move(delta_x, delta_y)

if legal(shape_blcks):
    for index in range(num_block):
        background.fill((color['white']), shape_blcks[index].move(-delta_x,
                                                                  -delta_y))
    return True
else:
    for index in range(num_block):
        shape_blcks[index] = shape_blcks[index].move(-delta_x, -delta_y)
    return False


def legal(shape_blcks):
'''input: list of shape blocks
checks whether a shape is in a legal portion of the board as defined in the
doc of 'move' function'''
blck_x_axis, blck_y_axis = 0, 1
for index in range(num_block):
    new_x, new_y = (shape_blcks[index][blck_x_axis],
                    shape_blcks[index][blck_y_axis])

    if (((new_x, new_y) in occupied_squares or new_y >= height) or
        (new_x >= width or new_x < top_x)): #probly introduced a bug by removing the check for shape being less that y-axis origin 
        return False
return True


def create_newshape(start_x=0, start_y=0):
'''A shape is a list of four rectangular blocks.
Input:- coordinates of board at which shape is to be created
Output:- a list of the list of the coordinates of constituent blocks of each
shape relative to a reference block and shape name. Reference block  has
starting coordinates of start_x and start_y. '''
shape_names = ['S', 'O', 'I', 'L', 'T']
shapes = {'S':[(start_x + 1*sqrsize, start_y + 2*sqrsize),
    (start_x, start_y), (start_x, start_y + 1*sqrsize),(start_x + 1*sqrsize,
                                                start_y + 1*sqrsize)],

    'O':[(start_x + 1*sqrsize, start_y + 1*sqrsize), (start_x, start_y),
        (start_x, start_y + 1*sqrsize), (start_x + 1*sqrsize, start_y)],

    'I':[(start_x, start_y + 3*sqrsize), (start_x, start_y),
        (start_x, start_y + 2*sqrsize), (start_x, start_y + 1*sqrsize)],

    'L':[(start_x + 1*sqrsize, start_y + 2*sqrsize), (start_x, start_y),
        (start_x, start_y + 2*sqrsize), (start_x, start_y + 1*sqrsize)],

    'T':[(start_x + 1*sqrsize, start_y + 1*sqrsize),(start_x, start_y),
        (start_x - 1*sqrsize, start_y + 1*sqrsize),(start_x,
                                                    start_y + 1*sqrsize)]
    }
a_shape = random.randint(0, 4)
return shapes[shape_names[a_shape]], shape_names[a_shape]
#return shapes['O'], 'O' #for testing 


def rotate(shape_blcks, shape):
'''input:- list of shape blocks
ouput:- list of shape blocks
function tries to rotate ie change orientation of blocks in the shape
and this applied depending on the shape for example if a 'O' shape is passed
to this function, the same shape is returned because the orientation of such
shape cannot be changed according to tetris rules'''
if shape == 'O':
    return shape_blcks
else:
    #global no_move, occupied_squares, background
    blck_x_axis, blck_y_axis = 0, 1

    shape_coords = [(block[blck_x_axis], block[blck_y_axis]) for
        block in shape_blcks]

    ref_shape_ind = 3 # index of block along which shape is rotated
    start_x, start_y = (shape_coords[ref_shape_ind][blck_x_axis],
                        shape_coords[ref_shape_ind][blck_y_axis])  
    new_shape_blcks = [(start_x + start_y-shape_coords[0][1],
                        start_y - (start_x - shape_coords[0][0])),
        (start_x + start_y-shape_coords[1][1],
         start_y - (start_x - shape_coords[1][0])),
        (start_x + start_y-shape_coords[2][1],
         start_y - (start_x - shape_coords[2][0])),
        (shape_coords[3][0], shape_coords[3][1])]
    if legal(new_shape_blcks):
        for index in range(num_block): # paint over the previous shape
            background.fill(color['white'], shape_blcks[index])
        return [pygame.Rect(block[blck_x_axis], block[blck_y_axis],
                                                 sqrsize, sqrsize) for
                                           block in new_shape_blcks] 
    else:
        return shape_blcks

if __name__ == '__main__':
    tetris()
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-21T05:38:12+00:00Added an answer on May 21, 2026 at 5:38 am

    This is similar to my first version of Tetris which I wrote many years ago when I was learning Pascal.

    Recently I wrote another version in order to experiment with Javascript.
    This time for representing the tetrominoes I used this structure:

        gameboard.colors = ['black','red','brown','cyan','orange','magenta','yellow','green'];
        gameboard.tetrominoes = {
          O: [[[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]],
              [[0,1,1,0], [0,1,1,0], [0,1,1,0], [0,1,1,0]],
              [[0,1,1,0], [0,1,1,0], [0,1,1,0], [0,1,1,0]],
              [[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]]],
    
          I: [[[0,0,0,0], [0,0,2,0], [0,0,0,0], [0,0,2,0]],
              [[2,2,2,2], [0,0,2,0], [2,2,2,2], [0,0,2,0]],
              [[0,0,0,0], [0,0,2,0], [0,0,0,0], [0,0,2,0]],
              [[0,0,0,0], [0,0,2,0], [0,0,0,0], [0,0,2,0]]],
    
          S: [[[0,0,0,0], [0,0,3,0], [0,0,0,0], [0,0,3,0]],
              [[0,0,3,3], [0,0,3,3], [0,0,3,3], [0,0,3,3]],
              [[0,3,3,0], [0,0,0,3], [0,3,3,0], [0,0,0,3]],
              [[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]]],
    
          Z: [[[0,0,0,0], [0,0,0,4], [0,0,0,0], [0,0,0,4]],
              [[0,4,4,0], [0,0,4,4], [0,4,4,0], [0,0,4,4]],
              [[0,0,4,4], [0,0,4,0], [0,0,4,4], [0,0,4,0]],
              [[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]]],
    
          L: [[[0,0,0,0], [0,0,5,0], [0,0,0,5], [0,5,5,0]],
              [[0,5,5,5], [0,0,5,0], [0,5,5,5], [0,0,5,0]],
              [[0,5,0,0], [0,0,5,5], [0,0,0,0], [0,0,5,0]],
              [[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]]],
    
          J: [[[0,0,0,0], [0,0,6,6], [0,6,0,0], [0,0,6,0]],
              [[0,6,6,6], [0,0,6,0], [0,6,6,6], [0,0,6,0]],
              [[0,0,0,6], [0,0,6,0], [0,0,0,0], [0,6,6,0]],
              [[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]]],
    
          T: [[[0,0,0,0], [0,0,7,0], [0,0,7,0], [0,0,7,0]],
              [[0,7,7,7], [0,0,7,7], [0,7,7,7], [0,7,7,0]],
              [[0,0,7,0], [0,0,7,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]]]
        };
    

    where each number represents a color. I found it to be more convenient, plus I didn’t have to use a “rotate” function.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

No related questions found

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.