Amazing-Python-Scripts

Форк
0
244 строки · 7.9 Кб
1
import random
2
import copy
3

4

5
class AI2048:
6
    def __init__(self, board):
7
        self.board = board
8

9
    def get_empty_cells(self):
10
        empty_cells = []
11
        for i in range(len(self.board)):
12
            for j in range(len(self.board[i])):
13
                if self.board[i][j] == 0:
14
                    empty_cells.append((i, j))
15
        return empty_cells
16

17
    def get_max_tile(self):
18
        return max(map(max, self.board))
19

20
    def move_left(self):
21
        merged = []
22
        for row in self.board:
23
            new_row = [tile for tile in row if tile != 0]
24
            for i in range(len(new_row) - 1):
25
                if new_row[i] == new_row[i + 1]:
26
                    new_row[i] *= 2
27
                    new_row[i + 1] = 0
28
                    merged.append(new_row[i])
29
            new_row = [tile for tile in new_row if tile != 0]
30
            new_row.extend([0] * (len(row) - len(new_row)))
31
            self.board[self.board.index(row)] = new_row
32
        return merged
33

34
    def move_right(self):
35
        self.flip_board()
36
        merged = self.move_left()
37
        self.flip_board()
38
        return merged
39

40
    def move_up(self):
41
        self.transpose_board()
42
        merged = self.move_left()
43
        self.transpose_board()
44
        return merged
45

46
    def move_down(self):
47
        self.transpose_board()
48
        merged = self.move_right()
49
        self.transpose_board()
50
        return merged
51

52
    def get_score(self):
53
        return sum(map(sum, self.board))
54

55
    def get_heuristic_score(self):
56
        max_tile = self.get_max_tile()
57
        empty_cells = len(self.get_empty_cells())
58
        smoothness = self.calculate_smoothness()
59
        monotonicity = self.calculate_monotonicity()
60

61
        # Weighted sum of different heuristics
62
        return 0.1 * self.get_score() + 2.7 * empty_cells + 1.0 * smoothness + 1.5 * monotonicity + 3.0 * max_tile
63

64
    def calculate_smoothness(self):
65
        smoothness = 0
66
        for i in range(len(self.board)):
67
            for j in range(len(self.board[i])):
68
                if self.board[i][j] != 0:
69
                    value = math.log2(self.board[i][j])
70
                    for (dx, dy) in [(-1, 0), (0, -1), (1, 0), (0, 1)]:
71
                        x, y = i + dx, j + dy
72
                        if 0 <= x < len(self.board) and 0 <= y < len(self.board[i]) and self.board[x][y] != 0:
73
                            neighbor_value = math.log2(self.board[x][y])
74
                            smoothness -= abs(value - neighbor_value)
75
        return smoothness
76

77
    def calculate_monotonicity(self):
78
        monotonicity = [0, 0, 0, 0]
79
        for i in range(len(self.board)):
80
            current = 0
81
            next = current + 1
82
            while next < 4:
83
                while next < 4 and self.board[i][next] == 0:
84
                    next += 1
85
                if next >= 4:
86
                    next -= 1
87
                current_value = 0 if self.board[i][current] == 0 else math.log2(
88
                    self.board[i][current])
89
                next_value = 0 if self.board[i][next] == 0 else math.log2(
90
                    self.board[i][next])
91
                if current_value > next_value:
92
                    monotonicity[0] += next_value - current_value
93
                elif next_value > current_value:
94
                    monotonicity[1] += current_value - next_value
95
                current = next
96
                next += 1
97

98
        for j in range(len(self.board[0])):
99
            current = 0
100
            next = current + 1
101
            while next < 4:
102
                while next < 4 and self.board[next][j] == 0:
103
                    next += 1
104
                if next >= 4:
105
                    next -= 1
106
                current_value = 0 if self.board[current][j] == 0 else math.log2(
107
                    self.board[current][j])
108
                next_value = 0 if self.board[next][j] == 0 else math.log2(
109
                    self.board[next][j])
110
                if current_value > next_value:
111
                    monotonicity[2] += next_value - current_value
112
                elif next_value > current_value:
