Last active
August 29, 2015 14:22
-
-
Save xmunoz/ace5e92e647b8cba81ee to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
from copy import deepcopy | |
class Piece: | |
def __init__(self, display, stuck = False): | |
self.display = display | |
self.stuck = stuck | |
# 4 x 4 | |
self.height = len(display) | |
self.width = len(display[0]) | |
def actual_width(self): | |
''' | |
Determine the actual piece length to determine valid range of initial position | |
''' | |
widths = [0] * self.height | |
for row in self.display: | |
for i in range(len(row)): | |
if row[i] == "*": | |
widths[i] = 1 | |
return sum(widths) | |
def actual_height(self): | |
''' | |
Determine the actual piece height to determine valid range of initial position | |
''' | |
heights = [0] * self.width | |
for i in range(len(self.display)): | |
for cell in self.display[i]: | |
if cell == "*": | |
heights[i] = 1 | |
return sum(heights) | |
def rotate_clockwise(self): | |
display_copy = deepcopy(self.display) | |
for y in range(self.height): | |
for x in range(self.width): | |
self.display[y][x] = display_copy[x][y] | |
def rotate_counterclockwise(self): | |
''' | |
Got tired... | |
''' | |
self.rotate_clockwise() | |
class Pieces: | |
def __init__(self): | |
self.generate_pieces() | |
def generate_pieces(self): | |
LOG = 0 | |
ELLE = 1 | |
BELLE = 2 | |
SNAKE= 3 | |
BOX = 4 | |
self.all_pieces = {} | |
self.all_pieces[LOG] = Piece([["*", "*", "*", "*"], | |
[" ", " ", " ", " "], | |
[" ", " ", " ", " "], | |
[" ", " ", " ", " "]]) | |
self.all_pieces[ELLE] = Piece([["*", " ", " ", " "], | |
["*", " ", " ", " "], | |
["*", "*", " ", " "], | |
[" ", " ", " ", " "]]) | |
self.all_pieces[BELLE] = Piece([[" ", "*", " ", " "], | |
[" ", "*", " ", " "], | |
["*", "*", " ", " "], | |
[" ", " ", " ", " "]]) | |
self.all_pieces[SNAKE] = Piece([[" ", "*", " ", " "], | |
["*", "*", " ", " "], | |
["*", " ", " ", " "], | |
[" ", " ", " ", " "]]) | |
self.all_pieces[BOX] = Piece([["*", "*", " ", " "], | |
["*", "*", " ", " "], | |
[" ", " ", " ", " "], | |
[" ", " ", " ", " "]]) | |
def choose_random(self): | |
return deepcopy(self.all_pieces[random.randint(0,4)]) | |
class Board: | |
def __init__(self, length, width): | |
self.length = length | |
self.width = width | |
self.border_char = "*" | |
self.display = [] | |
self.initialize() | |
self.valid_moves = set(["a", "d", "w", "s"]) | |
def initialize(self): | |
for i in range(self.length): | |
self.display.append([" "] * self.width) | |
def show(self): | |
for i in range(self.length): | |
line = self.border_char | |
for j in range(self.width): | |
line += self.display[i][j] | |
line += self.border_char | |
print line | |
print self.border_char * (self.width + 2) | |
def add(self, piece, x, y): | |
for i in range(y, y + piece.actual_height()): | |
for j in range(x, x + piece.actual_width()): | |
piece_part = piece.display[i - y][j - x] | |
if piece_part == "*": | |
if self.display[i][j] == "*": | |
# a collision at the top, game over | |
return False | |
else: | |
# alter the board display | |
self.display[i][j] = "*" | |
if i == (self.length - 1) or self.display[i+1][j] == "*": | |
piece.stuck = True | |
return True | |
def perform_move_update(self, piece, x, move): | |
while move not in self.valid_moves: | |
print "Please input one of the valid characters: " | |
move = raw_input() | |
''' | |
Capable of updating x or piece, hence the deepcopy one level up | |
''' | |
if move == "a": | |
x -= 1 | |
elif move == "d": | |
x += 1 | |
elif move == "w": | |
piece.rotate_clockwise() | |
else: | |
piece.rotate_counterclockwise() | |
return x | |
def check_result(self, piece, x, y): | |
''' | |
Perform move validation | |
''' | |
# within bounds | |
if x < 0: | |
return False | |
if x > (self.width - piece.actual_width()): | |
return False | |
if y > (self.length - piece.actual_height()): | |
return False | |
for i in range(y, y + piece.actual_height()): | |
for j in range(x, x + piece.actual_width()): | |
if piece.display[i - y][j - x] == "*": | |
if self.display[i][j] == "*": | |
return False | |
return True | |
class Game: | |
''' | |
The main game class. | |
''' | |
def __init__(self): | |
self.length = 20 | |
self.width = 20 | |
self.board = Board(self.length, self.width) | |
self.pieces = Pieces() | |
self.game_over = False | |
def run(self): | |
while not self.game_over: | |
self.drop_piece() | |
def drop_piece(self): | |
moves_tried = set() | |
piece = self.pieces.choose_random() | |
x_position = random.randint(0, self.board.width - piece.actual_width()) | |
y_position = 0 | |
# keep backup for later | |
board_backup = deepcopy(self.board) | |
add_success = self.board.add(piece, x_position, y_position) | |
if not add_success: | |
self.game_over = True | |
return | |
while not piece.stuck: | |
self.board.show() | |
print "Move (a: left, d: right, w: rotate clockwise, s: rotate counter-clockwise): " | |
move = raw_input() | |
y_position += 1 | |
# perform_move_update modifies piece also, so keep a back up | |
piece_backup = deepcopy(piece) | |
x_position_tmp = board_backup.perform_move_update(piece, x_position, move) | |
valid = board_backup.check_result(piece, x_position_tmp, y_position) | |
while not valid: | |
self.board.show() | |
if move in self.board.valid_moves: moves_tried.add(move) | |
if len(moves_tried) == 4: | |
print "AcK, no moves left to try." | |
self.game_over = True | |
return | |
print "Move invalid, please try another option (a, d, w, s): " | |
move = raw_input() | |
piece = deepcopy(piece_backup) | |
x_position_tmp = board_backup.perform_move_update(piece, x_position, move) | |
valid = board_backup.check_result(piece, x_position_tmp, y_position) | |
# refresh the item location | |
self.board = deepcopy(board_backup) | |
x_position = x_position_tmp | |
self.board.add(piece, x_position, y_position) | |
self.board.show() | |
def main(): | |
Game().run() | |
print "Game Over!" | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment