Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- from random import shuffle
- class Tile:
- def __init__(self, id, corner, side_length, images_path, empty = False):
- print(id, corner, side_length, images_path)
- print(os.path.join(images_path, str(id) + ".png"))
- self.id = id
- self.corner = corner
- self.side_length = side_length
- self.img = loadImage(os.path.join(images_path, str(id) + ".png"))
- self.empty = empty
- def swap_position(self, other):
- self.corner, other.corner = other.corner, self.corner
- def draw(self, draw_corners=True, draw_if_empty=False):
- if self.empty and not draw_if_empty:
- fill(0)
- rect(self.corner[0], self.corner[1], self.side_length, self.side_length)
- else:
- image(
- self.img,
- self.corner[0],
- self.corner[1],
- self.side_length,
- self.side_length
- )
- if not draw_corners:
- return
- corners = [[None for _ in range(2)] for _ in range(2)]
- for i in range(2):
- for j in range(2):
- corners[i][j] = (
- self.corner[0] + (self.side_length if i else 0),
- self.corner[1] + (self.side_length if j else 0)
- )
- line(corners[0][0][0], corners[0][0][1], corners[0][1][0], corners[0][1][1])
- line(corners[0][0][0], corners[0][0][1], corners[1][0][0], corners[1][0][1])
- line(corners[0][1][0], corners[0][1][1], corners[1][1][0], corners[1][1][1])
- line(corners[1][0][0], corners[1][0][1], corners[1][1][0], corners[1][1][1])
- def __str__(self):
- return "<Tile {} {} {} {} {}>".format(self.id, self.corner, self.side_length, self.img, self.empty)
- def __repr__(self):
- return self.__str__()
- class Board:
- def __init__(self, num_tiles, side_length, corner, images_path, shuffle_tiles = True):
- self.num_tiles = num_tiles
- self.corner = corner
- self.side_length = side_length
- self.dimension = int(sqrt(num_tiles))
- self.tiles = []
- tile_side_length = floor(self.side_length / self.dimension)
- tile_corner = self.corner
- tiles_order = [i for i in range(num_tiles-1)]
- if shuffle_tiles:
- shuffle(tiles_order)
- # add the last element, which is empty
- tiles_order.append(num_tiles-1)
- for i in range(num_tiles):
- if i % self.dimension == 0 and i > 0:
- tile_corner = (self.corner[0], tile_corner[1] + tile_side_length)
- id = tiles_order[i]
- self.tiles.append(Tile(id, tile_corner, tile_side_length, images_path, id == num_tiles-1))
- tile_corner = (tile_corner[0] + tile_side_length, tile_corner[1])
- def get_tile_num_from_point(self, p):
- for i in range(self.num_tiles):
- tile = self.tiles[i]
- if tile.corner[0] <= p[0] < tile.corner[0] + tile.side_length:
- if tile.corner[1] <= p[1] < tile.corner[1] + tile.side_length:
- return i
- return -1
- def move_tile(self, id, change):
- """Move the tile in a direction."""
- num = None
- for i in range(self.num_tiles):
- if self.tiles[i].id == id:
- num = i
- break
- cell = (num // self.dimension, num % self.dimension)
- other_cell = (cell[0] + change[0], cell[1] + change[1])
- if not (0 <= other_cell[0] < self.dimension and 0 <= other_cell[1] < self.dimension):
- return
- other_num = other_cell[0]*self.dimension + other_cell[1]
- # print("Moving num={} cell={} tile={} onum={} ocell={} otile={}".format(num, cell, self.tiles[num], other_num, other_cell, self.tiles[other_num]))
- self.tiles[num].swap_position(self.tiles[other_num])
- self.tiles[num], self.tiles[other_num] = self.tiles[other_num], self.tiles[num]
- self.tiles[num].draw()
- self.tiles[other_num].draw()
- def move_tile_toward_empty(self, num):
- """Move a non-empty tile by swapping it with the empty tile, only if they are adjacent."""
- if self.tiles[num].id == self.num_tiles - 1:
- return
- cell = (num // self.dimension, num % self.dimension)
- # print("Will try to move toward empty num={}, cell={}, tile={}".format(num, cell, self.tiles[num]))
- for i in range(self.num_tiles):
- if self.tiles[i].empty:
- empty_cell = (i // self.dimension, i % self.dimension)
- change = (cell[0] - empty_cell[0], cell[1] - empty_cell[1])
- if abs(change[0]) + abs(change[1]) == 1:
- # they are vertically or horizontally adjacent
- self.move_tile(self.num_tiles - 1, change)
- return True
- return False
- return False
- def draw_all_tiles(self, draw_corners=True, draw_empty=False):
- for tile in self.tiles:
- tile.draw(draw_corners, draw_empty)
- class Game:
- def __init__(self, num_tiles, board_length, corner_point, images_path):
- if int(sqrt(num_tiles))**2 != num_tiles:
- raise ValueError()
- self.num_tiles = num_tiles
- self.status = 1
- self.board = Board(num_tiles, board_length, corner_point, images_path)
- self.board.draw_all_tiles()
- def get_status(self):
- return self.status
- def process_click(self, x, y):
- num = self.board.get_tile_num_from_point((x, y))
- # print("Processing click, x={} y={} num={}".format(x, y, num))
- if 0 <= self.board.tiles[num].id < self.num_tiles - 1:
- self.board.move_tile_toward_empty(num)
- self.check_victory()
- def process_key(self, key_code):
- directions = {}
- directions[UP] = (1, 0)
- directions[DOWN] = (-1, 0)
- directions[LEFT] = (0, 1)
- directions[RIGHT] = (0, -1)
- if key_code in directions:
- self.board.move_tile(self.num_tiles - 1, directions[key_code])
- self.check_victory()
- def check_victory(self):
- if self.status != 1:
- return
- # status is 1 (game ongoing)
- for i in range(self.num_tiles):
- if self.board.tiles[i].id != i:
- return
- # success, all are good
- self.status = 2
- self.board.draw_all_tiles(False, True)
- print("The game has ended!")
- g = None
- IMG_FOLDER_PATH = "img2"
- def setup():
- size(600, 600)
- background(0, 0, 0)
- stroke(255, 255, 255)
- global g
- g = Game(4, min(width, height), (0, 0), IMG_FOLDER_PATH)
- def draw():
- pass
- def mouseClicked():
- if g.get_status() != 1:
- return
- g.process_click(mouseX, mouseY)
- def keyPressed():
- if g.get_status() != 1:
- return
- g.process_key(keyCode)
Add Comment
Please, Sign In to add comment