· 4 years ago · Apr 30, 2021, 07:40 AM
1Skip to content
2Sign up
3Mekire
4/
5console-2048
675
7Code
8Issues
9Pull requests
10Actions
11Projects
12Wiki
13Security
14Insights
15console-2048/console2048_color.py /
16@Mekire
17Mekire Changed rate 4 appears from .25 to .1
18Latest commit 8995f42 on Apr 30, 2014
19 History
20 1 contributor
21234 lines (195 sloc) 7.08 KB
22
23from __future__ import print_function
24
25import os
26import sys
27import copy
28import random
29import functools
30
31import colorama
32from colorama import Back, Fore, Style
33
34#Python 2/3 compatibility.
35if sys.version_info[0] == 2:
36 range = xrange
37 input = raw_input
38
39
40def _getch_windows(prompt):
41 """
42 Windows specific version of getch. Special keys like arrows actually post
43 two key events. If you want to use these keys you can create a dictionary
44 and return the result of looking up the appropriate second key within the
45 if block.
46 """
47 print(prompt, end="")
48 key = msvcrt.getch()
49 if ord(key) == 224:
50 key = msvcrt.getch()
51 return key
52 print(key.decode())
53 return key.decode()
54
55
56def _getch_linux(prompt):
57 """Linux specific version of getch."""
58 print(prompt, end="")
59 sys.stdout.flush()
60 fd = sys.stdin.fileno()
61 old = termios.tcgetattr(fd)
62 new = termios.tcgetattr(fd)
63 new[3] = new[3] & ~termios.ICANON & ~termios.ECHO
64 new[6][termios.VMIN] = 1
65 new[6][termios.VTIME] = 0
66 termios.tcsetattr(fd, termios.TCSANOW, new)
67 char = None
68 try:
69 char = os.read(fd, 1)
70 finally:
71 termios.tcsetattr(fd, termios.TCSAFLUSH, old)
72 print(char.decode())
73 return char.decode()
74
75
76#Set version of getch to use based on operating system.
77if sys.platform[:3] == 'win':
78 import msvcrt
79 getch = _getch_windows
80else:
81 import termios
82 getch = _getch_linux
83
84
85RESET = Style.RESET_ALL
86WHITE = Fore.BLACK+Back.WHITE+Style.BRIGHT
87
88BRIGHTS = {"GREEN" : Back.GREEN+Fore.RED+Style.BRIGHT,
89 "RED" : Back.RED+Fore.GREEN+Style.BRIGHT,
90 "YELLOW" : Back.YELLOW+Fore.CYAN+Style.BRIGHT,
91 "BLUE" : Back.BLUE+Fore.YELLOW+Style.BRIGHT,
92 "MAGENTA" : Back.MAGENTA+Fore.CYAN+Style.BRIGHT,
93 "CYAN" : Back.CYAN+Fore.YELLOW+Style.BRIGHT,
94 "WHITE" : Back.WHITE+Fore.RED+Style.BRIGHT}
95
96IMPOSSIBLE = {"CYAN" : Back.CYAN+Fore.GREEN+Style.BRIGHT,
97 "RED" : Back.RED+Fore.WHITE+Style.BRIGHT,
98 "YELLOW" : Back.YELLOW+Fore.WHITE+Style.BRIGHT}
99
100COLORS = {2 : "{} 2 {}".format(Back.GREEN, RESET),
101 4 : "{} 4 {}".format(Back.RED, RESET),
102 8 : "{} 8 {}".format(Back.YELLOW, RESET),
103 16 : "{} 16 {}".format(Back.BLUE, RESET),
104 32 : "{} 32 {}".format(Back.MAGENTA, RESET),
105 64 : "{} 64 {}".format(Back.CYAN, RESET),
106 128 : "{} 128 {}".format(WHITE, RESET),
107 256 : "{} 256 {}".format(BRIGHTS["GREEN"], RESET),
108 512 : "{} 512 {}".format(BRIGHTS["RED"], RESET),
109 1024 : "{} 1024 {}".format(BRIGHTS["YELLOW"], RESET),
110 2048 : "{} 2048 {}".format(BRIGHTS["BLUE"], RESET),
111 4096 : "{} 4096 {}".format(BRIGHTS["MAGENTA"], RESET),
112 8192 : "{} 8192 {}".format(BRIGHTS["CYAN"], RESET),
113 16384 : "{}16384 {}".format(BRIGHTS["WHITE"], RESET),
114 32768 : "{}32768 {}".format(IMPOSSIBLE["CYAN"], RESET),
115 65536 : "{}65536 {}".format(IMPOSSIBLE["RED"], RESET),
116 131972 : "{}131972{}".format(IMPOSSIBLE["YELLOW"], RESET)}
117
118
119def push_row(row, left=True):
120 """Push all tiles in one row; like tiles will be merged together."""
121 row = row[:] if left else row[::-1]
122 new_row = [item for item in row if item]
123 for i in range(len(new_row)-1):
124 if new_row[i] and new_row[i] == new_row[i+1]:
125 new_row[i], new_row[i+1:] = new_row[i]*2, new_row[i+2:]+[""]
126 new_row += [""]*(len(row)-len(new_row))
127 return new_row if left else new_row[::-1]
128
129
130def get_column(grid, column_index):
131 """Return the column from the grid at column_index as a list."""
132 return [row[column_index] for row in grid]
133
134
135def set_column(grid, column_index, new):
136 """
137 Replace the values in the grid at column_index with the values in new.
138 The grid is changed inplace.
139 """
140 for i,row in enumerate(grid):
141 row[column_index] = new[i]
142
143
144def push_all_rows(grid, left=True):
145 """
146 Perform a horizontal shift on all rows.
147 Pass left=True for left and left=False for right.
148 The grid will be changed inplace.
149 """
150 for i,row in enumerate(grid):
151 grid[i] = push_row(row, left)
152
153
154def push_all_columns(grid, up=True):
155 """
156 Perform a vertical shift on all columns.
157 Pass up=True for up and up=False for down.
158 The grid will be changed inplace.
159 """
160 for i,val in enumerate(grid[0]):
161 column = get_column(grid, i)
162 new = push_row(column, up)
163 set_column(grid, i, new)
164
165
166def get_empty_cells(grid):
167 """Return a list of coordinate pairs corresponding to empty cells."""
168 empty = []
169 for j,row in enumerate(grid):
170 for i,val in enumerate(row):
171 if not val:
172 empty.append((j,i))
173 return empty
174
175
176def any_possible_moves(grid):
177 """Return True if there are any legal moves, and False otherwise."""
178 if get_empty_cells(grid):
179 return True
180 for row in grid:
181 if any(row[i]==row[i+1] for i in range(len(row)-1)):
182 return True
183 for i,val in enumerate(grid[0]):
184 column = get_column(grid, i)
185 if any(column[i]==column[i+1] for i in range(len(column)-1)):
186 return True
187 return False
188
189
190def get_start_grid(cols=4, rows=4):
191 """Create the start grid and seed it with two numbers."""
192 grid = [[""]*cols for i in range(rows)]
193 for i in range(2):
194 empties = get_empty_cells(grid)
195 y,x = random.choice(empties)
196 grid[y][x] = 2 if random.random() < 0.9 else 4
197 return grid
198
199
200def prepare_next_turn(grid):
201 """
202 Spawn a new number on the grid; then return the result of
203 any_possible_moves after this change has been made.
204 """
205 empties = get_empty_cells(grid)
206 y,x = random.choice(empties)
207 grid[y][x] = 2 if random.random() < 0.9 else 4
208 return any_possible_moves(grid)
209
210
211def print_grid(grid):
212 """Print a pretty grid to the screen."""
213 print("")
214 wall = "+------"*len(grid[0])+"+"
215 print(wall)
216 for row in grid:
217 meat = "|".join(COLORS[val] if val else " "*6 for val in row)
218 print("|{}|".format(meat))
219 print(wall)
220
221
222def main():
223 """
224 Get user input.
225 Update game state.
226 Display updates to user.
227 """
228 colorama.init()
229 functions = {"a" : functools.partial(push_all_rows, left=True),
230 "d" : functools.partial(push_all_rows, left=False),
231 "w" : functools.partial(push_all_columns, up=True),
232 "s" : functools.partial(push_all_columns, up=False)}
233 grid = get_start_grid(*map(int,sys.argv[1:]))
234 print_grid(grid)
235 while True:
236 grid_copy = copy.deepcopy(grid)
237 get_input = getch("Enter direction (w/a/s/d): ")
238 if get_input in functions:
239 functions[get_input](grid)
240 elif get_input == "q":
241 break
242 else:
243 print("\nInvalid choice.")
244 continue
245 if grid != grid_copy:
246 if not prepare_next_turn(grid):
247 print_grid(grid)
248 print("You Lose!")
249 break
250 print_grid(grid)
251 print("Thanks for playing.")
252
253
254if __name__ == "__main__":
255 main()
256© 2021 GitHub, Inc.
257Terms
258Privacy
259Security
260Status
261Docs
262Contact GitHub
263Pricing
264API
265Training
266Blog
267About
268