Movatterモバイル変換


[0]ホーム

URL:


Open In App
Next Article:
Brick Breaker Game In Python using Pygame
Next article icon

Slide Puzzle game is a 2-dimensional game i.e the pieces can only be removed inside the grid and reconfigured by sliding them into an empty spot. The slide puzzle game developed here is a 3X3 grid game i.e 9 cells will be there from 1 to 8(9 is not here since a blank cell is needed for sliding the neighboring cells). In this article, we are going to see how to create a slide puzzle inPygame usingPython.

Slide_game Python

Importing necessary modules 

Python3
# Code for the sliding puzzle game in python using pygame.importpygameimportrandomimportpyautoguifrompygame.localsimport*

Call the main function 

  • The main() function is called to start the program i.e initialize the necessary variables
Python3
classTiles:# main method for initializing different variablesdef__init__(self,screen,start_position_x,start_position_y,num,mat_pos_x,mat_pos_y):self.color=(0,255,0)# complete screenself.screen=screen# screen(x)self.start_pos_x=start_position_x# screen(y)self.start_pos_y=start_position_y# total numsself.num=num# width of each tileself.width=tile_width# depth of each tile(shadow)self.depth=tile_depth# tile selected falseself.selected=False# matrix alignment from screen w.r.t x coordinateself.position_x=mat_pos_x# matrix alignment from screen w.r.t y coordinateself.position_y=mat_pos_y# tile movable false in its initial stateself.movable=False

draw_tyle() method for drawing the tiles in the grid :

  • Draw rectangles using .rect(). Pass length, breadth, width & height to make the rectangle 
  • blit() will take that rectangular Surface and put it on top of the screen
Python3
# Draw tilesdefdraw_tyle(self):pygame.draw.rect(self.screen,self.color,pygame.Rect(self.start_pos_x,self.start_pos_y,self.width,self.depth))numb=font.render(str(self.num),True,(125,55,100))screen.blit(numb,(self.start_pos_x+40,self.start_pos_y+10))

mouse_hover() method for changing the color of a tile: 

  • mouse_hover() method for changing the color of a tile to white when the mouse hovers over the tile
Python3
# Mouse hover chnage the color of tilesdefmouse_hover(self,x_m_motion,y_m_motion):ifx_m_motion>self.start_pos_xandx_m_motion<self.start_pos_x+self.widthandy_m_motion>self.start_pos_yandy_m_motion<self.start_pos_y+self.depth:self.color=(255,255,255)else:self.color=(255,165,0)

mouse_click() method for selecting the tile: 

  • when the mouse clicks on a tile, the tile changes position with some depthless causing it to go below the main grid
Python3
# when  mouse  clicks check if a tile is selected or notdefmouse_click(self,x_m_click,y_m_click):ifx_m_click>self.start_pos_xandx_m_click<self.start_pos_x+self.widthandy_m_click>self.start_pos_yandy_m_click<self.start_pos_y+self.depth:self.selected=Trueelse:self.selected=False

mouse_click_release() for checking whether the tile is released or not: 

  • when the mouse click is released unselect the tile by setting selected as  False 
Python3
# when mouse click released unselect the tile by setting Falsedefmouse_click_release(self,x_m_click_rel,y_m_click_rel):ifx_m_click_rel>0andy_m_click_rel>0:self.selected=False

move_tyle() method for moving the tiles with appropriate co-ords:

Python3
# Move the tile(i.e hower)defmove_tyle(self,x_m_motion,y_m_motion):self.start_pos_x=x_m_motionself.start_pos_y=y_m_motion# end of class

create_tyles() method for creating tiles in the matrix:

  • Create tiles w.r.t to no of tiles available i.e in a 3x3 matrix the no of tiles will be 9(blank tile included) 
  • For puzzle-making, create tiles at random positions in the matrix. Once the position is fixed append the tile_no to that tile from the available tiles
  • Print the tiles in the grid 
Python3
# Create tiles w.r.t to no of tiles availabledefcreate_tyles():i=1# create tiles at random positionswhilei<=tile_count:r=random.randint(1,tile_count)ifrnotintile_no:tile_no.append(r)i+=1tile_no.append("")k=0# print the tiles in the gridforiinrange(0,rows):forjinrange(0,cols):if(i==rows-1)and(j==cols-1):passelse:t=Tiles(screen,tile_print_position[(i,j)][0],tile_print_position[(i,j)][1],tile_no[k],i,j)tiles.append(t)matrix[i][j]=tile_no[k]k+=1check_mobility()

