├── README.md ├── Makefile ├── .gitignore ├── board.h ├── 2048.c └── board.c /README.md: -------------------------------------------------------------------------------- 1 | re2048 2 | ====== 3 | 4 | Reinforcement Learning for 2048 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-g -Wall -Wextra -std=c99 -O3 2 | LDFLAGS=-lrt 3 | CC = gcc 4 | 5 | 2048: board.o 2048.c 6 | $(CC) $(CFLAGS) -o 2048 board.o $(LDFLAGS) 2048.c 7 | 8 | board.o: board.c 9 | $(CC) -c $(CFLAGS) board.c 10 | 11 | clean: 12 | rm -f board.o 2048 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Libraries 8 | *.lib 9 | *.a 10 | 11 | # Shared objects (inc. Windows DLLs) 12 | *.dll 13 | *.so 14 | *.so.* 15 | *.dylib 16 | 17 | # Executables 18 | *.exe 19 | *.out 20 | *.app 21 | *.i*86 22 | *.x86_64 23 | *.hex 24 | -------------------------------------------------------------------------------- /board.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SIZE 4 5 | 6 | #define UP 0 7 | #define DOWN 1 8 | #define LEFT 2 9 | #define RIGHT 3 10 | 11 | typedef struct board_t { 12 | int cells[SIZE][SIZE]; 13 | } board_t; 14 | 15 | board_t board_init(); 16 | void board_print(board_t); 17 | void board_move(board_t*, int); 18 | 19 | int board_move_right(board_t *board); 20 | int board_move_left(board_t *board); 21 | int board_move_up(board_t *board); 22 | int board_move_down(board_t *board); 23 | 24 | bool board_check_game_over(board_t *board); 25 | 26 | void board_fill_random(board_t *board); 27 | 28 | uint64_t board_encode(board_t board); 29 | 30 | void setBufferedInput(bool); 31 | -------------------------------------------------------------------------------- /2048.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 199309L 2 | #include 3 | #include "board.h" 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | srand(time(NULL)); 10 | 11 | time_t start; 12 | time(&start); 13 | 14 | for(int i=0; i < 1; i++) 15 | { 16 | board_t board = board_init(); 17 | 18 | board_fill_random(&board); 19 | 20 | int play = 1; 21 | while (play && !board_check_game_over(&board)) 22 | { 23 | board_print(board); 24 | 25 | int c = getchar(); 26 | //int c = rand() % 4; 27 | switch(c) 28 | { 29 | case 'h': 30 | case 68: 31 | case 0: 32 | board_move(&board, LEFT); 33 | break; 34 | case 'j': 35 | case 66: 36 | case 1: 37 | board_move(&board, DOWN); 38 | break; 39 | case 'k': 40 | case 65: 41 | case 2: 42 | board_move(&board, UP); 43 | break; 44 | case 'l': 45 | case 67: 46 | case 3: 47 | board_move(&board, RIGHT); 48 | break; 49 | default: 50 | play = 0; 51 | break; 52 | } 53 | } 54 | /*if (i % 1000 == 0)*/ 55 | /*printf("Iteration %i\n", i);*/ 56 | //printf("The game is over:\n"); 57 | //board_print(board); 58 | } 59 | 60 | time_t end; 61 | time(&end); 62 | 63 | printf("Time elapsed is %0f\n", difftime(end, start)); 64 | } 65 | -------------------------------------------------------------------------------- /board.c: -------------------------------------------------------------------------------- 1 | #include "board.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | board_t board_init() 8 | { 9 | board_t board; 10 | memset(&board, 0, sizeof board); 11 | 12 | return board; 13 | } 14 | 15 | void board_print(board_t board) 16 | { 17 | for(int i=0; i < SIZE; i++) 18 | { 19 | for(int j=0; j < SIZE; j++) 20 | { 21 | if (board.cells[i][j]) 22 | printf(" %5d ", 1 << board.cells[i][j]); 23 | else 24 | printf(" %5s ", "."); 25 | } 26 | printf("\n"); 27 | } 28 | } 29 | 30 | int slide_right(board_t *board, int row) 31 | { 32 | int count = 0; 33 | 34 | int blank = SIZE - 1; 35 | while (blank >= 0) 36 | { 37 | while(blank >= 0) 38 | { 39 | if(!board->cells[row][blank]) 40 | break; 41 | blank--; 42 | } 43 | 44 | int nonblank = blank - 1; 45 | 46 | while(nonblank >= 0) 47 | { 48 | if(board->cells[row][nonblank]) 49 | break; 50 | nonblank--; 51 | } 52 | 53 | if (blank < 0 || nonblank < 0) 54 | break; 55 | 56 | board->cells[row][blank] = board->cells[row][nonblank]; 57 | board->cells[row][nonblank] = 0; 58 | count++; 59 | 60 | blank--; 61 | nonblank--; 62 | } 63 | 64 | return count; 65 | } 66 | 67 | int slide_left(board_t *board, int row) 68 | { 69 | int count = 0; 70 | int blank = 0; 71 | while (blank < SIZE) 72 | { 73 | while(blank < SIZE) 74 | { 75 | if(!board->cells[row][blank]) 76 | break; 77 | blank++; 78 | } 79 | 80 | int nonblank = blank + 1; 81 | 82 | while(nonblank < SIZE) 83 | { 84 | if(board->cells[row][nonblank]) 85 | break; 86 | nonblank++; 87 | } 88 | 89 | if (blank >= SIZE || nonblank >= SIZE) 90 | break; 91 | 92 | board->cells[row][blank] = board->cells[row][nonblank]; 93 | board->cells[row][nonblank] = 0; 94 | 95 | count++; 96 | 97 | blank++; 98 | nonblank++; 99 | } 100 | 101 | return count; 102 | } 103 | 104 | int slide_up(board_t *board, int col) 105 | { 106 | int count = 0; 107 | int blank = 0; 108 | while (blank < SIZE) 109 | { 110 | while(blank < SIZE) 111 | { 112 | if(!board->cells[blank][col]) 113 | break; 114 | blank++; 115 | } 116 | 117 | int nonblank = blank + 1; 118 | 119 | while(nonblank < SIZE) 120 | { 121 | if(board->cells[nonblank][col]) 122 | break; 123 | nonblank++; 124 | } 125 | 126 | if (blank >= SIZE || nonblank >= SIZE) 127 | break; 128 | 129 | board->cells[blank][col] = board->cells[nonblank][col]; 130 | board->cells[nonblank][col] = 0; 131 | 132 | count++; 133 | 134 | blank++; 135 | nonblank++; 136 | } 137 | 138 | return count; 139 | } 140 | 141 | int slide_down(board_t *board, int col) 142 | { 143 | int count = 0; 144 | int blank = SIZE - 1; 145 | while (blank >= 0) 146 | { 147 | while(blank >= 0) 148 | { 149 | if(!board->cells[blank][col]) 150 | break; 151 | blank--; 152 | } 153 | 154 | int nonblank = blank - 1; 155 | 156 | while(nonblank >= 0) 157 | { 158 | if(board->cells[nonblank][col]) 159 | break; 160 | nonblank--; 161 | } 162 | 163 | if (blank < 0 || nonblank < 0) 164 | break; 165 | 166 | board->cells[blank][col] = board->cells[nonblank][col]; 167 | board->cells[nonblank][col] = 0; 168 | 169 | count++; 170 | 171 | blank--; 172 | nonblank--; 173 | } 174 | return count; 175 | } 176 | 177 | int board_move_right(board_t *board) 178 | { 179 | int count = 0; 180 | for(int row=0; row < SIZE; row++) 181 | { 182 | count += slide_right(board, row); 183 | 184 | //sums up things next to each other. 185 | for(int col=SIZE - 1; col > 0; col--) 186 | { 187 | if(board->cells[row][col]) 188 | { 189 | //we have a collision. 190 | if(board->cells[row][col - 1] == board->cells[row][col]) 191 | { 192 | board->cells[row][col] = board->cells[row][col - 1] + 1; 193 | board->cells[row][col - 1] = 0; 194 | 195 | count += 1; 196 | } 197 | } 198 | } 199 | 200 | count += slide_right(board, row); 201 | } 202 | return count; 203 | } 204 | 205 | int board_move_left(board_t *board) 206 | { 207 | int count = 0; 208 | for(int row=0; row < SIZE; row++) 209 | { 210 | count += slide_left(board, row); 211 | 212 | //sums up things next to each other. 213 | for(int col=0; col < SIZE - 1; col++) 214 | { 215 | if(board->cells[row][col]) 216 | { 217 | //we have a collision. 218 | if(board->cells[row][col] == board->cells[row][col + 1]) 219 | { 220 | board->cells[row][col] = board->cells[row][col + 1] + 1; 221 | board->cells[row][col + 1] = 0; 222 | 223 | count += 1; 224 | } 225 | } 226 | } 227 | 228 | count += slide_left(board, row); 229 | } 230 | return count; 231 | } 232 | 233 | int board_move_up(board_t *board) 234 | { 235 | int count = 0; 236 | for(int col=0; col < SIZE; col++) 237 | { 238 | count += slide_up(board, col); 239 | 240 | //sums up things next to each other. 241 | for(int row=0; row < SIZE - 1; row++) 242 | { 243 | if(board->cells[row][col]) 244 | { 245 | //we have a collision. 246 | if(board->cells[row][col] == board->cells[row + 1][col]) 247 | { 248 | board->cells[row + 1][col] = board->cells[row][col] + 1; 249 | board->cells[row][col] = 0; 250 | 251 | count += 1; 252 | } 253 | } 254 | } 255 | 256 | count += slide_up(board, col); 257 | } 258 | return count; 259 | } 260 | 261 | void board_fill_random(board_t *board) 262 | { 263 | int blank_cells = 0; 264 | for (int row=0; row < SIZE; row++) 265 | { 266 | for(int col=0; col < SIZE; col++) 267 | { 268 | if(!board->cells[row][col]) 269 | blank_cells++; 270 | } 271 | } 272 | 273 | int random = rand() % blank_cells; 274 | 275 | for (int row=0; row < SIZE; row++) 276 | { 277 | for(int col=0; col < SIZE; col++) 278 | { 279 | if(!board->cells[row][col]) 280 | { 281 | if(random-- == 0) 282 | { 283 | int dice = rand() % 10; 284 | 285 | if (dice == 9) 286 | board->cells[row][col] = 2; 287 | else 288 | board->cells[row][col] = 1; 289 | return; 290 | } 291 | } 292 | } 293 | } 294 | } 295 | 296 | int board_move_down(board_t *board) 297 | { 298 | int count = 0; 299 | for(int col=0; col < SIZE; col++) 300 | { 301 | count += slide_down(board, col); 302 | 303 | //sums up things next to each other. 304 | for(int row=SIZE - 1; row > 0; row--) 305 | { 306 | if(board->cells[row][col]) 307 | { 308 | //we have a collision. 309 | if(board->cells[row][col] == board->cells[row - 1][col]) 310 | { 311 | board->cells[row - 1][col] = board->cells[row][col] + 1; 312 | board->cells[row][col] = 0; 313 | 314 | count += 1; 315 | } 316 | } 317 | } 318 | 319 | count += slide_down(board, col); 320 | } 321 | 322 | return count; 323 | } 324 | 325 | void board_move(board_t *board, int move) 326 | { 327 | int count = 0; 328 | if (move == RIGHT) 329 | { 330 | count = board_move_right(board); 331 | } 332 | else if (move == LEFT) 333 | { 334 | count = board_move_left(board); 335 | } 336 | else if (move == UP) 337 | { 338 | count = board_move_up(board); 339 | } 340 | else if (move == DOWN) 341 | { 342 | count = board_move_down(board); 343 | } 344 | 345 | if (count > 0) 346 | board_fill_random(board); 347 | } 348 | 349 | uint64_t board_encode(board_t board) 350 | { 351 | uint64_t result = 0; 352 | for (int row=0; row < SIZE; row++) 353 | { 354 | for (int col=0; col < SIZE; col+=2) 355 | { 356 | int first = board.cells[row][col]; 357 | int second = board.cells[row][col + 1]; 358 | 359 | char byte = (char) (((first << 28) >> 24) | ((second << 28) >> 28)); 360 | 361 | result = result << 8; 362 | result = result + byte; 363 | } 364 | } 365 | 366 | return result; 367 | } 368 | 369 | void board_draw(board_t *board) 370 | { 371 | printf("\033[H"); 372 | 373 | for (int row=0; row < SIZE; row++) 374 | { 375 | for (int col=0; col < SIZE; col++) 376 | { 377 | printf("%d", board->cells[row][col]); 378 | } 379 | } 380 | } 381 | 382 | bool board_check_game_over(board_t *board) 383 | { 384 | //check for horizontal moves. 385 | for(int row=0; row < SIZE; row++) 386 | { 387 | for(int col=0; col < SIZE - 1; col++) 388 | { 389 | if(board->cells[row][col] == board->cells[row][col + 1]) 390 | return false; 391 | } 392 | } 393 | 394 | for(int col=0; col < SIZE; col++) 395 | { 396 | for(int row=0; row < SIZE - 1; row++) 397 | { 398 | if(board->cells[row][col] == board->cells[row + 1][col]) 399 | return false; 400 | } 401 | } 402 | 403 | for(int row=0; row < SIZE; row++) 404 | { 405 | for(int col=0; col < SIZE; col++) 406 | { 407 | if(!board->cells[row][col]) 408 | return false; 409 | } 410 | } 411 | 412 | return true; 413 | } 414 | --------------------------------------------------------------------------------