Last active
August 29, 2015 13:58
-
-
Save legendmohe/9951027 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
#!/usr/bin/env python | |
# encoding: utf-8 | |
import random | |
import sys | |
class GameState: | |
NORMAL = 0 | |
WIN = 1 | |
LOSE = 2 | |
class SwapDir: | |
LEFT = 0 | |
UP = 1 | |
RIGHT = 2 | |
DOWN = 3 | |
class GameBoard: | |
def __init__(self, n): | |
self.length = n | |
self.board = [0 for i in range(n*n)] | |
self.num_of_empty = n*n | |
self.max_value = 2 | |
self.total_score = 0 | |
def get(self, x, y): | |
if x < 0 or y < 0 or x >= self.length or y >= self.length: | |
return -1 | |
return self.board[x*self.length + y] | |
def set(self, x, y, value): | |
if x < 0 or y < 0 or x >= self.length or y >= self.length: | |
return False | |
self.board[x*self.length + y] = value | |
def copy(self): | |
new_board = GameBoard(0) | |
new_board.length = self.length | |
new_board.num_of_empty = self.num_of_empty | |
new_board.max_value = self.max_value | |
new_board.total_score = self.total_score | |
new_board.board = self.board[:] | |
return new_board | |
def __len__(self): | |
return self.length | |
def set_random_number(board): | |
# 在空格处放置随机值 | |
n = len(board) | |
while not board.num_of_empty == 0: | |
x = random.randint(0, n - 1) | |
y = random.randint(0, n - 1) | |
if board.get(x, y) == 0: | |
value = random.uniform(0, 1) | |
if value < 0.05: # 简化一下 | |
value = 4 | |
else: | |
value = 2 | |
board.set(x, y, value) | |
board.num_of_empty -= 1 | |
return True | |
return False | |
def combinable(board): | |
# 从左上角开始,检查左边和下边是否存在可合并的单元格 | |
for i in range(len(board)): | |
for j in range(len(board)): | |
value = board.get(i, j) | |
if value == 0: | |
return True | |
if value == board.get(i, j + 1): | |
return True | |
if value == board.get(i + 1, j): | |
return True | |
return False | |
def apply_swap(board, swap_dir): | |
# 统一成swap left | |
def xset_cur(i, j, value): | |
board.set(i, j, value) | |
def yset_cur(i, j, value): | |
board.set(j, i, value) | |
def xget_cur(i, j): | |
return board.get(i, j) | |
def yget_cur(i, j): | |
return board.get(j, i) | |
col_indexs = range(len(board)) | |
if swap_dir == SwapDir.LEFT: | |
get_cur = xget_cur | |
set_cur = xset_cur | |
delta = 1 | |
elif swap_dir == SwapDir.RIGHT: | |
get_cur = xget_cur | |
set_cur = xset_cur | |
delta = -1 | |
col_indexs = col_indexs[::-1] | |
elif swap_dir == SwapDir.UP: | |
get_cur = yget_cur | |
set_cur = yset_cur | |
delta = 1 | |
elif swap_dir == SwapDir.DOWN: | |
get_cur = yget_cur | |
set_cur = yset_cur | |
delta = -1 | |
col_indexs = col_indexs[::-1] | |
else: | |
return 0, False | |
score = 0 | |
moved = False | |
for i in range(len(board)): | |
for j in col_indexs: | |
if get_cur(i, j) == 0: | |
continue | |
k = j + delta | |
while get_cur(i, k) == 0: | |
k += delta | |
if get_cur(i, j) == get_cur(i, k): | |
set_cur(i, j, get_cur(i, j)*2) | |
set_cur(i, k, 0) | |
if get_cur(i, j) > board.max_value: | |
board.max_value = get_cur(i, j) | |
score += get_cur(i, j) | |
board.num_of_empty += 1 | |
moved = True | |
# print "get score:", get_cur(i, j) | |
k = j | |
while get_cur(i, k - delta) == 0: | |
k -= delta | |
if not k == j: | |
set_cur(i, k, get_cur(i, j)) | |
set_cur(i, j, 0) | |
moved = True | |
# print "move", i, j, "to", i, k | |
board.total_score += score | |
return score, moved | |
def init_game(n): | |
# 初始化游戏 | |
board = GameBoard(n) | |
set_random_number(board) | |
return board, GameState.NORMAL | |
def print_game(board): | |
n = len(board) | |
sys.stdout.write(" " + "----"*n + " \n") | |
for i in range(n): | |
sys.stdout.write(" ") | |
for j in range(n): | |
value = board.get(i, j) | |
if value == 0: | |
value = " " | |
sys.stdout.write(str(value).rjust(3) + "|") | |
sys.stdout.write(" \n") | |
sys.stdout.write(" " + "----"*n + " \n") | |
sys.stdout.flush() | |
def get_swap_dir(board): | |
# return random.randint(1, 4) # 测试用 | |
swap_dir = raw_input("your turn:") | |
if swap_dir == 'w': | |
return SwapDir.UP | |
elif swap_dir == 's': | |
return SwapDir.DOWN | |
elif swap_dir == 'a': | |
return SwapDir.LEFT | |
elif swap_dir == 'd': | |
return SwapDir.RIGHT | |
else: | |
return None | |
def play(n, target, swap_func, debug=False): | |
board, state = init_game(n) | |
set_random_number(board) | |
if debug: | |
print_game(board) | |
while state == GameState.NORMAL: | |
if board.max_value >= target: | |
state = GameState.WIN | |
break | |
elif board.num_of_empty == 0 and not combinable(board): | |
state = GameState.LOSE | |
break | |
swap_dir = swap_func(board) | |
cur_score, moved = apply_swap(board, swap_dir) | |
if moved: | |
if debug: | |
print "score:", board.total_score | |
print_game(board) | |
set_random_number(board) | |
return state | |
if __name__ == '__main__': | |
state = play(4, 1024, get_swap_dir, debug=True) | |
if state == GameState.WIN: | |
print "You Win!" | |
else: | |
print "You Lose!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment