Advertisement
Guest User

Snake and ladder game

a guest
Oct 9th, 2016
845
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.23 KB | None | 0 0
  1.  
  2. #Load tkinter module. it is available by default by python and we just need to import it
  3. from tkinter import *
  4.  
  5. #Import messagebox and promptbox modules for tkinter
  6. import tkinter.simpledialog
  7.  
  8. #this is used for color cycle when player reach end of the game
  9. import threading
  10.  
  11. #try to load PIL (Pillow) module if it is available and drop an error if it is not available
  12. try:
  13.     from PIL import ImageTk, Image
  14. except:
  15.     print("Python PIL package not found. Please install it to be able load images correctly.")
  16. import random
  17.  
  18. dice_num=0
  19. #Assign array for snake holes colors in labels
  20. SNAKE_HOLES = [48,44,   39,34,   28,13]
  21. #Assign array for ladder bridges colors in labels
  22. LADDER_BRIDGES = [3,8,   6,26,   14,22,   32,49]
  23. #set current position
  24. player_1_pos=0
  25. #count player moves
  26. player_moves=0
  27. #count snake bites
  28. player_bites=0
  29. #count ladder climbs
  30. player_climb=0
  31. #player name variable
  32. player_name=""
  33. #Time holder
  34. time_elapsed=0
  35.  
  36. def randomColor():
  37.     global PlayerMovesLabel
  38.     COLORS = ['red','blue','yellow','pink','lightblue','steel blue','turquoise','sandy brown','purple','violet red','violet','maroon','tomato','orange','green yellow']
  39.     randomColor = random.randint(0, len(COLORS))
  40.     PlayerMovesLabel.config(bg=COLORS[randomColor])
  41.  
  42.  
  43.  
  44. def colorCycle():
  45.     global PlayerMovesLabel, time_elapsed
  46.     #put it inside try, so that if in middle of color switching, main thread is closed, it don't crash
  47.     try:
  48.         #assign our timer
  49.         mytimer = threading.Timer(0.2, colorCycle)
  50.         #link timer to main thread, so that if main thread is closed, timer get stopped
  51.         mytimer.daemon = True
  52.         #start timer
  53.         mytimer.start()
  54.  
  55.         #if player is in position 50, start the cycle
  56.         if player_1_pos==50:
  57.             randomColor()
  58.         else:
  59.             #otherwise keep background white
  60.             PlayerMovesLabel.config(bg='white')
  61.  
  62.         time_elapsed=time_elapsed+1
  63.     except:
  64.         #if error, do nothing. error means program has been exited but thread is running for one more last time.
  65.         return
  66.  
  67.  
  68. def movePlayer():
  69. #define our global variables so that function can access variables outside of its scope
  70.     global player_1_pos
  71.     global dice_num
  72.     global player_moves
  73.     global player_bites
  74.     global player_climb
  75.     global grid_array
  76.     global PlayerMovesLabel
  77.     global diceRollLabel
  78.     global time_elapsed
  79.  
  80. #If player reach goal, reset the counter and colors
  81.     if player_1_pos==50:
  82.         player_1_pos=0
  83.         player_moves=0
  84.         player_1_pos=0
  85.         player_bites=0
  86.         player_climb=0
  87.         grid_array[50-1].config(bg="white")
  88.         time_elapsed=0
  89.  
  90. #get our old and new player positions
  91.     old_player_pos=player_1_pos
  92.     new_player_pos=player_1_pos+dice_num
  93.  
  94. #if there is snake bite or ladder climb, show feedback message
  95.     additional_message=""
  96.  
  97. #code to take care when move is more than 50
  98.     if new_player_pos>50:
  99.         new_player_pos=50-(new_player_pos-50)
  100.  
  101. #detect if player go to snake hole
  102. #enumerate snake holes to get their Index ID and
  103. #go through list of snake holes
  104.     for idx,val in enumerate(SNAKE_HOLES):
  105. #in our array, first value (even index number) is snake head, and second value (odd index number) is snake tail, detect head
  106.         if idx % 2 == 0:
  107. #if it is head, and player is on head
  108.             if new_player_pos==SNAKE_HOLES[idx]:
  109. #move player to tail number
  110.                 new_player_pos=SNAKE_HOLES[idx+1]
  111. #Update player bites counter
  112.                 player_bites=player_bites+1
  113.                 additional_message="Bitten | "
  114.  
  115. #detect if player go to ladder bottom
  116. #enumerate ladder bridges to get their Index ID and
  117. #go through list of ladders
  118.     for idx,val in enumerate(LADDER_BRIDGES):
  119. #in our array, first value (even index number) is ladder bottom, and second value (odd index number) is ladder top, detect bottom
  120.         if idx % 2 == 0:
  121. #if it is ladder bottom, and player is on bottom of ladder
  122.             if new_player_pos==LADDER_BRIDGES[idx]:
  123. #climb the ladder!
  124.                 new_player_pos=LADDER_BRIDGES[idx+1]
  125. #Update player climb counter
  126.                 player_climb=player_climb+1
  127.                 additional_message="Climb | "
  128.  
  129.  
  130.  
  131.  
  132. #change old position to white
  133.     if old_player_pos>0:
  134.         grid_array[old_player_pos-1].config(bg="white")
  135.  
  136. #change new position to yellow
  137.     grid_array[new_player_pos-1].config(bg="yellow")
  138.  
  139. #apply change to player position variable
  140.     player_1_pos=new_player_pos
  141.     player_moves=player_moves+1
  142.  
  143.  
  144.     if player_1_pos == 50:
  145.         PlayerMovesLabel['text'] = "*WON* Move: " + str(player_moves) + ", Bite: " + str(player_bites) + ", Climb:" + str(player_climb) + " *WON*"
  146.         tkinter.messagebox.showinfo("*WON*", player_name+" Won the game in "+str(player_moves) + " moves during "+ str(int(time_elapsed/5)) +" seconds!")
  147.     else:
  148.         PlayerMovesLabel['text']=additional_message + "Move: " + str(player_moves) + ", Bite: " + str(player_bites) + ", Climb:" + str(player_climb)
  149.  
  150. #function when Roll button is clicked
  151. def rollTheDice():
  152.         global dice_num
  153.         global diceRollLabel
  154.     #get a random number between 1 to 6
  155.         dice_num=random.randint(1,6)
  156.     #write number into label
  157.         diceRollLabel['text']=player_name + " Rolled: " + str(dice_num)
  158.     #move the player!
  159.         movePlayer()
  160.  
  161.  
  162. def createGUI():
  163.     global grid_array
  164.     global PlayerMovesLabel
  165.     global diceRollLabel
  166.     global diceWindow
  167.     global player_name
  168.  
  169.  
  170.     # create diceWindow
  171.     diceWindow = Tk()
  172.  
  173.  
  174.  
  175.     # Set title for diceWindow
  176.     diceWindow.title("SNAKE & LADDERS")
  177.     # Make window not resizable
  178.     diceWindow.resizable(width=False, height=False)
  179.     diceWindow.config(bg='white')
  180.     # Load logo if PIL module is installed:
  181.     try:
  182.         #load logo.gif
  183.        logoFile=Image.open("lbg='white'ogo.gif")
  184.         #resize the image to match field size
  185.        logo = logoFile.resize((300, 37), Image.ANTIALIAS)
  186.         #define image type
  187.        logo = ImageTk.PhotoImage(logo)
  188.         #put image into a label
  189.        logoContainer = Label(diceWindow, image = logo,bg='white')
  190.         #show the label
  191.        logoContainer.grid(row=0,column=1,columnspan=10)
  192.  
  193.     except:
  194.     #otherwise just show a label
  195.         RevertLogoImage = Label(diceWindow, text="Snake & Ladder",bg='white',font=("Arial",30))
  196.         RevertLogoImage.grid(row=0, column=1, columnspan=10)
  197.         print("Logo rendering has been skipped.")
  198.  
  199.     #create moves indicator label
  200.     PlayerMovesLabel = Label(diceWindow, text="Please enter your name in popup window", bg='white')
  201.     PlayerMovesLabel.grid(row=1,column=1,columnspan=10)
  202.  
  203.     #Create button for GUI
  204.     btnRoll = Button(diceWindow, text="Roll", command=rollTheDice, width=30)
  205.     #show it on screen
  206.     btnRoll.grid(row=3,column=1,columnspan=10)
  207.  
  208.     #create our board interface
  209.     #define out array of labels first
  210.     grid_array = []
  211.     for y in range (0,5):
  212.         for x in range (0,10):
  213.             array_num=((x+1)+(y*10))
  214.             grid_array.append(Label(diceWindow, borderwidth=8,text=  array_num  ))
  215.  
  216.             #get x and y and put them into new variable to avoid editing original x/y variables which can cause infinite loop
  217.             xx=x
  218.             yy=y
  219.  
  220.             #a simple control to make board-like numbers to position correctly
  221.             yy=abs(yy-5)
  222.             #reverse the numbers if it is not even row
  223.             if not yy % 2:
  224.                 xx=abs(xx-9)
  225.  
  226.             grid_array[array_num - 1].grid(row=  (yy+1)  +4,column=(xx+1))
  227.             #fix problem with windows OS that don't show labels in white color by default
  228.             grid_array[array_num - 1].config(bg='white')
  229.             #take care of snake holes, apply custom colors
  230.             if array_num in SNAKE_HOLES:
  231.                 #if it is even index number, means it is snake head
  232.                 if SNAKE_HOLES.index(array_num) % 2 == 0:
  233.                     #red is for snake head
  234.                     grid_array[array_num-1].config(fg="red")
  235.                 else:
  236.                     #orange is for snake tail
  237.                     grid_array[array_num-1].config(fg="orange")
  238.  
  239.             #take care of ladder bridges, apply custom colors
  240.             if array_num in LADDER_BRIDGES:
  241.                 #if it is even index number, it means it is ladder bottom
  242.                 if LADDER_BRIDGES.index(array_num) % 2 == 0:
  243.                     #blue is ladder bottom
  244.                     grid_array[array_num-1].config(fg="blue")
  245.                 else:
  246.                     #blue is ladder top
  247.                     grid_array[array_num-1].config(fg="lightblue")
  248.     #initialize timer
  249.     colorCycle()
  250.  
  251.     #If user cancel promptbox dialog or left name empty, ask again
  252.     while player_name=='' or player_name is None:
  253.         player_name=tkinter.simpledialog.askstring("Player Name","Please enter your name: ")
  254.         PlayerMovesLabel['text']='- Waiting for first Roll -'
  255.  
  256.     #create introduction label
  257.     diceRollLabel = Label(diceWindow, bg="white", text="Welcome "+player_name+", Please roll your dice!")
  258.     diceRollLabel.grid(row=2,column=1,columnspan=10)
  259.  
  260.     # Establish the window
  261.     diceWindow.mainloop()
  262.  
  263.  
  264. #create GUI to start things up
  265. createGUI()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement