Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- '''
- Lights Out
- author: diverges
- last modified: 7/12/2013
- '''
- from tkinter import *
- from random import randrange, shuffle
- import copy
- DEBUG = True
- W_WIDTH = 640 # width of window
- W_HEIGHT = 480 # height of window
- BOX_DIM = 80 # size of box width and height
- BOARDCOL= 5 # number of columns
- BOARDROW = 5 # number of rows
- BOARD_XINIT = 30 # leftmost x-coordinate of board
- BOARD_YINIT = 10 # topmost y_coordinate of board
- GAP = 2 # pixel gap between blocks
- DIFFICULTY = 10 # percentage of lights flipped and
- # number of moves made when
- # generating a board.
- assert (DIFFICULTY <= 100 and DIFFICULTY > 0)
- # R G B
- GREEN = '#55CC00'
- CYAN = '#22CCff'
- DGREEN = '#A0AA00'
- class Light:
- def __init__(self, row, col, x, y, on=0):
- self.id = 0
- self.row = row
- self.col = col
- self.x = x # x-coordinate
- self.y = y # y-coordinate
- self.on = on
- def toggle(self):
- self.on = not self.on
- # determine if a coordinate (x,y) is within the rectangle
- def contains(self, cord):
- a = (cord[0] > self.x and cord[0] < self.x + BOX_DIM and
- cord[1] > self.y and cord[1] < self.y + BOX_DIM)
- if a: print(str(self) + " " + str(cord))
- return a
- def __str__(self):
- return "Row: %s Col: %s ON: %s (%s,%s)" %(self.row, self.col, self.on,
- self.x, self.y)
- class Board(Frame):
- # Default game board
- gameTextId = None
- def __init__(self, parent):
- Frame.__init__(self, parent)
- self.parent = parent
- self.board = Canvas(self)
- self.gameOver = False
- # initial lights array
- # index go from left to right, top to bottom
- # value 0 = off and 1 = on
- self.lights = [ [None for _ in range(BOARDROW)] for _ in range(BOARDCOL)]
- for r in range(BOARDROW):
- for c in range(BOARDCOL):
- self.lights[r][c] = Light(r,c, BOARD_XINIT
- + (BOX_DIM + GAP)*(c), BOARD_YINIT
- + (BOX_DIM + GAP)*(r), 0)
- self.shuffle(DIFFICULTY//30 + 1)
- self.initBoard()
- self.save = copy.deepcopy(self.lights)
- # Add text
- self.gameTextId = self.board.create_text(475,150, text="text")
- newgame_Label = Label(parent, anchor=NW, font="Calibri",
- text="New Game")
- newgame_Label.bind("<Button 1>", self.newgame_Click)
- newgame_Label.place(x=450, y=300)
- reset_Label = Label(parent, anchor=NW, font="Calibri",
- text="Reset Board")
- reset_Label.bind("<Button 1>", self.reset_Click)
- reset_Label.place(x=450, y=400)
- def initBoard(self):
- self.parent.title("Board")
- self.pack(fill=BOTH, expand=1)
- self.board.pack(fill=BOTH, expand=1)
- self.drawBoard(self.board)
- # Backtracks a set number of moves from an end state to
- # generate a board
- def shuffle(self, moves):
- for x in range(moves):
- rows = list(range(BOARDROW))
- cols = list(range(BOARDCOL))
- shuffle(rows)
- shuffle(cols)
- count = 0
- for r in rows:
- for c in cols:
- if (DIFFICULTY >= randrange(100 + DIFFICULTY)
- and count <= (DIFFICULTY/100) * BOARDCOL
- * BOARDROW):
- self.toggleLight(self.lights[r][c])
- if DEBUG: print("Generated move: " +
- str(self.lights[r][c]))
- count += 1
- # Draws the given canvas(board).
- def drawBoard(self, board):
- for rows in self.lights:
- for light in rows:
- if DEBUG: print("drawing: " + str(light))
- x1 = light.x + BOX_DIM
- y1 = light.y + BOX_DIM
- color = GREEN
- if light.on:
- color = CYAN
- light.id = board.create_rectangle(light.x,light.y,x1,y1,
- outline=DGREEN, fill=color)
- # Record mouse click event.
- def mouseEvent(self, event):
- cord = (event.x, event.y)
- if DEBUG: print(cord)
- for rows in self.lights:
- for light in rows:
- if light.contains(cord):
- self.toggleLight(light)
- print("light toggled")
- self.checkState()
- self.updateBoard()
- # New game label click event.
- def newgame_Click(self, event):
- self.gameOver = False
- self.board.itemconfigure(self.gameTextId, text="New Game!")
- for rows in self.lights:
- for light in rows: light.on = 0
- self.shuffle(DIFFICULTY//20 + 1)
- self.updateBoard()
- self.save = copy.deepcopy(self.lights)
- # Reset label click event,
- # loads saved board.
- def reset_Click(self, event):
- self.lights = copy.deepcopy(self.save)
- self.updateBoard()
- print("board loaded")
- # Handles click event.
- def toggleLight(self, light):
- light.toggle()
- row = light.row
- col = light.col
- if light.row > 0:
- self.lights[row-1][col].toggle()
- if light.row < BOARDROW - 1:
- self.lights[row+1][col].toggle()
- if light.col > 0:
- self.lights[row][col-1].toggle()
- if light.col < BOARDCOL - 1:
- self.lights[row][col+1].toggle()
- # Counts the number of lights on.
- def lightsOn(self):
- n_on = 0
- for rows in self.lights:
- for light in rows:
- if light.on: n_on += 1
- return n_on
- # Determines if the current board has been solved.
- def checkState(self):
- self.gameOver = True
- for rows in self.lights:
- for light in rows:
- if light.on: self.gameOver = False
- # Redraw the board.
- def updateBoard(self):
- for rows in self.lights:
- for light in rows:
- color = GREEN
- if light.on:
- color = CYAN
- self.board.itemconfigure(light.id, fill=color)
- if self.gameOver:
- self.board.itemconfigure(self.gameTextId, text="Game Over!")
- if DEBUG: print("Game board has been solved")
- def main():
- root = Tk()
- ex = Board(root)
- root.geometry('%sx%s+%s+%s' %(W_WIDTH, W_HEIGHT, 100, 100))
- root.resizable(0,0)
- root.bind('<Button 1>', ex.mouseEvent)
- root.mainloop()
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement