Wrote this up when I could have been doing something more productive.It is just an implementation of 2048 that runs in the terminal.Annoying wasd controls that must be confirmed with enter.I'm sure I overcomplicated things but I doubt I will dedicate much more time to it.

Try non-standard grids by passing command line arguments (if none are passed you get default 4x4).

def _getch_windows(prompt):""" Windows specific version of getch. Special keys like arrows actually post two key events. If you want to use these keys you can create a dictionary and return the result of looking up the appropriate second key within the if block. """ print(prompt, end="") key = msvcrt.getch() if ord(key)== 224: key = msvcrt.getch() return key print(key) return key

def push_row(row, left=True):"""Push all tiles in one row; like tiles will be merged together.""" row = row[:] if left else row[::-1] new_row =[item for item in row if item] for i in range(len(new_row)-1): if new_row[i] and new_row[i]== new_row[i+1]: new_row[i], new_row[i+1:]= new_row[i]*2, new_row[i+2:]+[""] new_row +=[""]*(len(row)-len(new_row)) return new_row if left else new_row[::-1]

def get_column(grid, column_index):"""Return the column from the grid at column_index as a list.""" return [row[column_index] for row in grid]

def set_column(grid, column_index, new):""" Replace the values in the grid at column_index with the values in new. The grid is changed inplace. """ for i,row in enumerate(grid): row[column_index]= new[i]

def push_all_rows(grid, left=True):""" Perform a horizontal shift on all rows. Pass left=True for left and left=False for right. The grid will be changed inplace. """ for i,row in enumerate(grid): grid[i]= push_row(row, left)

def push_all_columns(grid, up=True):""" Perform a vertical shift on all columns. Pass up=True for up and up=False for down. The grid will be changed inplace. """ for i,val in enumerate(grid[0]): column = get_column(grid, i) new = push_row(column, up) set_column(grid, i, new)

def get_empty_cells(grid):"""Return a list of coordinate pairs corresponding to empty cells.""" empty =[] for j,row in enumerate(grid): for i,val in enumerate(row): if not val: empty.append((j,i)) return empty

def any_possible_moves(grid):"""Return True if there are any legal moves, and False otherwise.""" if get_empty_cells(grid): return True for row in grid: if any(row[i]==row[i+1] for i in range(len(row)-1)): return True for i,val in enumerate(grid[0]): column = get_column(grid, i) if any(column[i]==column[i+1] for i in range(len(column)-1)): return True return False

def get_start_grid(cols=4, rows=4):"""Create the start grid and seed it with two numbers.""" grid =[[""]*cols for i in range(rows)] for i in range(2): empties = get_empty_cells(grid) y,x = random.choice(empties) grid[y][x]= random.choice((2,2,2,4)) return grid

def prepare_next_turn(grid):""" Spawn a new number on the grid; then return the result of any_possible_moves after this change has been made. """ empties = get_empty_cells(grid) y,x = random.choice(empties) grid[y][x]= random.choice((2,2,2,4)) return any_possible_moves(grid)

Merged.Pretty amazed you haven't heard of it.Rules are really basic. Tiles slide in the direction pressed and if two of the same numbers run in to each other they combine. Every turn a 2, or by a slightly lower chance a 4, will spawn in an empty cell. Game is over when there are no legal moves.

Made a couple minor changes. The windows getch would crash if it got a special key (like an arrow key) because they post two events as one.Seems to be working quite nicely on both my OS now.Now to completely over do it with ansi color codes. :p