fc5cb4f3ea50f3d2f7dcce179a672759ae7b7027
[TD_C.git] / TP_13 / exo2 / lib / coordinates.c
1 /*
2 * =====================================================================================
3 *
4 * Filename: coordinates.c
5 *
6 * Description: Data definition and functions to manipulate elements in the grid
7 *
8 * Version: 1.0
9 * Created: 16/03/2017 19:05:02
10 * Revision: none
11 * Compiler: gcc
12 *
13 * Author: Jerome Benoit (fraggle), jerome.benoit@piment-noir.org
14 * Organization: Piment Noir
15 *
16 * =====================================================================================
17 */
18
19 #include "coordinates.h"
20
21 void zero_coordinates(coordinates_t* coordinates_array) {
22
23 for (unsigned i = 0; i < MAX_COORDINATES; i++) {
24 coordinates_array[i] = set_coordinates(0, 0, 0);
25 }
26 }
27
28 coordinates_t set_coordinates(int y, int x, unsigned type) {
29 coordinates_t new_coordinates;
30
31 new_coordinates.y = y;
32 new_coordinates.x = x;
33 new_coordinates.type = type;
34 return new_coordinates;
35 }
36
37 /* FIXME: Does it worth doing a coordinates_t get_coordinates(int y, int x, unsigned type); helper function? */
38 /* Or a int get_coordinates_x(coordinates_t coordinates); helper function? */
39
40 /* this function do a lot of sanity checks before adding new board elements,
41 * hence the loop. moving the checks in the main loop is also possible.
42 * for now, just branch in the main loop given this function error value returned. */
43 unsigned add_coordinates(coordinates_t new_coordinates, coordinates_t* coordinates_array, unsigned round) {
44
45 /* valid coordinates are in the [1-3] range */
46 if (new_coordinates.y < 1 || new_coordinates.y > 3 || new_coordinates.x < 1 || new_coordinates.x > 3) {
47 return 3; /* error value for invalid coordinates */
48 } else if (round == MAX_COORDINATES - 1) {
49 /* round is off-by-one vs. MAX_COORDINATES */
50 coordinates_array[MAX_COORDINATES - 1] = new_coordinates;
51 return 1; /* error value for full array */
52 }
53 for (unsigned i = 0; i < MAX_COORDINATES; i++) {
54 /* check if already entered */
55 if (new_coordinates.y == (coordinates_array + i)->y && new_coordinates.x == (coordinates_array + i)->x) {
56 return 2; /* error value for duplicates */
57 } else if ((coordinates_array + i)->y == 0 && (coordinates_array + i)->x == 0) {
58 coordinates_array[i] = new_coordinates;
59 return 0; /* error value when everything if fine */
60 }
61 }
62 return 4; /* error value for unknown error case - should never happen - */
63 }
64
65 static bool chk_line(coordinates_t* coordinates_array, int line_number, unsigned round) {
66 unsigned nb_o_align = 0;
67 unsigned nb_x_align = 0;
68
69 for (unsigned i = 0; i <= round; i++) {
70 /* check if they are all the same */
71 if ((coordinates_array + i)->y == line_number && (coordinates_array + i)->type == 0) {
72 nb_o_align++;
73 }
74 if ((coordinates_array + i)->y == line_number && (coordinates_array + i)->type == 1) {
75 nb_x_align++;
76 }
77 }
78 if (nb_o_align == 3 || nb_x_align == 3) {
79 return true;
80 }
81 return false;
82 }
83
84 static bool chk_column(coordinates_t* coordinates_array, int column_number, unsigned round) {
85 unsigned nb_o_align = 0;
86 unsigned nb_x_align = 0;
87
88 for (unsigned i = 0; i <= round; i++) {
89 /* check if they are all the same */
90 if ((coordinates_array + i)->x == column_number && (coordinates_array + i)->type == 0) {
91 nb_o_align++;
92 }
93 if ((coordinates_array + i)->x == column_number && (coordinates_array + i)->type == 1) {
94 nb_x_align++;
95 }
96 }
97 /* one column must be full of the same type */
98 if (nb_o_align == 3 || nb_x_align == 3) {
99 return true;
100 }
101 return false;
102 }
103
104 static bool chk_diagonals(coordinates_t* coordinates_array, unsigned round) {
105 unsigned nb_o_diag_one = 0, nb_o_diag_two = 0;
106 unsigned nb_x_diag_one = 0, nb_x_diag_two = 0;
107
108 for (unsigned i = 0; i <= round; i++) {
109 /* dumb count of each elements type in the two diagonals */
110 for (int y_x_diag = 1; y_x_diag < 4; y_x_diag++) {
111 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == y_x_diag && (coordinates_array + i)->type == 0) {
112 nb_o_diag_one++;
113 }
114 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == (4 - y_x_diag) && (coordinates_array + i)->type == 0) {
115 nb_o_diag_two++;
116 }
117 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == y_x_diag && (coordinates_array + i)->type == 1) {
118 nb_x_diag_one++;
119 }
120 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == (4 - y_x_diag) && (coordinates_array + i)->type == 1) {
121 nb_x_diag_two++;
122 }
123 }
124 if (nb_o_diag_one == 3 || nb_o_diag_two == 3 || nb_x_diag_one == 3 || nb_x_diag_two == 3) {
125 return true;
126 }
127 }
128 return false;
129 }
130
131 bool chk_win_conditions(coordinates_t* coordinates_array, unsigned round) {
132
133 /* winning conditions begin at round = 4 */
134 if (round > 3) {
135 if (chk_diagonals(coordinates_array, round)) {
136 return true;
137 }
138 for (unsigned i = 1; i < 4; i++) {
139 if (chk_line(coordinates_array, i, round) || \
140 chk_column(coordinates_array, i, round)) {
141 return true;
142 }
143 }
144 }
145 return false;
146 }