Amazing-Python-Scripts
244 строки · 7.9 Кб
1import random2import copy3
4
5class AI2048:6def __init__(self, board):7self.board = board8
9def get_empty_cells(self):10empty_cells = []11for i in range(len(self.board)):12for j in range(len(self.board[i])):13if self.board[i][j] == 0:14empty_cells.append((i, j))15return empty_cells16
17def get_max_tile(self):18return max(map(max, self.board))19
20def move_left(self):21merged = []22for row in self.board:23new_row = [tile for tile in row if tile != 0]24for i in range(len(new_row) - 1):25if new_row[i] == new_row[i + 1]:26new_row[i] *= 227new_row[i + 1] = 028merged.append(new_row[i])29new_row = [tile for tile in new_row if tile != 0]30new_row.extend([0] * (len(row) - len(new_row)))31self.board[self.board.index(row)] = new_row32return merged33
34def move_right(self):35self.flip_board()36merged = self.move_left()37self.flip_board()38return merged39
40def move_up(self):41self.transpose_board()42merged = self.move_left()43self.transpose_board()44return merged45
46def move_down(self):47self.transpose_board()48merged = self.move_right()49self.transpose_board()50return merged51
52def get_score(self):53return sum(map(sum, self.board))54
55def get_heuristic_score(self):56max_tile = self.get_max_tile()57empty_cells = len(self.get_empty_cells())58smoothness = self.calculate_smoothness()59monotonicity = self.calculate_monotonicity()60
61# Weighted sum of different heuristics62return 0.1 * self.get_score() + 2.7 * empty_cells + 1.0 * smoothness + 1.5 * monotonicity + 3.0 * max_tile63
64def calculate_smoothness(self):65smoothness = 066for i in range(len(self.board)):67for j in range(len(self.board[i])):68if self.board[i][j] != 0:69value = math.log2(self.board[i][j])70for (dx, dy) in [(-1, 0), (0, -1), (1, 0), (0, 1)]:71x, y = i + dx, j + dy72if 0 <= x < len(self.board) and 0 <= y < len(self.board[i]) and self.board[x][y] != 0:73neighbor_value = math.log2(self.board[x][y])74smoothness -= abs(value - neighbor_value)75return smoothness76
77def calculate_monotonicity(self):78monotonicity = [0, 0, 0, 0]79for i in range(len(self.board)):80current = 081next = current + 182while next < 4:83while next < 4 and self.board[i][next] == 0:84next += 185if next >= 4:86next -= 187current_value = 0 if self.board[i][current] == 0 else math.log2(88self.board[i][current])89next_value = 0 if self.board[i][next] == 0 else math.log2(90self.board[i][next])91if current_value > next_value:92monotonicity[0] += next_value - current_value93elif next_value > current_value:94monotonicity[1] += current_value - next_value95current = next96next += 197
98for j in range(len(self.board[0])):99current = 0100next = current + 1101while next < 4:102while next < 4 and self.board[next][j] == 0:103next += 1104if next >= 4:105next -= 1106current_value = 0 if self.board[current][j] == 0 else math.log2(107self.board[current][j])108next_value = 0 if self.board[next][j] == 0 else math.log2(109self.board[next][j])110if current_value > next_value:111monotonicity[2] += next_value - current_value112elif next_value > current_value:113monotonicity[3] += current_value - next_value114current = next115next += 1116
117return max(monotonicity)118
119def get_children_states(self):120children = []121for move in ['left', 'right', 'up', 'down']:122new_board = copy.deepcopy(self.board)123merged = self.move(new_board, move)124if merged:125children.append((new_board, merged))126return children127
128def get_best_move(self, depth=3):129moves = ['left', 'right', 'up', 'down']130best_score = float('-inf')131best_move = random.choice(moves)132for move in moves:133new_board = copy.deepcopy(self.board)134merged = self.move(new_board, move)135if merged:136child = AI2048(new_board)137score = self.expectimax(child, depth - 1, False)138if score > best_score:139best_score = score140best_move = move141return best_move142
143def expectimax(self, node, depth, is_maximizing):144if depth == 0:145return node.get_heuristic_score()146
147if is_maximizing:148max_eval = float('-inf')149children = node.get_children_states()150for child_board, merged in children:151child = AI2048(child_board)152eval = self.expectimax(child, depth - 1, False)153max_eval = max(max_eval, eval)154return max_eval155else:156total_score = 0157empty_cells = node.get_empty_cells()158for cell in empty_cells:159child_board = copy.deepcopy(node.board)160child_board[cell[0]][cell[1]] = 2161child = AI2048(child_board)162eval = self.expectimax(child, depth - 1, True)163total_score += eval164return total_score / len(empty_cells)165
166def move(self, board, direction):167merged = []168if direction == 'left':169merged = self.move_left(board)170elif direction == 'right':171merged = self.move_right(board)172elif direction == 'up':173merged = self.move_up(board)174elif direction == 'down':175merged = self.move_down(board)176return merged177
178def move_left(self, board):179merged = []180for row in board:181new_row = [tile for tile in row if tile != 0]182for i in range(len(new_row) - 1):183if new_row[i] == new_row[i + 1]:184new_row[i] *= 2185new_row[i + 1] = 0186merged.append(new_row[i])187new_row = [tile for tile in new_row if tile != 0]188new_row.extend([0] * (len(row) - len(new_row)))189board[board.index(row)] = new_row190return merged191
192def move_right(self, board):193self.flip_board(board)194merged = self.move_left(board)195self.flip_board(board)196return merged197
198def move_up(self, board):199self.transpose_board(board)200merged = self.move_left(board)201self.transpose_board(board)202return merged203
204def move_down(self, board):205self.transpose_board(board)206merged = self.move_right(board)207self.transpose_board(board)208return merged209
210def flip_board(self, board):211for row in board:212row.reverse()213
214def transpose_board(self, board):215board[:] = [list(i) for i in zip(*board)]216
217
218def print_board(board):219for row in board:220print(row)221print()222
223
224if __name__ == "__main__":225board = [226[0, 2, 2, 4],227[0, 2, 0, 4],228[0, 4, 2, 0],229[0, 0, 2, 2]230]231
232ai = AI2048(board)233print("Initial Board:")234print_board(ai.board)235
236while True:237if ai.get_empty_cells():238move = ai.get_best_move()239print(f"Moving {move}")240ai.move(move)241print_board(ai.board)242else:243print("No more moves possible.")244break245