8 Queens – WEEK 5 (Python)

This is the last week, we were supposed to complete our project this week. So, I told you guys last week that I might change my winning logic, I changed my winning logic. My new logic is pretty simple, here it is:

def winning():
    for u in range(len(queen_details)):
            for o in range(len(queen_details)):
                if u != o:
                    if queen_safe(queen_details[u][0],queen_details[u][1],queen_details[o][0],queen_details[o][1]):
                        return False
    return True

def queen_safe(x,y,oldx,oldy):
    return x == oldx or y == oldy or abs(x-oldx) == abs(y-oldy)

In “winning” function, I’m using 2 nested loops of length of “queen_details”. Then I called another function, queen_safe, in it. “queen_safe” it takes x and y coordinates of two queens, and checks if the point x or point y or their gradient is same or not. To show that the wrong queen is placed, I improted these new images of queens. They are same as those we placed before but their color is different.

Download and save these images in the resources folder. You should use the same names like “error_queen1.png”,”error_queen2.png”… Then I made different labels to of text for my game screen.

label = pyglet.text.Label("",
     font_name='Castellar',
     font_size=40,
     x=width//2, y=220,
     anchor_x='center', anchor_y='center', color=(51, 51, 255, 205),bold = True)

I’m not going into the details of how to make a label. I made couple of these labels with different names and different x and y points. I made another function for keyboard event.

@screen.event
def on_key_press(symbol,modifiers):
    global keyboard, count, queen_details, error_queen, queen_num
    wrong.text = ""
    click=pyglet.media.load('resources/click.wav')
    if page == 3:
        screen.set_mouse_visible(False)
        if keyboard == 0:
            selector[0].visible = True
            keyboard = 1
        c = 0
        for i in range(8):
            for j in range(8):
                if selector[c + j].visible:
                    if symbol == key.SPACE:
                        click.play()
                        if queen_num <= 7:                            
                            visible(i,j,c+j)
                            count += 1
                            Wrong_check()
                        else:
                            if not winning():
                                if queen[c + j].visible:
                                    queen[c + j].visible = False
                                    queen_details.remove((i,j,tile_num))
                                    queen_num -= 1
                                    count += 1
                                if error_queen[c + j].visible:
                                    error_queen[c + j].visible = False
                                    count += 1
                                else:
                                    label.text = "Can't place more queens"
                
                    if symbol == key.UP:
                        selector[c + j].visible = False
                        c += 8
                        if i == 7:
                            c = 0
                            selector[c + j].visible = True
                        else:
                            selector[c + j].visible = True
                    elif symbol == key.DOWN:
                        selector[c + j].visible = False
                        c -= 8
                        selector[c + j].visible = True
                    elif symbol == key.RIGHT:
                        if selector[63] .visible:
                            selector[0].visible = True
                            selector[63].visible = False
                        else:
                            selector[c + j].visible = False
                            c += 1
                            selector[c + j].visible = True
                    elif symbol == key.LEFT:
                        selector[c + j].visible = False
                        c -= 1
                        selector[c + j].visible = True
                    return
            c += 8

I also included another functions “on_mouse+motion”. It takes four arguments, x ,y ,dx, and dy. I used that function to change the text of the labels.

@screen.event
def on_mouse_motion(x,y,dx,dy):
    global keyboard
    if x != dx or y != dy:
        label.text = ""
        wrong.text = ""
        for I in range(64):
            selector[i].visible = False
        keyboard = 0
        screen.set_mouse_visible(True)

These are all the functions I neede to complete my game. But I did some customizations to make my game look cool. Like I added intro page, instructions, play again button, exit button, and sound for click and wrong move. I designed the images for these pages and button on Adobe Photoshop, you can design yours. Of course you will design yours, you won’t be using my intro page. If you do so you will have to do some changes in my code according to your images.

Download these images and then add them to your resources folder, with same names as given. Like “instructions.png”,”Main.png”… I can’t upload the sounds I used, what you can do is just download any audio with WAV extension. I download two of them one which had a click sound other which had error sound. They were like only  sec long. Download any of them and save them in your resources folder with name “click.wav” and “wrong.wav”. Here is my complete code.

#############################################################################################################################################
###################################################### _author_ = "Abdul Junaid"#############################################################
############################################ published on www.codehunterz.wordpress.com #####################################################
#############################################################################################################################################

import pyglet 
from pyglet.window import Window, mouse, gl, key

# creating a window
# I'm setting width and height according to the fullscreen resoulutions of my screen
width = 1366
height = 715
screen = Window(width, height,
                resizable=True,
                caption="8 Queens",
                config=pyglet.gl.Config(double_buffer=True),
                vsync=False)

#To change cursor
cimage = pyglet.image.load(('resources/Cursor.png'))
cursor = pyglet.window.ImageMouseCursor(cimage, 0, 50)
screen.set_mouse_cursor(cursor)

# Display an image in the application window

# introduction window

intro = pyglet.sprite.Sprite(pyglet.image.load(("resources/Main.png")))
instructions = pyglet.sprite.Sprite(pyglet.image.load(("resources/instructions.png")))

# Selection Buttons

