attack_munir

Форк
0
/
main.c 
490 строк · 12.3 Кб
1
#include <stdio.h>
2
#include <string.h>
3
#include <stdlib.h>
4
#include <ctype.h>
5
#include <stdbool.h>
6
#include <math.h>
7

8
// maximum length of string
9
#define MAX_LENGTH 100
10
// maximum power of players
11
#define MAX_POWER 1000
12
// minimal value
13
#define MIN(ARG1, ARG2) (ARG1) < (ARG2) ? (ARG1) : (ARG2)
14

15
/**
16
 * Function that throws an error and closes files
17
 * @param fileIn Pointer to input file
18
 * @param fileOut Pointer to output file
19
*/
20
void error(FILE *fileIn, FILE *fileOut) {
21
    fclose(fileIn);
22
    fclose(fileOut);
23

24
    fileOut = fopen("output.txt", "w");
25
    fprintf(fileOut, "Invalid inputs\n");
26
    exit(0);
27
}
28

29

30
/**
31
 * Function that splits a string by symbol, writes it into array and returns amount of elements
32
 * @param str String that is needed to split
33
 * @param delim Symbol to split the string
34
 * @param dest Array where the split string will be
35
*/
36
int split(char *str, char *delim, char dest[][100]) {
37
    char *token = strtok(str, delim);
38
    int counter = 0;
39
    while (token != NULL) {
40
        strcpy(dest[counter++], token);
41
        token = strtok(NULL, delim);
42
    }
43
    return counter;
44
}
45

46
/**
47
 * Function that trims a string by "\n"
48
 * @param str String itself
49
*/
50
void trim(char *str) {
51
    str[strcspn(str, "\n")] = '\0';
52
}
53

54
/**
55
 * Function that checks if there any non-english symbols in string
56
 * @param s String itself
57
*/
58
bool isString(char s[MAX_LENGTH]) {
59
    int size = (int)strlen(s) - 1;
60
    for (int i = 0; i < size; i++) {
61
        char elem = s[i];
62
        if (!isalpha(elem)) {
63
            return false;
64
        }
65
    }
66
    return true;
67
}
68

69
/**
70
 * Function that checks if the string satisfies the condition of name
71
 * @param s String itself
72
*/
73
bool isName(char s[MAX_LENGTH]) {
74
    int len = (int)strlen(s);
75
    return isString(s) && isupper(s[0]) && len >= 2 && len <= 20;
76
}
77

78
/**
79
 * Function that checks if the string contains a number
80
 * @param s String itself
81
*/
82
bool isNumber(char s[MAX_LENGTH]) {
83
    int size = (int)strlen(s) - 1;
84
    for (int i = 0; i < size; i++) {
85
        char elem = s[i];
86
        if (!isdigit(elem)) {
87
            return false;
88
        }
89
    }
90
    return true;
91
}
92

93

94
/**
95
 * Function that checks if the string contains a boolean
96
 * @param s String itself
97
*/
98
bool isBool(char s[MAX_LENGTH]) {
99
    return (!strcmp(s, "True\n") || !strcmp(s, "False\n"));
100
}
101

102
/**
103
 * Function that takes a string with "True" or "False" written and returns bool
104
 * @param s String itself
105
*/
106
void *getBool(char s[MAX_LENGTH]) {
107
    if (!strcmp(s, "True\n")) return (void *) true;
108
    if (!strcmp(s, "False\n")) return (void *) false;
109
    return NULL;
110
}
111

112
/**
113
 * Function that reads a string and writes it to an int variable and returns if a number is received
114
 * @param fileIn Pointer to input file
115
 * @param n Pointer to int value
116
 */
117
bool inputNumber(FILE *fileIn, int *n) {
118
    char s[MAX_LENGTH];
119
    fgets(s, MAX_LENGTH, fileIn);
120
    if (!isNumber(s)) return false;
121

122
    *n = atoi(s);
123
    return true;
124
}
125

126
// Structure of player
127
typedef struct {
128
    char name[200];
129
    int teamNumber;
130
    int power;
131
    bool visibility;
132
    bool active;
133
} Player;
134

135
// Structure of Team
136
typedef struct {
137
    int number;
138
    int power;
139
} Team;
140

141
/**
142
 * Comparator for Team sorting function
143
 * @param t1 First Team
144
 * @param t2 Second Team
145
*/
146
int teamCmp(void *team1, void *team2) {
147
    Team t1 = *(Team *) team1;
148
    Team t2 = *(Team *) team2;
149
    return t1.power - t2.power;
150
}
151

152
/**
153
 * Function that returns player by name
154
 * @param name Name of player to be checked
155
 * @param playersCount Amount of all players
156
 * @param players Array with all players
157
*/
158
Player *getPlayer(char name[], int playersCount, Player *players) {
159
    for (Player *p = players; p != players + playersCount; ++p) {
160
        if (!strcmp(p->name, name)) {
161
            return p;
162
        }
163
    }
164
    return NULL;
165
}
166