113
                    monotonicity[3] += current_value - next_value
114
                current = next
115
                next += 1
116

117
        return max(monotonicity)
118

119
    def get_children_states(self):
120
        children = []
121
        for move in ['left', 'right', 'up', 'down']:
122
            new_board = copy.deepcopy(self.board)
123
            merged = self.move(new_board, move)
124
            if merged:
125
                children.append((new_board, merged))
126
        return children
127

128
    def get_best_move(self, depth=3):
129
        moves = ['left', 'right', 'up', 'down']
130
        best_score = float('-inf')
131
        best_move = random.choice(moves)
132
        for move in moves:
133
            new_board = copy.deepcopy(self.board)
134
            merged = self.move(new_board, move)
135
            if merged:
136
                child = AI2048(new_board)
137
                score = self.expectimax(child, depth - 1, False)
138
                if score > best_score:
139
                    best_score = score
140
                    best_move = move
141
        return best_move
142

143
    def expectimax(self, node, depth, is_maximizing):
144
        if depth == 0:
145
            return node.get_heuristic_score()
146

147
        if is_maximizing:
148
            max_eval = float('-inf')
149
            children = node.get_children_states()
150
            for child_board, merged in children:
151
                child = AI2048(child_board)
152
                eval = self.expectimax(child, depth - 1, False)
153
                max_eval = max(max_eval, eval)
154
            return max_eval
155
        else:
156
            total_score = 0
157
            empty_cells = node.get_empty_cells()
158
            for cell in empty_cells:
159
                child_board = copy.deepcopy(node.board)
160
                child_board[cell[0]][cell[1]] = 2
161
                child = AI2048(child_board)
162
                eval = self.expectimax(child, depth - 1, True)
163
                total_score += eval
164
            return total_score / len(empty_cells)
165

166
    def move(self, board, direction):
167
        merged = []
168
        if direction == 'left':
169
            merged = self.move_left(board)
170
        elif direction == 'right':
171
            merged = self.move_right(board)
172
        elif direction == 'up':
173
            merged = self.move_up(board)
174
        elif direction == 'down':
175
            merged = self.move_down(board)
176
        return merged
177

178
    def move_left(self, board):
179
        merged = []
180
        for row in board:
181
            new_row = [tile for tile in row if tile != 0]
182
            for i in range(len(new_row) - 1):
183
                if new_row[i] == new_row[i + 1]:
184
                    new_row[i] *= 2
185
                    new_row[i + 1] = 0
186
                    merged.append(new_row[i])
187
            new_row = [tile for tile in new_row if tile != 0]
188
            new_row.extend([0] * (len(row) - len(new_row)))
189
            board[board.index(row)] = new_row
190
        return merged
191

192
    def move_right(self, board):
193
        self.flip_board(board)
194
        merged = self.move_left(board)
195
        self.flip_board(board)
196
        return merged
197

198
    def move_up(self, board):
199
        self.transpose_board(board)
200
        merged = self.move_left(board)
201
        self.transpose_board(board)
202
        return merged
203

204
    def move_down(self, board):
205
        self.transpose_board(board)
206
        merged = self.move_right(board)
207
        self.transpose_board(board)
208
        return merged
209

210
    def flip_board(self, board):
211
        for row in board:
212
            row.reverse()
213

214
    def transpose_board(self, board):
215
        board[:] = [list(i) for i in zip(*board)]
216

217

218
def print_board(board):
219
    for row in board:
220
        print(row)
221
    print()
222

223

224
if __name__ == "__main__":
225
    board = [
226
        [0, 2, 2, 4],
227
        [0, 2, 0, 4],
228
        [0, 4, 2, 0],
229
        [0, 0, 2, 2]
230
    ]
231

232
    ai = AI2048(board)
233
    print("Initial Board:")
234
    print_board(ai.board)
235

236
    while True:
237
        if ai.get_empty_cells():
238
            move = ai.get_best_move()
239
            print(f"Moving {move}")
240
            ai.move(move)
241
            print_board(ai.board)
242
        else:
243
            print("No more moves possible.")
244
            break
245

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.