TP 13 exo2: Fix the beginning round of winning conditions check
[TD_C.git] / TP_13 / exo2 / lib / coordinates.c
CommitLineData
5df3071e
JB
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
811d4abe
JB
21#include <ncurses.h>
22
5df3071e 23void init_coordinates(coordinates_t* coordinates_array) {
811d4abe 24
5df3071e
JB
25 for (unsigned i = 0; i < MAX_COORDINATES; i++) {
26 coordinates_array[i] = set_coordinates(0, 0, 0);
27 }
28}
29
30coordinates_t set_coordinates(int y, int x, unsigned type) {
31 coordinates_t new_coordinates;
32
33 new_coordinates.y = y;
34 new_coordinates.x = x;
35 new_coordinates.type = type;
36 return new_coordinates;
37}
38
811d4abe
JB
39/* FIXME: Does it worth doing a coordinates_t get_coordinates(int y, int x, unsigned type); helper function? */
40/* Or a int get_coordinates_x(int y, int x, unsigned type); helper function? */
41
04b0afb5
JB
42/* the function do a lot of sanity checks before adding new board elements,
43 * hence the loop. moving the checks in the main loop is also possible */
44unsigned add_coordinates(coordinates_t new_coordinates, coordinates_t* coordinates_array, unsigned round) {
811d4abe 45
5df3071e
JB
46 /* valid coordinates are in the [1-3] range */
47 if (new_coordinates.y < 1 || new_coordinates.y > 3 || new_coordinates.x < 1 || new_coordinates.x > 3) {
48 return 3; /* error value for invalid coordinates */
811d4abe
JB
49 } else if (round == MAX_COORDINATES) {
50 /* round is off-by-one */
51 coordinates_array[MAX_COORDINATES - 1] = new_coordinates;
04b0afb5 52 return 1; /* error value for full array */
5df3071e
JB
53 }
54 for (unsigned i = 0; i < MAX_COORDINATES; i++) {
55 /* check if already entered */
56 if (new_coordinates.y == (coordinates_array + i)->y && new_coordinates.x == (coordinates_array + i)->x) {
57 return 2; /* error value for duplicates */
58 } else if ((coordinates_array + i)->y == 0 && (coordinates_array + i)->x == 0) {
59 coordinates_array[i] = new_coordinates;
60 return 0; /* error value when everything if fine */
61 }
62 }
04b0afb5
JB
63 return 4; /* error value for unknown error case - should never happen - */
64}
65
811d4abe
JB
66static bool chk_line(coordinates_t* coordinates_array, int line_number, unsigned round) {
67 unsigned nb_o_align = 0;
68 unsigned nb_x_align = 0;
69
70 for (unsigned i = 0; i < round; i++) {
71 /* check if they are all the same */
72 if ((coordinates_array + i)->y == line_number && (coordinates_array + i)->type == 0) {
73 nb_o_align++;
74 }
75 if ((coordinates_array + i)->y == line_number && (coordinates_array + i)->type == 1) {
76 nb_x_align++;
77 }
78 }
79 if (nb_o_align == 3 || nb_x_align == 3) {
80 return true;
81 }
82 return false;
83}
84
85static bool chk_column(coordinates_t* coordinates_array, int column_number, unsigned round) {
86 unsigned nb_o_align = 0;
87 unsigned nb_x_align = 0;
04b0afb5 88
811d4abe
JB
89 for (unsigned i = 0; i < round; i++) {
90 /* check if they are all the same */
91 if ((coordinates_array + i)->x == column_number && (coordinates_array + i)->type == 0) {
92 nb_o_align++;
93 }
94 if ((coordinates_array + i)->x == column_number && (coordinates_array + i)->type == 1) {
95 nb_x_align++;
96 }
97 }
98 /* one column must be full of the same type */
99 if (nb_o_align == 3 || nb_x_align == 3) {
100 return true;
101 }
102 return false;
103}
104
105static bool chk_diagonals(coordinates_t* coordinates_array, unsigned round) {
106 unsigned nb_o_diag_one = 0, nb_o_diag_two = 0;
107 unsigned nb_x_diag_one = 0, nb_x_diag_two = 0;
108
109 for (unsigned i = 0; i < round; i++) {
110 /* dumb count of each elements type in the two diagonals */
111 for (int y_x_diag = 1; y_x_diag < 4; y_x_diag++) {
112 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == y_x_diag && (coordinates_array + i)->type == 0) {
113 nb_o_diag_one++;
114 }
115 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == (4 - y_x_diag) && (coordinates_array + i)->type == 0) {
116 nb_o_diag_two++;
117 }
118 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == y_x_diag && (coordinates_array + i)->type == 1) {
119 nb_x_diag_one++;
120 }
121 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == (4 - y_x_diag) && (coordinates_array + i)->type == 1) {
122 nb_x_diag_two++;
123 }
124 }
125 if (nb_o_diag_one == 3 || nb_o_diag_two == 3 || nb_x_diag_one == 3 || nb_x_diag_two == 3) {
126 return true;
127 }
128 }
129 return false;
130}
131
132bool chk_win_conditions(coordinates_t* coordinates_array, unsigned round) {
133
a7ebbad7
JB
134 /* winning conditions begin at round = 5 */
135 if (round > 4) {
811d4abe
JB
136 if (chk_diagonals(coordinates_array, round)) {
137 return true;
138 }
139 for (unsigned i = 1; i < 4; i++) {
140 if (chk_line(coordinates_array, i, round) || \
141 chk_column(coordinates_array, i, round)) {
142 return true;
143 }
144 }
04b0afb5
JB
145 }
146 return false;
5df3071e 147}