pla = pyglet.image.load("resources/play.png")
play = pyglet.sprite.Sprite(pla,(width-pla.width)//2,(height-pla.height)//2)
play.visible = False

exi = pyglet.image.load("resources/exit.png")
exit = pyglet.sprite.Sprite(exi,(width-exi.width)//2,(height-exi.height-400)//2)
exit.visible = False

# loading board image
board = pyglet.sprite.Sprite(pyglet.image.load(('resources/chess-boards.jpg')))

# initiating global vriables and list
queen_num = 0
queen_details = []
keyboard = 0
page = 1

# loading image of queens and storing them in list, and placing selector on tiles
queen = []
error_queen = []
selector = []
count = 0
a = 1
for i in range(64):
    if ((i > 7) and (i%8 == 0)):
        a += 1
    queen.append(pyglet.sprite.Sprite(pyglet.image.load(("resources/queen"+str(a)+".png"))))
    error_queen.append(pyglet.sprite.Sprite(pyglet.image.load(("resources/error_queen"+str(a)+".png"))))
    selector.append(pyglet.sprite.Sprite(cimage))
    error_queen[i].visible = False
    queen[i].visible = False
    selector[i].visible = False

# assigning images to tiles, and x, y axis values to the images
                         # starting points of the first tile in each row
row = [[317,248],[331,293],[345,335],[358,372],[370,406],[380,437],[391,464],[399,491],[407,516]]
wid = 91 # width of the tile in first row
indx = 0 # to keep record of which row is being used
c = 0 # to keep record that 8 queens are placed in one row
for i in range(64):
    if (c == 8): # checking if 8 queens are placed in a row
        c = 0
    if (i > 7 and i % 8 == 0): # checking if the row is changed
        wid -= 3.5 # width of tiles in row changes
        indx += 1 # row number
    b = row[indx] # opening the list acoording to the row number
    queen[i].x = b[0]+(wid*c) # assigning x_axis value to the respective queen
    error_queen[i].x = b[0]+(wid*c)
    selector[i].x = (b[0]+(wid*c))+20
    queen[i].y = b[1] # assigning y_axis value to the respective queen
    error_queen[i].y = b[1]
    selector[i].y = b[1]-25
    c+=1

# for writing text on window
label = pyglet.text.Label("",
                             font_name='Castellar',
                             font_size=40,
                             x=width//2, y=220,
                             anchor_x='center', anchor_y='center', color=(51, 51, 255, 205),bold = True)

wrong = pyglet.text.Label("",
                             font_name='Castellar',
                             font_size=40,
                             x=width//2, y=600,
                             anchor_x='center', anchor_y='center', color=(51, 51, 255, 205),bold = True)

win = pyglet.text.Label("",
                             font_name='Castellar',
                             font_size=80,
                             x=width//2, y=600,
                             anchor_x='center', anchor_y='center', color=(0, 0, 0, 205),bold = True)

queen_count = pyglet.text.Label("",
                             font_name='Castellar',
                             font_size=30,
                             x=width//2, y=70,
                             anchor_x='center', anchor_y='center', color=(0, 0, 0, 205),bold = True)

move = pyglet.text.Label("",
                             font_name='Castellar',
                             font_size=30,
                             x=width//2, y=30,
                             anchor_x='center', anchor_y='center', color=(0, 0, 0, 205),bold = True)

@screen.event
def on_mouse_motion(x,y,dx,dy):
    global keyboard
    if x != dx or y != dy:
        label.text = ""
        wrong.text = ""
        for i in range(64):
            selector[i].visible = False
        keyboard = 0
        screen.set_mouse_visible(True)

def on_draw():
    screen.clear() # Clearing screen
    board.draw() # Drawing board on screen
    move.text = "Number of moves: "+str(count) # changing text of label "move"
    queen_count.text = "Number of queen placed: " +str(queen_num) # changing text of label "queen_count"
    # changing the visibility of images accordig to the page number

    if page == 1:
        intro.visible = True
        instructions.visible = False
        board.visible = False
    elif page == 2:
        instructions.visible = True
        intro.visible = False
        board.visible = False
    elif page == 3:
        intro.visible = False
        instructions.visible = False
        board.visible = True

    # drawing queens, error queens and tile selector on board
        
    for i in range(63,-1,-1):
        queen[i].draw()
        error_queen[i].draw()
        selector[i].draw()
    
    # changing text of label "win", and visibility of buttons "Play Again" and "Exit"
    if queen_num <= 7:
        win.text = ""
    else:
        if winning():
            win.text = "YOU WON"
            play.visible = True
            exit.visible = True

    # draw all the labels, pages and buttons
    
    label.draw()
    move.draw()
    win.draw()
    wrong.draw()
    queen_count.draw()
    instructions.draw()
    intro.draw()
    exit.draw()
    play.draw()
   

@screen.event
def on_mouse_press(x, y, button, modifier):
    global queen_details, queen_num, count, page
    if (button == mouse.LEFT): # Check if left button was clicked
        click=pyglet.media.load('resources/click.wav')
        if page == 1:
            click.play()
            if 275 < x and x < 1129:
               if ((517 < x and x < 859) and (368 < y and y < 470)):
                    page = 3
               if 182 < y and y < 286:
                   page = 2
        elif page == 2:
            click.play()
            if 429 < x and x < 915:
                if 26 < y and y < 180:
                    page = 1
        elif page == 3:
            click.play()
            c = 0
            for i in range(8): # for row
                a = row[i]
                b = row[i+1]
                if ((y > a[1]) and (y < b[1])):
                    for j in range(8): # for column
                        tile_num = c + j
                        if ((x > (queen[tile_num].x)) and (x < ((queen[tile_num].width)+queen[tile_num].x))): # checking the tile
                            if queen_num < 8:               
                                visible(i,j,tile_num)
                                win.text = ""
                                count += 1
                            else:
                                if not winning():
                                    if queen[tile_num].visible:
                                        queen[tile_num].visible = False
                                        queen_details.remove((i,j,tile_num))
                                        queen_num -= 1
                                        count += 1
                                    if error_queen[tile_num].visible:
                                        error_queen[tile_num].visible = False
                                        count += 1
                                    else:
                                        label.text = "Can't place more queens"
                c += 8
            Wrong_check()
            if winning() and queen_num >=8:
                if (((screen.width-play.width)//2) < x and x < ((screen.width//2)+play.width)):
                    if ((301) < y and y < (411)):
                        clear()
                    elif ((207-play.width) < y and y < (207)):
                        quit()
    
# for keyboard
@screen.event
def on_key_press(symbol,modifiers):
    global keyboard, count, queen_details, error_queen, queen_num
    wrong.text = ""
    click=pyglet.media.load('resources/click.wav')
    if page == 3:
        screen.set_mouse_visible(False)
        if keyboard == 0:
            selector[0].visible = True
            keyboard = 1
        c = 0
        for i in range(8):
            for j in range(8):
                if selector[c + j].visible:
                    if symbol == key.SPACE:
                        click.play()
                        if queen_num <= 7:                            
                            visible(i,j,c+j)
                            count += 1
                            Wrong_check()
                        else:
                            if not winning():
                                if queen[c + j].visible:
                                    queen[c + j].visible = False
                                    queen_details.remove((i,j,tile_num))
                                    queen_num -= 1
                                    count += 1
                                if error_queen[c + j].visible:
                                    error_queen[c + j].visible = False
                                    count += 1
                                else:
                                    label.text = "Can't place more queens"
                
                    if symbol == key.UP:
                        selector[c + j].visible = False
                        c += 8
                        if i == 7:
                            c = 0
                            selector[c + j].visible = True
                        else:
                            selector[c + j].visible = True
                    elif symbol == key.DOWN:
                        selector[c + j].visible = False
                        c -= 8
                        selector[c + j].visible = True
                    elif symbol == key.RIGHT:
                        if selector[63] .visible:
                            selector[0].visible = True
                            selector[63].visible = False
                        else:
                            selector[c + j].visible = False
                            c += 1
                            selector[c + j].visible = True
                    elif symbol == key.LEFT:
                        selector[c + j].visible = False
                        c -= 1
                        selector[c + j].visible = True
                    return
            c += 8

# play again clearing everything
def clear():
    global queen_count,error_queen,queen_details,queen_num, count, keyboard
    count = 0
    queen_num = 0
    queen_details = []
    keyboard = 0
    page = 3
    move.text = ""
    label.text = ""
    wrong.text = ""
    win.text = ""
    queen_count.text = ""
    for i in range(64):
        queen[i].visible = False
        selector[i].visible = False
        error_queen[i].visible = False
    play.visible = False
    exit.visible = False
 
# Check for wrong move
def Wrong_check():
    for i in range(64):
            error_queen[i].visible = False
    wrong.text = ""
    for u in range(len(queen_details)):
        for o in range(len(queen_details)):
            if u != o:
                if queen_safe(queen_details[u][0],queen_details[u][1],queen_details[o][0],queen_details[o][1]):
                    error_queen[queen_details[o][2]].visible = True
                    error_queen[queen_details[u][2]].visible = True
                    wrong.text = "Wrong Move"
                    Wrong=pyglet.media.load('resources/wrong.wav')
                    Wrong.play()
           
# check for winning conditon

def winning():
    for u in range(len(queen_details)):
            for o in range(len(queen_details)):
                if u != o:
                    if queen_safe(queen_details[u][0],queen_details[u][1],queen_details[o][0],queen_details[o][1]):
                        return False
    return True

# to change the visibility of the queen

def visible(r,c,tile_num):
    global queen_num
    if queen[tile_num].visible:
        queen[tile_num].visible = False
        queen_details.remove((r,c,tile_num))
        queen_num -= 1
    else:
        queen[tile_num].visible = True
        queen_details.append((r,c,tile_num))
        queen_num += 1
    if error_queen[tile_num].visible:
        error_queen[tile_num].visible = False

#Check if queen is safe

def queen_safe(x,y,oldx,oldy):
    return x == oldx or y == oldy or abs(x-oldx) == abs(y-oldy)

def updated(dt):
    on_draw()

pyglet.clock.schedule_interval(updated, 1 / 60)

# Launch the application
pyglet.app.run()

Just copy paste the code and download all the files and add them in resources folder. Enjoy!

Here is the exe +  source code of this game. Learn how to make .exe from .py

Advertisements

One Comment Add yours

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s