attack_munir
/
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 10010// maximum power of players
11#define MAX_POWER 100012// 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*/
20void error(FILE *fileIn, FILE *fileOut) {21fclose(fileIn);22fclose(fileOut);23
24fileOut = fopen("output.txt", "w");25fprintf(fileOut, "Invalid inputs\n");26exit(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*/
36int split(char *str, char *delim, char dest[][100]) {37char *token = strtok(str, delim);38int counter = 0;39while (token != NULL) {40strcpy(dest[counter++], token);41token = strtok(NULL, delim);42}43return counter;44}
45
46/**
47* Function that trims a string by "\n"
48* @param str String itself
49*/
50void trim(char *str) {51str[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*/
58bool isString(char s[MAX_LENGTH]) {59int size = (int)strlen(s) - 1;60for (int i = 0; i < size; i++) {61char elem = s[i];62if (!isalpha(elem)) {63return false;64}65}66return true;67}
68
69/**
70* Function that checks if the string satisfies the condition of name
71* @param s String itself
72*/
73bool isName(char s[MAX_LENGTH]) {74int len = (int)strlen(s);75return 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*/
82bool isNumber(char s[MAX_LENGTH]) {83int size = (int)strlen(s) - 1;84for (int i = 0; i < size; i++) {85char elem = s[i];86if (!isdigit(elem)) {87return false;88}89}90return true;91}
92
93
94/**
95* Function that checks if the string contains a boolean
96* @param s String itself
97*/
98bool isBool(char s[MAX_LENGTH]) {99return (!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*/
106void *getBool(char s[MAX_LENGTH]) {107if (!strcmp(s, "True\n")) return (void *) true;108if (!strcmp(s, "False\n")) return (void *) false;109return 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*/
117bool inputNumber(FILE *fileIn, int *n) {118char s[MAX_LENGTH];119fgets(s, MAX_LENGTH, fileIn);120if (!isNumber(s)) return false;121
122*n = atoi(s);123return true;124}
125
126// Structure of player
127typedef struct {128char name[200];129int teamNumber;130int power;131bool visibility;132bool active;133} Player;134
135// Structure of Team
136typedef struct {137int number;138int power;139} Team;140
141/**
142* Comparator for Team sorting function
143* @param t1 First Team
144* @param t2 Second Team
145*/
146int teamCmp(void *team1, void *team2) {147Team t1 = *(Team *) team1;148Team t2 = *(Team *) team2;149return 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*/
158Player *getPlayer(char name[], int playersCount, Player *players) {159for (Player *p = players; p != players + playersCount; ++p) {160if (!strcmp(p->name, name)) {161return p;162}163}164return NULL;165}
166
167/**
168* Function that prints info about player in terminal
169* @param player Player itself
170*/
171void printPlayer(Player player) {172printf("%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*/
180void attack(Player *player1, Player *player2) {181if (player1->power > player2->power) {182player1->power = MIN(player1->power + (player1->power - player2->power), MAX_POWER);183player2->power = 0;184}185if (player2->power > player1->power) {186player2->power = MIN(player2->power + (player2->power - player1->power), MAX_POWER);187player1->power = 0;188}189if (player1->power == player2->power) {190player1->power = 0;191player2->power = 0;192}193}
194
195/**
196* Function that does flip_visibility action
197* @param player First player
198*/
199void flipVisibility(Player *player) {200player->visibility = !player->visibility;201}
202
203/**
204* Function that does heal action
205* @param player1 First player
206* @param player2 Second player
207*/
208void heal(Player *player1, Player *player2) {209int half = ceil(player1->power / 2.0);210player1->power = half;211player2->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*/
219void super(Player *player1, Player *player2, Player *players, int *playersCount) {220player1->active = false;221player2->active = false;222static int counter = 0;223char name[100];224sprintf(name, "S_%d", counter++);225Player player = {.power = MIN(player1->power + player2->power,226MAX_POWER), .visibility = true, .teamNumber = player1->teamNumber, .active = true};227strcpy(player.name, name);228
229players[(*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*/
240void actions(char s[MAX_LENGTH], Player *players, int *playersCount, FILE *fileIn, FILE *fileOut) {241char strings[3][MAX_LENGTH];242int actionCount = split(s, " ", strings);243
244// Proceeds if action is attack245if (!strcmp(strings[0], "attack")) {246if (actionCount != 3) {247error(fileIn, fileOut);248}249
250Player *player1 = getPlayer(strings[1], *playersCount, players);251Player *player2 = getPlayer(strings[2], *playersCount, players);252
253if (!player1 || !player2) {254error(fileIn, fileOut);255}256
257if (!player1->visibility) {258fprintf(fileOut, "This player can't play\n");259return;260}261
262
263if (!player1->power) {264fprintf(fileOut, "This player is frozen\n");265return;266}267
268if (!player2->visibility) {269player1->power = 0;270return;271}272
273attack(player1, player2);274return;275}276
277// Proceeds if action is flip_visibility278if (!strcmp(strings[0], "flip_visibility")) {279if (actionCount != 2) {280error(fileIn, fileOut);281}282
283Player *player = getPlayer(strings[1], *playersCount, players);284
285if (!player) {286error(fileIn, fileOut);287}288
289if (!player->power) {290fprintf(fileOut, "This player is frozen\n");291return;292}293
294flipVisibility(player);295return;296}297
298// Proceeds if action is heal299if (!strcmp(strings[0], "heal")) {300if (actionCount != 3) {301error(fileIn, fileOut);302}303
304Player *player1 = getPlayer(strings[1], *playersCount, players);305Player *player2 = getPlayer(strings[2], *playersCount, players);306
307if (!player1 || !player2) {308error(fileIn, fileOut);309}310
311if (!player1->visibility) {312fprintf(fileOut, "This player can't play\n");313return;314}315
316if (!player1->power) {317fprintf(fileOut, "This player is frozen\n");318return;319}320
321if (player1 == player2) {322fprintf(fileOut, "The player cannot heal itself\n");323return;324}325
326if (player1->teamNumber != player2->teamNumber) {327fprintf(fileOut, "Both players should be from the same team\n");328return;329}330
331heal(player1, player2);332return;333}334
335// Proceeds if action is super336if (!strcmp(strings[0], "super")) {337if (actionCount != 3) {338error(fileIn, fileOut);339}340
341Player *player1 = getPlayer(strings[1], *playersCount, players);342Player *player2 = getPlayer(strings[2], *playersCount, players);343
344if (!player1 || !player2) {345error(fileIn, fileOut);346}347
348
349if (!player1->visibility) {350fprintf(fileOut, "This player can't play\n");351return;352}353
354if (!player1->power) {355fprintf(fileOut, "This player is frozen\n");356return;357}358
359if (!strcmp(player1->name, player2->name)) {360fprintf(fileOut, "The player cannot do super action with itself\n");361return;362}363
364if (player1->teamNumber != player2->teamNumber) {365fprintf(fileOut, "Both players should be from the same team\n");366return;367}368
369super(player1, player2, players, playersCount);370return;371}372
373// Proceeds if action is wrong374error(fileIn, fileOut);375}
376
377
378int main() {379// Opening files380FILE *fileIn = fopen("input.txt", "r");381FILE *fileOut = fopen("output.txt", "w");382
383// Checking if file exists384if (fileIn == NULL)385error(fileIn, fileOut);386
387// Getting number of teams388int n;389if (!inputNumber(fileIn, &n) || (n < 1) || (n > 10)) error(fileIn, fileOut);390
391// Getting captains392char captains[n][MAX_LENGTH];393for (int i = 0; i < n; i++) {394if (feof(fileIn)) {395error(fileIn, fileOut);396}397
398fgets(captains[i], MAX_LENGTH, fileIn);399if (!isString(captains[i]) || !isName(captains[i])) {400error(fileIn, fileOut);401}402trim(captains[i]);403}404
405// Getting number of players406int m;407if (!inputNumber(fileIn, &m) || (m < n) || (m > 100)) error(fileIn, fileOut);408
409// Getting players410Player players[m * 2];411for (int i = 0; i < m; i++) {412char name[20];413int teamNumber;414int power;415char visibility[10];416bool visible;417
418// Checking if line exists419if (feof(fileIn)) {420error(fileIn, fileOut);421}422
423// Getting player's name424fgets(name, MAX_LENGTH, fileIn);425trim(name);426if (!isString(name) || !isName(name)) {427error(fileIn, fileOut);428}429
430// Getting player's Team number431if (!inputNumber(fileIn, &teamNumber) || (teamNumber < 0) || (teamNumber >= n)) error(fileIn, fileOut);432
433// Getting player's power434if (!inputNumber(fileIn, &power) || (power < 0) || (power > 1000)) error(fileIn, fileOut);435
436// Getting player's visibility437fgets(visibility, MAX_LENGTH, fileIn);438if (!isBool(visibility)) {439error(fileIn, fileOut);440}441visible = getBool(visibility);442
443// Creating player and adding it to array444Player player = {.teamNumber = teamNumber, .visibility=visible, .power=power, .active=true};445strcpy(player.name, name);446players[i] = player;447}448
449// Getting actions450char string[MAX_LENGTH];451int s = 0;452while (fgets(string, MAX_LENGTH, fileIn) != NULL) {453s++;454trim(string);455actions(string, players, &m, fileIn, fileOut);456}457
458
459// Checking if amount of actions satisfies the condition460if (s > 1000) {461error(fileIn, fileOut);462}463
464// Counting power of each Team465Team powers[n];466for (int i = 0; i < n; i++) {467powers[i].number = i;468powers[i].power = 0;469}470for (int i = 0; i < m; i++) {471Player player = players[i];472if (player.active) {473powers[player.teamNumber].power += player.power;474}475}476
477// Getting Team with the biggest amount of power478qsort(powers, n, sizeof(Team), teamCmp);479if (powers[n - 1].power == powers[n - 2].power) {480fprintf(fileOut, "It's a tie\n");481} else {482fprintf(fileOut, "The chosen wizard is %s\n", captains[powers[n - 1].number]);483}484
485// Closing files486fclose(fileIn);487fclose(fileOut);488
489return 0;490}
491
492