TP_13 exo2: Finish the implementation of a basic tic-tac-toe game.
[TD_C.git] / TP_13 / exo2 / lib / coordinates.c
index a9d8159a3584af3fc321d4857d4f73d558d80267..0a2d5e028c406579b8da3c3509727463fee1710e 100644 (file)
 
 #include "coordinates.h"
 
+#include <ncurses.h>
+
 void init_coordinates(coordinates_t* coordinates_array) {
+
     for (unsigned i = 0; i < MAX_COORDINATES; i++) {
         coordinates_array[i] = set_coordinates(0, 0, 0);
     }
@@ -33,16 +36,21 @@ coordinates_t set_coordinates(int y, int x, unsigned type) {
     return new_coordinates;
 }
 
+/* FIXME: Does it worth doing a coordinates_t get_coordinates(int y, int x, unsigned type); helper function? */
+/* Or a int get_coordinates_x(int y, int x, unsigned type); helper function? */
+
 /* the function do a lot of sanity checks before adding new board elements,
  * hence the loop. moving the checks in the main loop is also possible */
 unsigned add_coordinates(coordinates_t new_coordinates, coordinates_t* coordinates_array, unsigned round) {
+
     /* valid coordinates are in the [1-3] range */
     if (new_coordinates.y < 1 || new_coordinates.y > 3 || new_coordinates.x < 1 || new_coordinates.x > 3) {
         return 3; /* error value for invalid coordinates */
-    } else if (round == MAX_COORDINATES + 1) {
+    } else if (round == MAX_COORDINATES) {
+        /* round is off-by-one */
+        coordinates_array[MAX_COORDINATES - 1] = new_coordinates;
         return 1; /* error value for full array */
     }
-
     for (unsigned i = 0; i < MAX_COORDINATES; i++) {
         /* check if already entered */
         if (new_coordinates.y == (coordinates_array + i)->y && new_coordinates.x == (coordinates_array + i)->x) {
@@ -55,9 +63,85 @@ unsigned add_coordinates(coordinates_t new_coordinates, coordinates_t* coordinat
     return 4; /* error value for unknown error case - should never happen - */
 }
 
-bool chk_win_conditions(coordinates_t* coordinates_array) {
-    for (unsigned i = 0; i < MAX_COORDINATES; i++) {
+static bool chk_line(coordinates_t* coordinates_array, int line_number, unsigned round) {
+    unsigned nb_o_align = 0;
+    unsigned nb_x_align = 0;
+
+    for (unsigned i = 0; i < round; i++) {
+        /* check if they are all the same */
+        if ((coordinates_array + i)->y == line_number && (coordinates_array + i)->type == 0) {
+            nb_o_align++;
+        }
+        if ((coordinates_array + i)->y == line_number && (coordinates_array + i)->type == 1) {
+            nb_x_align++;
+        }
+    }
+    if (nb_o_align == 3 || nb_x_align == 3) {
+        return true;
+    }
+    return false;
+}
+
+static bool chk_column(coordinates_t* coordinates_array, int column_number, unsigned round) {
+    unsigned nb_o_align = 0;
+    unsigned nb_x_align = 0;
 
+    for (unsigned i = 0; i < round; i++) {
+        /* check if they are all the same */
+        if ((coordinates_array + i)->x == column_number && (coordinates_array + i)->type == 0) {
+            nb_o_align++;
+        }
+        if ((coordinates_array + i)->x == column_number && (coordinates_array + i)->type == 1) {
+            nb_x_align++;
+        }
+    }
+    /* one column must be full of the same type */
+    if (nb_o_align == 3 || nb_x_align == 3) {
+        return true;
+    }
+    return false;
+}
+
+static bool chk_diagonals(coordinates_t* coordinates_array, unsigned round) {
+    unsigned nb_o_diag_one = 0, nb_o_diag_two = 0;
+    unsigned nb_x_diag_one = 0, nb_x_diag_two = 0;
+
+    for (unsigned i = 0; i < round; i++) {
+        /* dumb count of each elements type in the two diagonals */
+        for (int y_x_diag = 1; y_x_diag < 4; y_x_diag++) {
+            if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == y_x_diag && (coordinates_array + i)->type == 0) {
+                nb_o_diag_one++;
+            }
+            if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == (4 - y_x_diag) && (coordinates_array + i)->type == 0) {
+                nb_o_diag_two++;
+            }
+            if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == y_x_diag && (coordinates_array + i)->type == 1) {
+                nb_x_diag_one++;
+            }
+            if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == (4 - y_x_diag) && (coordinates_array + i)->type == 1) {
+                nb_x_diag_two++;
+            }
+        }
+        if (nb_o_diag_one == 3 || nb_o_diag_two == 3 || nb_x_diag_one == 3 || nb_x_diag_two == 3) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool chk_win_conditions(coordinates_t* coordinates_array, unsigned round) {
+
+    /* winning conditions begin at round = 4 */
+    if (round > 3) {
+        if (chk_diagonals(coordinates_array, round)) {
+            return true;
+        }
+        for (unsigned i = 1; i < 4; i++) {
+            if (chk_line(coordinates_array, i, round) || \
+                chk_column(coordinates_array, i, round)) {
+                return true;
+            }
+        }
     }
     return false;
 }