167
/**
168
 * Function that prints info about player in terminal
169
 * @param player Player itself
170
*/
171
void printPlayer(Player player) {
172
    printf("%s : Team=%d; power=%d; visibility=%d\n", player.name, player.teamNumber, player.power, player.visibility);
173
}
174

175
/**
176
 * Function that does attack action
177
 * @param player1 First player
178
 * @param player2 Second player
179
*/
180
void attack(Player *player1, Player *player2) {
181
    if (player1->power > player2->power) {
182
        player1->power = MIN(player1->power + (player1->power - player2->power), MAX_POWER);
183
        player2->power = 0;
184
    }
185
    if (player2->power > player1->power) {
186
        player2->power = MIN(player2->power + (player2->power - player1->power), MAX_POWER);
187
        player1->power = 0;
188
    }
189
    if (player1->power == player2->power) {
190
        player1->power = 0;
191
        player2->power = 0;
192
    }
193
}
194

195
/**
196
 * Function that does flip_visibility action
197
 * @param player First player
198
*/
199
void flipVisibility(Player *player) {
200
    player->visibility = !player->visibility;
201
}
202

203
/**
204
 * Function that does heal action
205
 * @param player1 First player
206
 * @param player2 Second player
207
*/
208
void heal(Player *player1, Player *player2) {
209
    int half = ceil(player1->power / 2.0);
210
    player1->power = half;
211
    player2->power = MIN(player2->power + half, MAX_POWER);
212
}
213

214
/**
215
 * Function that does super action
216
 * @param player1 First player
217
 * @param player2 Second player
218
*/
219
void super(Player *player1, Player *player2, Player *players, int *playersCount) {
220
    player1->active = false;
221
    player2->active = false;
222
    static int counter = 0;
223
    char name[100];
224
    sprintf(name, "S_%d", counter++);
225
    Player player = {.power = MIN(player1->power + player2->power,
226
                                  MAX_POWER), .visibility = true, .teamNumber = player1->teamNumber, .active = true};
227
    strcpy(player.name, name);
228

229
    players[(*playersCount)++] = player;
230

231
}
232

233
/**
234
 * Function that parses string and does action
235
 * @param s String that contains action
236
 * @param players Array with all players
237
 * @param playersCount Amount of all players
238
 * @param fileOut File where will be output
239
*/
240
void actions(char s[MAX_LENGTH], Player *players, int *playersCount, FILE *fileIn, FILE *fileOut) {
241
    char strings[3][MAX_LENGTH];
242
    int actionCount = split(s, " ", strings);
243

244
    // Proceeds if action is attack
245
    if (!strcmp(strings[0], "attack")) {
246
        if (actionCount != 3) {
247
            error(fileIn, fileOut);
248
        }
249

250
        Player *player1 = getPlayer(strings[1], *playersCount, players);
251
        Player *player2 = getPlayer(strings[2], *playersCount, players);
252

253
        if (!player1 || !player2) {
254
            error(fileIn, fileOut);
255
        }
256

257
        if (!player1->visibility) {
258
            fprintf(fileOut, "This player can't play\n");
259
            return;
260
        }
261

262

263
        if (!player1->power) {
264
            fprintf(fileOut, "This player is frozen\n");
265
            return;
266
        }
267

268
        if (!player2->visibility) {
269
            player1->power = 0;
270
            return;
271
        }
272

273
        attack(player1, player2);
274
        return;
275
    }
276

277
    // Proceeds if action is flip_visibility
278
    if (!strcmp(strings[0], "flip_visibility")) {
279
        if (actionCount != 2) {
280
            error(fileIn, fileOut);
281
        }
282

283
        Player *player = getPlayer(strings[1], *playersCount, players);
284

285
        if (!player) {
286
            error(fileIn, fileOut);
287
        }
288

289
        if (!player->power) {
290
            fprintf(fileOut, "This player is frozen\n");
291
            return;
292
        }
293

294
        flipVisibility(player);
295
        return;
296
    }
297

298
    // Proceeds if action is heal
299
    if (!strcmp(strings[0], "heal")) {
300
        if (actionCount != 3) {
301
            error(fileIn, fileOut);
302
        }
303

304
        Player *player1 = getPlayer(strings[1], *playersCount, players);
305
        Player *player2 = getPlayer(strings[2], *playersCount, players);
306

307
        if (!player1 || !player2) {
308
            error(fileIn, fileOut);
309
        }
310

311
        if (!player1->visibility) {
312
            fprintf(fileOut, "This player can't play\n");
313
            return;
314
        }
315

316
        if (!player1->power) {
317
            fprintf(fileOut, "This player is frozen\n");
318
            return;
319
        }
320

321
        if (player1 == player2) {
322
            fprintf(fileOut, "The player cannot heal itself\n");
323
            return;
324
        }
325

326
        if (player1->teamNumber != player2->teamNumber) {
327
            fprintf(fileOut, "Both players should be from the same team\n");
328
            return;
329
        }
330

331
        heal(player1, player2);
332
        return;
333
    }
334

335
    // Proceeds if action is super
336
    if (!strcmp(strings[0], "super")) {
337
        if (actionCount != 3) {
338
            error(fileIn, fileOut);
339
        }
340

341
        Player *player1 = getPlayer(strings[1], *playersCount, players);
342
        Player *player2 = getPlayer(strings[2], *playersCount, players);
343

344
        if (!player1 || !player2) {
345
            error(fileIn, fileOut);
346
        }
347

348

349
        if (!player1->visibility) {
350
            fprintf(fileOut, "This player can't play\n");
351
            return;
352
        }
353

354
        if (!player1->power) {
355
            fprintf(fileOut, "This player is frozen\n");
356
            return;
357
        }
358

359
        if (!strcmp(player1->name, player2->name)) {
360
            fprintf(fileOut, "The player cannot do super action with itself\n");
361
            return;
362
        }
363

364
        if (player1->teamNumber != player2->teamNumber) {
365
            fprintf(fileOut, "Both players should be from the same team\n");
366
            return;
367
        }
368

369
        super(player1, player2, players, playersCount);
370
        return;
371
    }
372

373
    // Proceeds if action is wrong
374
    error(fileIn, fileOut);
375
}
376