check_mobility() method for validating  positions: 

  • check if the tile can be placed in the required position where the player is trying to move the tile
Python3
# check if the tile can be placed# in the required position where# the player is trying to move the tiledefcheck_mobility():foriinrange(tile_count):tile=tiles[i]row_index=tile.position_xcol_index=tile.position_yadjacent_cells=[]adjacent_cells.append([row_index-1,col_index,False])# upadjacent_cells.append([row_index+1,col_index,False])# downadjacent_cells.append([row_index,col_index-1,False])# rightadjacent_cells.append([row_index,col_index+1,False])# leftforiinrange(len(adjacent_cells)):if(adjacent_cells[i][0]>=0andadjacent_cells[i][0]<rows)and(adjacent_cells[i][1]>=0andadjacent_cells[i][1]<cols):adjacent_cells[i][2]=Trueforjinrange(len(adjacent_cells)):ifadjacent_cells[j][2]:adj_cell_row=adjacent_cells[j][0]adj_cell_col=adjacent_cells[j][1]forkinrange(tile_count):ifadj_cell_row==tiles[k].position_xandadj_cell_col==tiles[k].position_y:adjacent_cells[j][2]=Falsefalse_count=0forminrange(len(adjacent_cells)):ifadjacent_cells[m][2]:tile.movable=Truebreakelse:false_count+=1iffalse_count==4:tile.movable=False

isGameOver() method for checking whether the game is over or not:  

  • If after iterating the matrix the string we get is 12345678_ then the player has won("Game Over") and lock the tiles at that position
Python3
# if after iterating the matrix# the string we get is 12345678_# then the player has won("Game Over")defisGameOver():globalgame_over,game_over_bannerallcelldata=""foriinrange(rows):forjinrange(cols):allcelldata=allcelldata+str(matrix[i][j])ifallcelldata=="12345678 ":game_over=Truegame_over_banner="Game Over"print("Game Over")# lock the tiles at that positionforiinrange(tile_count):tiles[i].movable=Falsetiles[i].selected=False

Define the matrix with its size and some initial variables: 

  • Define the window screen dimension with the help of pyautogui.size() function.   
  • pyautogui.size() returns two integers in tuple(width, height) of the screen size, in pixels.
  • Define no of rows and columns of the matrix & print the tiles at appropriate positions
  • Then set the initial values for mouse_press , x_m_click, y_m_click, x_m_click_rel, y_m_click_rel, game_over, game_over_banner.
Python3
# Window dimensionpage_width,page_depth=pyautogui.size()page_width=int(page_width*.95)page_depth=int(page_depth*.95)# tile dimensionstiles=[]tile_width=200tile_depth=200# no of rows & column i.e puzzle sizerows,cols=(3,3)tile_count=rows*cols-1# how many tiles should be createdmatrix=[[""foriinrange(cols)]forjinrange(rows)]tile_no=[]tile_print_position={(0,0):(100,50),(0,1):(305,50),(0,2):(510,50),(1,0):(100,255),(1,1):(305,255),(1,2):(510,255),(2,0):(100,460),(2,1):(305,460),(2,2):(510,460)}# initial values of variablesmouse_press=Falsex_m_click,y_m_click=0,0x_m_click_rel,y_m_click_rel=0,0game_over=Falsegame_over_banner=""

Initialize pygame module &  set the caption:

  • Initialize all the pygame modules with the help of pygame.init()
  • Now set the captions for texts and counter of counting the total number of moves.
Python3
# initialize pygame and set the captionpygame.init()game_over_font=pygame.font.Font('freesansbold.ttf',70)move_count=0move_count_banner="Moves : "move_count_font=pygame.font.Font('freesansbold.ttf',40)screen=pygame.display.set_mode((page_width,page_depth))pygame.display.set_caption("Slide Game")font=pygame.font.Font('freesansbold.ttf',200)# creation of tiles in the puzzlecreate_tyles()

