]> git.lizzy.rs Git - ttfe.git/commitdiff
initial commit
authorpowergold1 <lstaut@hotmail.de>
Mon, 19 Sep 2016 00:50:27 +0000 (02:50 +0200)
committerpowergold1 <lstaut@hotmail.de>
Mon, 19 Sep 2016 00:50:27 +0000 (02:50 +0200)
README [new file with mode: 0644]
main.c [new file with mode: 0644]
main.h [new file with mode: 0644]

diff --git a/README b/README
new file mode 100644 (file)
index 0000000..a50c5f1
--- /dev/null
+++ b/README
@@ -0,0 +1,4 @@
+My own toy implementation of 2048 on the command line.
+
+It supports hjkl for movements and q for quit.
+
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..b72a531
--- /dev/null
+++ b/main.c
@@ -0,0 +1,554 @@
+#include "main.h"
+
+#define DBG 0
+
+bool move_possible_north(board *b);
+bool move_possible_south(board *b);
+bool move_possible_east(board *b);
+bool move_possible_west(board *b);
+
+void move_north(board *b);
+void move_south(board *b);
+void move_east(board *b);
+void move_west(board *b);
+void merge(board *b, const int d);
+void merge_north(board *b);
+void merge_south(board *b);
+void merge_east(board *b);
+void merge_west(board *b);
+
+void place_new_piece(board *b);
+void game_loop(board *b);
+
+board* new_board() {
+       board *tmp = malloc(sizeof(board));
+       init_board(tmp);
+       return tmp;
+}
+
+void init_board(board *b) {
+       for(int i = 0; i < 4; ++i) {
+               for(int j = 0; j < 4; ++j)
+                       b->x[i][j] = 0;
+       }
+       b->points = 0;
+       b->num_p = 0;
+       srand((uint)time(NULL));
+       place_new_piece(b);
+       // second piece will be placed in game_loop
+}
+
+void game_start() {
+       board *b = new_board();
+       game_loop(b);
+       print_score(b);
+       free_board(b);
+}
+
+void game_loop(board *b) {
+       char c[16];
+       int d;
+       bool r = true;
+       while(move_possible_any(b)) {
+               place_new_piece(b);
+               print_board(b);
+               INPUT:
+               printf("Make a move:\n");
+               fgets(c, sizeof(c), stdin);
+               switch(c[0]) {
+                       case 'h':
+                               d = west;
+                               break;
+                       case 'j':
+                               d = south;
+                               break;
+                       case 'k':
+                               d = north;
+                               break;
+                       case 'l':
+                               d = east;
+                               break;
+                       case 'q':
+                               r = false;
+                               break;
+                       default:
+                               printf("Invalid move: %c\n", c[0]);
+                               goto INPUT;
+               }
+               if(!r)
+                       return;
+               if(!move_possible(b, d)) {
+                       printf("Move not possible: %c\n", c[0]);
+                       goto INPUT;
+               }
+               make_move(b, d);
+       }
+}
+
+void place_new_piece(board *b) {
+       int prob = rand() % 100;
+       int possibs[32];
+       uint val = 0;
+       int cnt = 0;
+       int pair = 0;
+       int rx = 0, ry = 0;
+       for(int i = 0; i < 4; ++i) {
+               for(int j = 0; j < 4; ++j) {
+                       if(b->x[i][j] == 0) {
+                               possibs[2*cnt] = i;
+                               possibs[2*cnt+1] = j;
+                               cnt++;
+                       }
+               }
+       }
+       assert(cnt > 0);
+       pair = rand() % cnt;
+       rx = possibs[2*pair];
+       ry = possibs[2*pair+1];
+       assert(b->x[rx][ry] == 0);
+       if(prob > 9)
+               val = 2;
+       else
+               val = 4;
+       b->x[rx][ry] = val;
+       b->num_p++;
+}
+
+void free_board(board *b) {
+       free(b);
+}
+
+void make_move(board *b, const int d) {
+       bool ok = (d == south) ||
+               (d == east) ||
+               (d == north) ||
+               (d == west);
+       assert(ok);
+       /*
+        * checked before already
+        * if(!move_possible(b, d))
+        *      return;
+       */
+       move(b, d);
+       merge(b, d);
+       move(b, d);
+}
+
+bool move_possible_any(board *b) {
+       if(b->num_p < 16)
+               return true;
+       if(move_possible_south(b))
+               return true;
+       if(move_possible_east(b))
+               return true;
+       if(move_possible_north(b))
+               return true;
+       if(move_possible_west(b))
+               return true;
+       return false;
+}
+
+bool move_possible(board *b, const int d) {
+       bool ok = (d == south) ||
+               (d == east) ||
+               (d == north) ||
+               (d == west);
+       assert(ok);
+       switch(d) {
+               case north:
+                       return move_possible_north(b);
+               case south:
+                       return move_possible_south(b);
+               case east:
+                       return move_possible_east(b);
+               case west:
+                       return move_possible_west(b);
+               default: // will never execute anyway
+                       return false;
+       }
+}
+
+void move(board *b, const int d) {
+       bool ok = (d == south) ||
+               (d == east) ||
+               (d == north) ||
+               (d == west);
+       assert(ok);
+       switch(d) {
+               case north:
+                       move_north(b);
+                       break;
+               case south:
+                       move_south(b);
+                       break;
+               case east:
+                        move_east(b);
+                       break;
+               case west:
+                       move_west(b);
+                       break;
+               default: // will never execute anyway
+                       return;
+       }
+}
+
+void merge(board *b, const int d) {
+       bool ok = (d == south) ||
+               (d == east) ||
+               (d == north) ||
+               (d == west);
+       assert(ok);
+       switch(d) {
+               case north:
+                       merge_north(b);
+                       break;
+               case south:
+                       merge_south(b);
+                       break;
+               case east:
+                       merge_east(b);
+                       break;
+               case west:
+                       merge_west(b);
+                       break;
+               default: // will never execute anyway
+                       return;
+       }
+}
+
+bool move_possible_south(board *b) {
+       for(int i = 0; i < 4; ++i) {
+               for(int j = 0; j < 3; ++j) {
+                       if(b->x[i][j] != 0) {
+                               if(b->x[i][j+1] == 0)
+                                       return true;
+                               if(b->x[i][j] == b->x[i][j+1])
+                                       return true;
+                       }
+               }
+       }
+       return false;
+}
+
+bool move_possible_north(board *b) {
+       for(int i = 0; i < 4; ++i) {
+               for(int j = 1; j < 4; ++j) {
+                       if(b->x[i][j] != 0) {
+                               if(b->x[i][j-1] == 0)
+                                       return true;
+                               if(b->x[i][j] == b->x[i][j-1])
+                                       return true;
+                       }
+               }
+       }
+       return false;
+}
+
+bool move_possible_east(board *b) {
+       for(int i = 0; i < 3; ++i) {
+               for(int j = 0; j < 4; ++j) {
+                       if(b->x[i][j] != 0) {
+                               if(b->x[i+1][j] == 0)
+                                       return true;
+                               if(b->x[i+1][j] == b->x[i][j])
+                                       return true;
+                       }
+               }
+       }
+       return false;
+}
+
+bool move_possible_west(board *b) {
+       for(int i = 1; i < 4; ++i) {
+               for(int j = 0; j < 4; ++j) {
+                       if(b->x[i][j] != 0) {
+                               if(b->x[i-1][j] == 0)
+                                       return true;
+                               if(b->x[i-1][j] == b->x[i][j])
+                                       return true;
+                       }
+               }
+       }
+       return false;
+}
+
+void move_north(board *b) {
+       int k;
+       for(int i = 0; i < 4; ++i) {
+               for(int j = 1; j < 4; ++j) {
+                       if(b->x[i][j] != 0) {
+                               k = j;
+                               while(b->x[i][k-1] == 0) {
+                                       b->x[i][k-1] = b->x[i][k];
+                                       b->x[i][k] = 0;
+                                       k--;
+                                       if(k < 1)
+                                               break;
+                               }
+                       }
+               }
+       }
+}
+
+void move_south(board *b) {
+       int k;
+       for(int i = 0; i < 4; ++i) {
+               for(int j = 2; j >= 0; --j) {
+                       if(b->x[i][j] != 0) {
+                               k = j;
+                               while(b->x[i][k+1] == 0) {
+                                       b->x[i][k+1] = b->x[i][k];
+                                       b->x[i][k] = 0;
+                                       k++;
+                                       if(k > 2)
+                                               break;
+                               }
+                       }
+               }
+       }
+}
+
+void move_east(board *b) {
+       int k;
+       for(int i = 2; i >= 0; --i) {
+               for(int j = 0; j < 4; ++j) {
+                       if(b->x[i][j] != 0) {
+                               k = i;
+                               while(b->x[k+1][j] == 0) {
+                                       b->x[k+1][j] = b->x[k][j];
+                                       b->x[k][j] = 0;
+                                       k++;
+                                       if(k > 2)
+                                               break;
+                               }
+                       }
+               }
+       }
+}
+
+void move_west(board *b) {
+       int k;
+       for(int i = 1; i < 4; ++i) {
+               for(int j = 0; j < 4; ++j) {
+                       if(b->x[i][j] != 0) {
+                               k = i;
+                               while(b->x[k-1][j] == 0) {
+                                       b->x[k-1][j] = b->x[k][j];
+                                       b->x[k][j] = 0;
+                                       k--;
+                                       if(k < 1)
+                                               break;
+                               }
+                       }
+               }
+       }
+}
+
+void merge_north(board *b) {
+       for(int i = 0; i < 4; ++i) {
+               for(int j = 1; j < 4; ++j) {
+                       if(b->x[i][j] != 0 && b->x[i][j] == b->x[i][j-1]) {
+                               b->x[i][j-1] *= 2;
+                               b->x[i][j] = 0;
+                               b->num_p--;
+                               b->points += b->x[i][j-1];
+                       }
+               }
+       }
+}
+
+void merge_south(board *b) {
+       for(int i = 0; i < 4; ++i) {
+               for(int j = 2; j >= 0; --j) {
+                       if(b->x[i][j] != 0 && b->x[i][j] == b->x[i][j+1]) {
+                               b->x[i][j+1] *= 2;
+                               b->x[i][j] = 0;
+                               b->num_p--;
+                               b->points += b->x[i][j+1];
+                       }
+               }
+       }
+}
+
+void merge_east(board *b) {
+       for(int i = 2; i >= 0; --i) {
+               for(int j = 0; j < 4; ++j) {
+                       if(b->x[i][j] != 0 && b->x[i+1][j] == b->x[i][j]) {
+                               b->x[i+1][j] *= 2;
+                               b->points += b->x[i+1][j];
+                               b->num_p--;
+                               b->x[i][j] = 0;
+                       }
+               }
+       }
+}
+
+void merge_west(board *b) {    
+       for(int i = 1; i < 4; ++i) {
+               for(int j = 0; j < 4; ++j) {
+                       if(b->x[i][j] != 0 && b->x[i-1][j] == b->x[i][j]) {
+                               b->x[i-1][j] *= 2;
+                               b->points += b->x[i-1][j];
+                               b->num_p--;
+                               b->x[i][j] = 0;
+                       }
+               }
+       }
+}
+
+void print_sep() {
+       printf("||--------------------------------------------------------------||\n");
+}
+
+void print_board_line(board *b, int l) {
+       printf("||\t%u\t|\t%u\t|\t%u\t|\t%u\t||\n", b->x[0][l], b->x[1][l], b->x[2][l], b->x[3][l]); 
+       print_sep();
+}
+
+void print_board(board *b) {
+       printf("Score: %u\n", b->points);
+       print_sep();
+       for(int i = 0; i < 4; ++i) {
+               print_board_line(b, i);
+       }
+       printf("\n");
+}
+
+void print_score(board *b) {
+       printf("Game Over\nScore:%u\n", b->points);
+}
+
+void merge_test1() {
+       board *b = new_board();
+       b->x[2][0] = 2;
+       b->x[3][0] = 2;
+       merge_east(b);
+       assert(b->x[3][0] == 4);
+}
+
+void merge_test2() {
+       board *b = new_board();
+       b->x[2][0] = 2;
+       b->x[3][0] = 2;
+       print_board(b);
+       move_west(b);
+       print_board(b);
+       merge_west(b);
+       print_board(b);
+       assert(b->x[0][0] == 4);
+}
+
+void merge_test3() {
+       board *b = new_board();
+       b->x[0][0] = 2;
+       b->x[0][1] = 2;
+       print_board(b);
+       merge_north(b);
+       print_board(b);
+       assert(b->x[0][0] == 4);
+}
+
+void merge_test4() {
+       board *b = new_board();
+       b->x[0][2] = 2;
+       b->x[0][3] = 2;
+       print_board(b);
+       merge_south(b);
+       print_board(b);
+       assert(b->x[0][3] == 4);
+}
+
+void move_merge_test1() {
+       board *b = new_board();
+       b->x[2][0] = 4;
+       b->x[3][0] = 2;
+       b->x[3][2] = 2;
+       print_board(b);
+       move_south(b);
+       print_board(b);
+       merge_south(b);
+       print_board(b);
+       assert(b->x[3][3] == 4);
+}
+
+void move_north_test() {
+       board *b = new_board();
+       b->x[2][3] = 8;
+       b->x[2][2] = 0;
+       b->x[2][1] = 0;
+       b->x[2][0] = 0;
+       b->x[0][1] = 2;
+       b->x[0][0] = 0;
+       b->x[3][0] = 4;
+       b->x[3][1] = 2;
+       b->x[3][2] = 3;
+       b->x[3][3] = 16;
+       print_board(b);
+       move_north(b);
+       merge_north(b);
+       move_north(b);
+       print_board(b);
+       assert(b->x[2][0] == 8);
+       assert(b->x[0][0] == 2);
+}
+
+void move_merge_test2() {
+       board *b = new_board();
+       b->x[3][0] = 2;
+       b->x[3][1] = 2;
+       b->x[3][2] = 4;
+       b->x[3][3] = 32;
+       print_board(b);
+       move_south(b);
+       merge_south(b);
+       move_south(b);
+       print_board(b);
+       assert(b->x[3][1] == 4);
+}
+
+void move_merge_test3() {
+       board *b = new_board();
+       b->x[0][0] = 0;
+       b->x[0][1] = 0;
+       b->x[0][2] = 0;
+       b->x[0][3] = 2;
+       b->x[1][0] = 0;
+       b->x[1][1] = 0;
+       b->x[1][2] = 0;
+       b->x[1][3] = 8;
+       b->x[2][0] = 0;
+       b->x[2][1] = 0;
+       b->x[2][2] = 0;
+       b->x[2][3] = 4;
+       b->x[3][0] = 2;
+       b->x[3][1] = 2;
+       b->x[3][2] = 4;
+       b->x[3][3] = 16;
+       print_board(b);
+       move_south(b);
+       merge_south(b);
+       move_south(b);
+       print_board(b);
+       assert(b->x[3][1] == 4);
+}
+
+void run_tests() {
+       /*
+       merge_test1();
+       merge_test2();
+       merge_test3();
+       merge_test4();
+       move_merge_test1();
+       move_north_test();
+       */
+       move_merge_test2();
+       move_merge_test3();
+}
+
+int main() {
+#if DBG
+       run_tests();
+#else
+       game_start();
+#endif
+}
diff --git a/main.h b/main.h
new file mode 100644 (file)
index 0000000..76a50d7
--- /dev/null
+++ b/main.h
@@ -0,0 +1,38 @@
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <time.h>
+
+typedef struct board board;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+enum direction {
+       north,
+       south,
+       west,
+       east,
+};
+
+struct board {
+       uint x[4][4];
+       uint points;
+       uint num_p;
+};
+
+board *new_board();
+void init_board(board*);
+void free_board(board*);
+bool move_possible_any(board*);
+bool move_possible(board*, const int d);
+void make_move(board*, const int d);
+void move(board*, const int d);
+
+void print_board(board*);
+void print_score(board*);
+
+#endif