377

378
int main() {
379
    // Opening files
380
    FILE *fileIn = fopen("input.txt", "r");
381
    FILE *fileOut = fopen("output.txt", "w");
382

383
    // Checking if file exists
384
    if (fileIn == NULL)
385
        error(fileIn, fileOut);
386

387
    // Getting number of teams
388
    int n;
389
    if (!inputNumber(fileIn, &n) || (n < 1) || (n > 10)) error(fileIn, fileOut);
390

391
    // Getting captains
392
    char captains[n][MAX_LENGTH];
393
    for (int i = 0; i < n; i++) {
394
        if (feof(fileIn)) {
395
            error(fileIn, fileOut);
396
        }
397

398
        fgets(captains[i], MAX_LENGTH, fileIn);
399
        if (!isString(captains[i]) || !isName(captains[i])) {
400
            error(fileIn, fileOut);
401
        }
402
        trim(captains[i]);
403
    }
404

405
    // Getting number of players
406
    int m;
407
    if (!inputNumber(fileIn, &m) || (m < n) || (m > 100)) error(fileIn, fileOut);
408

409
    // Getting players
410
    Player players[m * 2];
411
    for (int i = 0; i < m; i++) {
412
        char name[20];
413
        int teamNumber;
414
        int power;
415
        char visibility[10];
416
        bool visible;
417

418
        // Checking if line exists
419
        if (feof(fileIn)) {
420
            error(fileIn, fileOut);
421
        }
422

423
        // Getting player's name
424
        fgets(name, MAX_LENGTH, fileIn);
425
        trim(name);
426
        if (!isString(name) || !isName(name)) {
427
            error(fileIn, fileOut);
428
        }
429

430
        // Getting player's Team number
431
        if (!inputNumber(fileIn, &teamNumber) || (teamNumber < 0) || (teamNumber >= n)) error(fileIn, fileOut);
432

433
        // Getting player's power
434
        if (!inputNumber(fileIn, &power) || (power < 0) || (power > 1000)) error(fileIn, fileOut);
435

436
        // Getting player's visibility
437
        fgets(visibility, MAX_LENGTH, fileIn);
438
        if (!isBool(visibility)) {
439
            error(fileIn, fileOut);
440
        }
441
        visible = getBool(visibility);
442

443
        // Creating player and adding it to array
444
        Player player = {.teamNumber = teamNumber, .visibility=visible, .power=power, .active=true};
445
        strcpy(player.name, name);
446
        players[i] = player;
447
    }
448

449
    // Getting actions
450
    char string[MAX_LENGTH];
451
    int s = 0;
452
    while (fgets(string, MAX_LENGTH, fileIn) != NULL) {
453
        s++;
454
        trim(string);
455
        actions(string, players, &m, fileIn, fileOut);
456
    }
457

458

459
    // Checking if amount of actions satisfies the condition
460
    if (s > 1000) {
461
        error(fileIn, fileOut);
462
    }
463

464
    // Counting power of each Team
465
    Team powers[n];
466
    for (int i = 0; i < n; i++) {
467
        powers[i].number = i;
468
        powers[i].power = 0;
469
    }
470
    for (int i = 0; i < m; i++) {
471
        Player player = players[i];
472
        if (player.active) {
473
            powers[player.teamNumber].power += player.power;
474
        }
475
    }
476

477
    // Getting Team with the biggest amount of power
478
    qsort(powers, n, sizeof(Team), teamCmp);
479
    if (powers[n - 1].power == powers[n - 2].power) {
480
        fprintf(fileOut, "It's a tie\n");
481
    } else {
482
        fprintf(fileOut, "The chosen wizard is %s\n", captains[powers[n - 1].number]);
483
    }
484

485
    // Closing files
486
    fclose(fileIn);
487
    fclose(fileOut);
488

489
    return 0;
490
}
491

492

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.