Making the puzzle by doing random moves: 

  • Set the running = True, it indicates that the player is playing the game 
  • Fill the window screen with black color then start drawing the GUI board and print the tiles at the GUI
  • Now render the total no of counts each time a new move is played
  • Now get the events triggered by the player with the help of pygame.event.get()
    • If the event is quit operation then terminate the program
    • If mouse clicks are detected then find (x,y) and then pass them to the mouse_hover method
    • If the tile is selected & mouse is pressed then pass the coords to the move_tyle method and it will move the tile to the desired location
      • If the desired location is down pass coords to mouse_click and settle the tile there if the conditions are satisfying. similarly for other conditions.
Python3
# main looprunning=Truewhilerunning:# fill with black colorscreen.fill((0,0,0))# start drawing the gui board of sliding puzzlepygame.draw.rect(screen,(165,42,42),pygame.Rect(95,45,620,620))game_over_print=game_over_font.render(game_over_banner,True,(255,255,0))# blit() will take that rectangular# Surface and put it on top of the screen.screen.blit(game_over_print,(950,100))# render the move_count with the use of strifmove_count==0:move_count_render=move_count_font.render(move_count_banner,True,(0,255,0))else:move_count_render=move_count_font.render(move_count_banner+str(move_count),True,(0,255,0))screen.blit(move_count_render,(1050,200))# Get events from the queue.foreventinpygame.event.get():# if its quite operation then exit the while loopifevent.type==pygame.QUIT:running=False# if mouse click are detected# then find (x,y) and then pass# them to mouse_hover methodifevent.type==pygame.MOUSEMOTION:x_m_motion,y_m_motion=pygame.mouse.get_pos()foriinrange(tile_count):tiles[i].mouse_hover(x_m_motion,y_m_motion)# if the tile is selected &# mouse is pressed then pass# the coords to move_tyle methodforiinrange(tile_count):iftiles[i].selectedandmouse_press:tiles[i].move_tyle(x_m_motion,y_m_motion)# Moving tile downwardsifevent.type==pygame.MOUSEBUTTONDOWN:mouse_press=Truex_m_click,y_m_click=pygame.mouse.get_pos()foriinrange(tile_count):tiles[i].mouse_click(x_m_click,y_m_click)# Moving tile upwardsifevent.type==pygame.MOUSEBUTTONUP:mouse_press=Falsex_m_click_rel,y_m_click_rel=pygame.mouse.get_pos()x_m_click,y_m_click=0,0cell_found=Falseforiinrange(0,rows):forjinrange(0,cols):tile_start_pos_x=tile_print_position[(i,j)][0]tile_start_pos_y=tile_print_position[(i,j)][1]if(x_m_click_rel>tile_start_pos_xandx_m_click_rel<tile_start_pos_x+tile_width)and(y_m_click_rel>tile_start_pos_yandy_m_click_rel<tile_start_pos_y+tile_depth):ifmatrix[i][j]=="":forkinrange(tile_count):ifgame_over==False:iftiles[k].selected:iftiles[k].movable:cell_found=Truedummy=matrix[tiles[k].position_x][tiles[k].position_y]matrix[tiles[k].position_x][tiles[k].position_y]=matrix[i][j]matrix[i][j]=dummytiles[k].position_x=itiles[k].position_y=jtiles[k].start_pos_x=tile_print_position[(i,j)][0]tiles[k].start_pos_y=tile_print_position[(i,j)][1]move_count+=1isGameOver()check_mobility()ifcell_found==False:forkinrange(tile_count):iftiles[k].selected:mat_pos_x=tiles[k].position_xmat_pos_y=tiles[k].position_ytiles[k].start_pos_x=tile_print_position[(mat_pos_x,mat_pos_y)][0]tiles[k].start_pos_y=tile_print_position[(mat_pos_x,mat_pos_y)][1]break

Traversing & updating of tiles :

  • Traverse all the tiles and draw them
  • After drawing update them on the screen with the help of pygame.display.flip() 
  • pygame.display.flip(): Allows only a portion of the screen to update, instead of the entire area, 
Python3
foriinrange(tile_count):tiles[i].draw_tyle()pygame.display.flip()

Update the window of game: 

  • Now update the whole window of the game using pygame.display.update()
  • pygame.display.update(): If no argument is passed it updates the entire window area(This is the case of the below code).
Python3
# Update the whole screenpygame.display.update()

Complete source code: 

