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()