Python: Sample Candy Crush

Return to Python resources

import pygame, sys, random
from pygame.locals import *

pygame.init()
fps = pygame.time.Clock()
window = pygame.display.set_mode((450,450))
cols, rows = 9, 9
gameplay = True
score = 0
map = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0]
]

# Colours for the different candy.
candyOptions = [
    (0,0,0),
    (255,0,0),
    (0,255,0),
    (0,0,255),
    (255,255,0),
    (255,0,255),
    (0,255,255)
]

def swap_jewels(pressed, released):
    global map
    fromrow, fromcol = pressed
    torow, tocol = released
    tmp = map[fromrow][fromcol]
    map[fromrow][fromcol] = map[torow][tocol]
    map[torow][tocol] = tmp

def delete_jewel( target ):
    global score
    row, col = target
    # if the cell has a jewel...
    # we have to do this check otherwise the score will be increased everytime an empty cell is "deleted" when 3 empty cells exist
    if not map[row][col] == 0:
        map[row][col] = 0
        score = score + 1
        print("score: ", score)
 

def get_matches_for_this_cell(matches, target):
    rows = len(map)
    cols = len(map[0])
    targetrow, targetcol = target
    val = map[targetrow][targetcol]
    if targetrow > 0 and map[targetrow-1][targetcol] == val:
        new = (targetrow-1, targetcol)
        if not new in matches:
            matches.append( new )
            matches = get_matches_for_this_cell(matches, new)
    if targetrow < (rows-1) and map[targetrow+1][targetcol] == val:
        new = (targetrow+1, targetcol)
        if not new in matches:
            matches.append( new )
            matches = get_matches_for_this_cell(matches, new)
    if targetcol > 0 and map[targetrow][targetcol-1] == val:
        new = (targetrow, targetcol-1)
        if not new in matches:
            matches.append( new )
            matches = get_matches_for_this_cell(matches, new)
    if targetcol < (cols-1) and map[targetrow][targetcol+1] == val:
        new = (targetrow, targetcol+1)
        if not new in matches:
            matches.append( new )
            matches = get_matches_for_this_cell(matches, new)
    return matches

def check_near_this_cell_for_matches(target):
    global map, score
    matches = [ target ]            # start initial list of matches with our target
    matches = get_matches_for_this_cell(matches, target)
    if len( matches ) >= 3:         # if at least 3 jewels match
        for match in matches:       # for all our matches
            delete_jewel( match )   # delete the jewel at the match location
        return True
    return False

def check_entire_board_for_matches():

def get_random_jewel():
    return random.randint(1, len(candyOptions) - 1)

def draw_jewel( cell ):
    global window
    row, col = cell
    candyNumber = map[row][col]
    candyColor = candyOptions[candyNumber]
    y = row * 50
    x = col * 50
    pygame.draw.circle(window, candyColor, (x + 25, y + 25), 25, 0)

 

# MAIN
while gameplay:
    # Events
    for event in pygame.event.get():
        if event.type == QUIT:
            gameplay = False
        elif event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                gameplay = False
            if event.key == K_SPACE:
                check_entire_board_for_matches()
        elif event.type == MOUSEBUTTONDOWN:
            pressed = (event.pos[1]//50, event.pos[0]//50)
        elif event.type == MOUSEBUTTONUP:
            released = (event.pos[1]//50, event.pos[0]//50)
            print("Mouse pressed at  ",pressed)
            print("Mouse released at ",released)
            # For a move to be valid, it has to be an ajoining sprite
            if abs(pressed[0] - released[0]) <= 1 and abs(pressed[1] - released[1]) <= 1:
                swap_jewels(pressed, released)
                check_near_this_cell_for_matches(released)
            else:
                print("move is not valid")

    # Calculations
    check_entire_board_for_matches()

    # Draw everything
    for row in reversed(range(rows)):
        for col in range(cols):
            # if our cell is missing candy
            if map[row][col] == 0:
                if row>0:
                    map[row][col] = map[row - 1][col]
                    map[row - 1][col] = 0
                else:
                    map[row][col] = get_random_jewel()
            # draw the candy in our cell
            draw_jewel( (row, col) )
    pygame.display.update()
    fps.tick(15)

pygame.quit()
print("Good bye")