Python3
importpygameimportrandomimportpyautoguifrompygame.localsimport*classTiles:# main method for initializing different variablesdef__init__(self,screen,start_position_x,start_position_y,num,mat_pos_x,mat_pos_y):self.color=(0,255,0)self.screen=screenself.start_pos_x=start_position_xself.start_pos_y=start_position_yself.num=numself.width=tile_widthself.depth=tile_depthself.selected=Falseself.position_x=mat_pos_xself.position_y=mat_pos_yself.movable=False# Draw tilesdefdraw_tyle(self):pygame.draw.rect(self.screen,self.color,pygame.Rect(self.start_pos_x,self.start_pos_y,self.width,self.depth))numb=font.render(str(self.num),True,(125,55,100))screen.blit(numb,(self.start_pos_x+40,self.start_pos_y+10))# Mouse hover chnage the color of tilesdefmouse_hover(self,x_m_motion,y_m_motion):ifx_m_motion>self.start_pos_xandx_m_motion<self.start_pos_x+self.widthandy_m_motion>self.start_pos_yandy_m_motion<self.start_pos_y+self.depth:self.color=(255,255,255)else:self.color=(255,165,0)# when  mouse  clicks check if a tile is selected or notdefmouse_click(self,x_m_click,y_m_click):ifx_m_click>self.start_pos_xandx_m_click<self.start_pos_x+self.widthandy_m_click>self.start_pos_yandy_m_click<self.start_pos_y+self.depth:self.selected=Trueelse:self.selected=False# when mouse click released unselect the tile by setting Falsedefmouse_click_release(self,x_m_click_rel,y_m_click_rel):ifx_m_click_rel>0andy_m_click_rel>0:self.selected=False# Move the tile(i.e hower)defmove_tyle(self,x_m_motion,y_m_motion):self.start_pos_x=x_m_motionself.start_pos_y=y_m_motion# Create tiles w.r.t to no of tiles availabledefcreate_tyles():i=1whilei<=tile_count:r=random.randint(1,tile_count)ifrnotintile_no:tile_no.append(r)i+=1tile_no.append("")k=0foriinrange(0,rows):forjinrange(0,cols):if(i==rows-1)and(j==cols-1):passelse:t=Tiles(screen,tile_print_position[(i,j)][0],tile_print_position[(i,j)][1],tile_no[k],i,j)tiles.append(t)matrix[i][j]=tile_no[k]k+=1check_mobility()# check if the tile can be places on the# required position where the# player is trying to move the tiledefcheck_mobility():foriinrange(tile_count):tile=tiles[i]row_index=tile.position_xcol_index=tile.position_yadjacent_cells=[]adjacent_cells.append([row_index-1,col_index,False])# upadjacent_cells.append([row_index+1,col_index,False])# downadjacent_cells.append([row_index,col_index-1,False])# rightadjacent_cells.append([row_index,col_index+1,False])# leftforiinrange(len(adjacent_cells)):if(adjacent_cells[i][0]>=0andadjacent_cells[i][0]<rows)and(adjacent_cells[i][1]>=0andadjacent_cells[i][1]<cols):adjacent_cells[i][2]=Trueforjinrange(len(adjacent_cells)):ifadjacent_cells[j][2]:adj_cell_row=adjacent_cells[j][0]adj_cell_col=adjacent_cells[j][1]forkinrange(tile_count):ifadj_cell_row==tiles[k].position_xandadj_cell_col==tiles[k].position_y:adjacent_cells[j][2]=Falsefalse_count=0forminrange(len(adjacent_cells)):ifadjacent_cells[m][2]:tile.movable=Truebreakelse:false_count+=1iffalse_count==4:tile.movable=False# if after iterating the matrix the# string we get is 12345678_ then# the player has won("Game Over")defisGameOver():globalgame_over,game_over_bannerallcelldata=""foriinrange(rows):forjinrange(cols):allcelldata=allcelldata+str(matrix[i][j])ifallcelldata=="12345678 ":game_over=Truegame_over_banner="Game Over"print("Game Over")foriinrange(tile_count):tiles[i].movable=Falsetiles[i].selected=False# Window dimensionpage_width,page_depth=pyautogui.size()page_width=int(page_width*.95)page_depth=int(page_depth*.95)# tile dimensionstiles=[]tile_width=200tile_depth=200# no of rows & column i.e puzzle sizerows,cols=(3,3)tile_count=rows*cols-1# how many tiles should be createdmatrix=[[""foriinrange(cols)]forjinrange(rows)]tile_no=[]tile_print_position={(0,0):(100,50),(0,1):(305,50),(0,2):(510,50),(1,0):(100,255),(1,1):(305,255),(1,2):(510,255),(2,0):(100,460),(2,1):(305,460),(2,2):(510,460)}# initial values of variablesmouse_press=Falsex_m_click,y_m_click=0,0x_m_click_rel,y_m_click_rel=0,0game_over=Falsegame_over_banner=""# initialize pygame and set the captionpygame.init()game_over_font=pygame.font.Font('freesansbold.ttf',70)move_count=0move_count_banner="Moves : "move_count_font=pygame.font.Font('freesansbold.ttf',40)screen=pygame.display.set_mode((page_width,page_depth))pygame.display.set_caption("Slide Game")font=pygame.font.Font('freesansbold.ttf',200)# creation of tiles in the puzzlecreate_tyles()running=Truewhilerunning:screen.fill((0,0,0))# fill with black color# start drawing the gui board of sliding puzzlepygame.draw.rect(screen,(165,42,42),pygame.Rect(95,45,620,620))game_over_print=game_over_font.render(game_over_banner,True,(255,255,0))# blit() will take that rectangular Surface# and put it on top of the screen.screen.blit(game_over_print,(950,100))# render the move_count with the use of strifmove_count==0:move_count_render=move_count_font.render(move_count_banner,True,(0,255,0))else:move_count_render=move_count_font.render(move_count_banner+str(move_count),True,(0,255,0))screen.blit(move_count_render,(1050,200))# Get events from the queue.foreventinpygame.event.get():# if its quite operation then exit the while loopifevent.type==pygame.QUIT:running=False# if mouse click are detected then find (x,y)# and then pass them to mouse_hover methodifevent.type==pygame.MOUSEMOTION:x_m_motion,y_m_motion=pygame.mouse.get_pos()foriinrange(tile_count):tiles[i].mouse_hover(x_m_motion,y_m_motion)# if the tile is selected & mouse is pressed# then pass the coords to move_tyle methodforiinrange(tile_count):iftiles[i].selectedandmouse_press:tiles[i].move_tyle(x_m_motion,y_m_motion)# Moving tile downwardsifevent.type==pygame.MOUSEBUTTONDOWN:mouse_press=Truex_m_click,y_m_click=pygame.mouse.get_pos()foriinrange(tile_count):tiles[i].mouse_click(x_m_click,y_m_click)# Moving tile upwardsifevent.type==pygame.MOUSEBUTTONUP:mouse_press=Falsex_m_click_rel,y_m_click_rel=pygame.mouse.get_pos()x_m_click,y_m_click=0,0cell_found=Falseforiinrange(0,rows):forjinrange(0,cols):tile_start_pos_x=tile_print_position[(i,j)][0]tile_start_pos_y=tile_print_position[(i,j)][1]if(x_m_click_rel>tile_start_pos_xandx_m_click_rel<tile_start_pos_x+tile_width)and(y_m_click_rel>tile_start_pos_yandy_m_click_rel<tile_start_pos_y+tile_depth):ifmatrix[i][j]=="":forkinrange(tile_count):ifgame_over==False:iftiles[k].selected:iftiles[k].movable:cell_found=Truedummy=matrix[tiles[k].position_x][tiles[k].position_y]matrix[tiles[k].position_x][tiles[k].position_y]=matrix[i][j]matrix[i][j]=dummytiles[k].position_x=itiles[k].position_y=jtiles[k].start_pos_x=tile_print_position[(i,j)][0]tiles[k].start_pos_y=tile_print_position[(i,j)][1]move_count+=1isGameOver()check_mobility()ifcell_found==False:forkinrange(tile_count):iftiles[k].selected:mat_pos_x=tiles[k].position_xmat_pos_y=tiles[k].position_ytiles[k].start_pos_x=tile_print_position[(mat_pos_x,mat_pos_y)][0]tiles[k].start_pos_y=tile_print_position[(mat_pos_x,mat_pos_y)][1]breakforiinrange(tile_count):tiles[i].draw_tyle()# allows only a portion of the screen to updated,# instead of the entire area,# If no argument is passed it# updates the entire Surface area like pygame.pygame.display.flip()# Update the whole screenpygame.display.update()

Output : 


Similar Reads

We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood ourCookie Policy &Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences

[8]ページ先頭

©2009-2025 Movatter.jp