Hi I’m higashi.
This page introduce how to make 3×3 puzzle game by using ‘Python-OpenCV’ as shown below.
You can play just prepare a appropriate picture.
The number depicted on picture can be deleted.
If you interested in this game, let’s make together.
Sample Code of Puzzle Game
It is suddenly, the below program is it.
#import library
import cv2
import numpy as np
import random
#specify the picture file
file_name='sample_pic.jpg'
#reading picture
img=cv2.imread(file_name,cv2.IMREAD_COLOR)
h,w=img.shape[:2]
#split number of puzzle
splitx=3
splity=3
counter=0
#list fir checking the clicked position
posx_list=[w/6,w/2,w*5/6]
posy_list=[h/6,h/2,h*5/6]
#designate a place where can move
pos0=[100,1,0,1,0,0,0,0,0]
pos1=[1,100,1,0,1,0,0,0,0]
pos2=[0,1,100,0,0,1,0,0,0]
pos3=[1,0,0,100,1,0,1,0,0]
pos4=[0,1,0,1,100,1,0,1,0]
pos5=[0,0,1,0,1,100,0,0,1]
pos6=[0,0,0,1,0,0,100,1,0]
pos7=[0,0,0,0,1,0,1,100,1]
pos8=[0,0,0,0,0,1,0,1,100]
pos_available=[pos0,pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8]
#split base img
def split_pic(img):
h,w=img.shape[:2]
cx,cy=0,0
pic_list=[]
for j in range(splitx):
for i in range(splity):
spic=img[cy:cy+int(h/splity),cx:cx+int(w/splitx),:]
pic_list.append(spic)
cy+=int(h/splity)
cy=0
cx+=int(w/splitx)
pic_list=np.array(pic_list)
return pic_list
#update after click
def pic_apdate(pic_list,pos_list):
base_img=np.zeros((h,w,3),np.uint8)
cx,cy=0,0
for j in range(splitx):
for i in range(splity):
ppp=splitx*j+i
if pos_list[ppp]!=100:
base_img[cy:cy+int(h/splity),cx:cx+int(w/splitx),:]=pic_list[pos_list[ppp]]
cy+=int(h/splity)
cy=0
cx+=int(w/splitx)
return base_img
#update information after click
def pos_update(pos_index,pos_list,kkk):
if pos_available[pos_list.index(100)][pos_index]==1:
pos_list[pos_list.index(100)]=pos_list[pos_index]
pos_list[pos_index]=100
kkk+=1
return pos_list,kkk
#main program of game
def play_pazzle(event, x, y, flags, params):
global counter,img2,pos_list,kkk
img2=np.copy(img)
pic_list=split_pic(img)
#initialize
if event == cv2.EVENT_LBUTTONDOWN and counter==0:
pos_list=[0,1,2,3,4,5,6,7,100]
counter=1
pos_index=0
#make initial image
kkk=0
while kkk<100:
pos_list,kkk=pos_update(pos_index,pos_list,kkk)
pos_index=np.random.randint(0,splitx*splity)
new_pic=pic_apdate(pic_list,pos_list)
cv2.imshow('window', new_pic)
#moving plate
elif event == cv2.EVENT_LBUTTONDOWN and counter==1:
posx=np.argmin(np.abs(np.array(posx_list)-x))
posy=np.argmin(np.abs(np.array(posy_list)-y))
pos_index=posx*splitx+posy
pos_list,kkk=pos_update(pos_index,pos_list,kkk)
new_pic=pic_apdate(pic_list,pos_list)
cv2.imshow('window', new_pic)
if pos_list==[0,1,2,3,4,5,6,7,100]:
cv2.putText(img2, 'Complete!!',(int(w/2)-150, int(h/2)+50),cv2.FONT_HERSHEY_SIMPLEX,fontScale=2,color=(0,0,0),thickness=6)
cv2.imshow('window', img2)
counter=0
#numbering to plate(not neccessaly)
h,w=img.shape[:2]
for j in range(splitx):
for i in range(splity):
num=j*splitx+i
cv2.putText(img, str(num) ,(int(w/splitx*j) +100, int(h/splity*i) +100),cv2.FONT_HERSHEY_SIMPLEX,fontScale=1.0,color=(255,0,0),thickness=2)
cv2.imwrite('aaa.jpg',img)
cv2.imshow('window', img)
cv2.setMouseCallback('window', play_pazzle)
cv2.waitKey(0)
cv2.destroyAllWindows()
It is extremely long program.
I think it is difficult to understand only this program.
So, I explain the content of program in the following items.
Commentary1 : Input Information Section
At first, I explain about the below section.
#import library
import cv2
import numpy as np
import random
#specify the picture file
file_name='sample_pic.jpg'
#reading picture
img=cv2.imread(file_name,cv2.IMREAD_COLOR)
h,w=img.shape[:2]
#split number of puzzle
splitx=3
splity=3
counter=0
#list fir checking the clicked position
posx_list=[w/6,w/2,w*5/6]
posy_list=[h/6,h/2,h*5/6]
#designate a place where can move
pos0=[100,1,0,1,0,0,0,0,0]
pos1=[1,100,1,0,1,0,0,0,0]
pos2=[0,1,100,0,0,1,0,0,0]
pos3=[1,0,0,100,1,0,1,0,0]
pos4=[0,1,0,1,100,1,0,1,0]
pos5=[0,0,1,0,1,100,0,0,1]
pos6=[0,0,0,1,0,0,100,1,0]
pos7=[0,0,0,0,1,0,1,100,1]
pos8=[0,0,0,0,0,1,0,1,100]
pos_available=[pos0,pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8]
In this part, the first half is importing the library, reading the image, and specifying the number of divisions.
Also, ‘posx_list’ and ‘posy_list’ is an array used checking the which plate is clicked when playing.
And the most important program in this part is arrays such as pos0, pos1, etc.
This array specifies which plate can be replaced to empty square.
For instance, the empty square is ‘0’ position, it can replace to ‘1’ or ‘3’ plate.
In ‘pos0=[100,1,0,1,0,0,0,0,0]’ , ‘100’ is where now, and ‘1’ means can replace and ‘0’
means cannot replace.
Based on this information, we will play the puzzle game.
Commentary2 : Definition of Sub Function
Next, I explain about below section.
#split base img
def split_pic(img):
h,w=img.shape[:2]
cx,cy=0,0
pic_list=[]
for j in range(splitx):
for i in range(splity):
spic=img[cy:cy+int(h/splity),cx:cx+int(w/splitx),:]
pic_list.append(spic)
cy+=int(h/splity)
cy=0
cx+=int(w/splitx)
pic_list=np.array(pic_list)
return pic_list
#update after click
def pic_apdate(pic_list,pos_list):
base_img=np.zeros((h,w,3),np.uint8)
cx,cy=0,0
for j in range(splitx):
for i in range(splity):
ppp=splitx*j+i
if pos_list[ppp]!=100:
base_img[cy:cy+int(h/splity),cx:cx+int(w/splitx),:]=pic_list[pos_list[ppp]]
cy+=int(h/splity)
cy=0
cx+=int(w/splitx)
return base_img
#update information after click
def pos_update(pos_index,pos_list,kkk):
if pos_available[pos_list.index(100)][pos_index]==1:
pos_list[pos_list.index(100)]=pos_list[pos_index]
pos_list[pos_index]=100
kkk+=1
return pos_list,kkk
At first, ‘split_pic’ function split the base image to designated numbers.
By putting these split images randomly, puzzle initial condition is made.
Next is about ‘pos_update’ function. (It is located at third.)
In this game, information of squares condition is stored in the variable ‘pos_list’ at anytime.
If an interchangeable location in the image were to be clicked, it is neccesay to exchange the parts, so the information of ‘pos_list’ is also updated.
Exchangeability is determined using the variable ‘pos_available’ mentioned above.
Finally, about ‘pic_update’ function.
This function update the puzzle images based on the ‘pos_list’ updated by ‘pos_update’ function.
Commentary3 : Definition of Main Function
Finally, below section is main program of this puzzle game.
#main program of game
def play_pazzle(event, x, y, flags, params):
global counter,img2,pos_list,kkk
img2=np.copy(img)
pic_list=split_pic(img)
#initialize
if event == cv2.EVENT_LBUTTONDOWN and counter==0:
pos_list=[0,1,2,3,4,5,6,7,100]
counter=1
pos_index=0
#make initial image
kkk=0
while kkk<100:
pos_list,kkk=pos_update(pos_index,pos_list,kkk)
pos_index=np.random.randint(0,splitx*splity)
new_pic=pic_apdate(pic_list,pos_list)
cv2.imshow('window', new_pic)
#moving plate
elif event == cv2.EVENT_LBUTTONDOWN and counter==1:
posx=np.argmin(np.abs(np.array(posx_list)-x))
posy=np.argmin(np.abs(np.array(posy_list)-y))
pos_index=posx*splitx+posy
pos_list,kkk=pos_update(pos_index,pos_list,kkk)
new_pic=pic_apdate(pic_list,pos_list)
cv2.imshow('window', new_pic)
if pos_list==[0,1,2,3,4,5,6,7,100]:
cv2.putText(img2, 'Complete!!',(int(w/2)-150, int(h/2)+50),cv2.FONT_HERSHEY_SIMPLEX,fontScale=2,color=(0,0,0),thickness=6)
cv2.imshow('window', img2)
counter=0
#numbering to plate(not neccessaly)
h,w=img.shape[:2]
for j in range(splitx):
for i in range(splity):
num=j*splitx+i
cv2.putText(img, str(num) ,(int(w/splitx*j) +100, int(h/splity*i) +100),cv2.FONT_HERSHEY_SIMPLEX,fontScale=1.0,color=(255,0,0),thickness=2)
cv2.imwrite('aaa.jpg',img)
cv2.imshow('window', img)
cv2.setMouseCallback('window', play_pazzle)
cv2.waitKey(0)
cv2.destroyAllWindows()
The processing details are as follows.
①Reading base image and click image then start game.
②By clicking second and subsequent, the game progress by using the functions that introduced above section.
③The puzzle is completed, the sentence ‘COMPLETE!!’ is displayed.
That is all for the commentary.
This time it was 3×3, but it can be applied to 4×4 and 5×5.
If you are interested, please give it a try.
That’s all. Thank you!!
コメント