На второй неделе обучения по курсу Computer Science CS50 (Harvard) после выполнения всех индивидуальных заданий мы переходим к лабораторной работе по языку C, которую нужно выполнять в группе. Это будет интересная задача — написать код игры «Эрудит» (Scrabble.с). Суть задания: игроки придумывают слова, которые набирают разное количество очков в зависимости от букв в этом слове, при этом каждой букве приписывается разное количество очков от 1 до 10 и затем эти очки складываются (сумма очков букв дает общее количество очков в слове).
Для этой задачи используется следующая таблица соответствий букв и баллов:
A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
1 | 3 | 3 | 2 | 1 | 4 | 2 | 4 | 1 | 8 | 5 | 1 | 3 | 1 | 1 | 3 | 10 | 1 | 1 | 1 | 1 | 4 | 4 | 8 | 4 | 10 |
*Любой символ, кроме буквы, получает ноль баллов; большие и маленькие буквы оцениваются одинаковым количеством символов.
Игровой процесс: каждый игрок вводит слово, программа рассчитывает количество баллов по каждому слову и выигрывает тот, у кого сумма баллов получилась больше.
Результат игры: после того, как оба игрока введут по слову, компьютер выводит номер выигравшего игрока («Player x wins!«). Если получилась ничья, выводится сообщение «Tie!» (ничья).
Решение (Игроглаз)
#include <stdio.h> #include <ctype.h> int scrabble (char *input, int *AZ); int main() { int AZ[] = {1,3,3,2,1,4,2,4,1,8,5,1,3,1,1,3,10,1,1,1,1,4,4,8,4,10}; char input[1000]; int p1_score, p2_score; printf("Player 1: "); p1_score = scrabble (input, AZ); printf("Player 2: "); p2_score = scrabble (input, AZ); if (p1_score > p2_score) printf("Player 1 wins!"); else if (p1_score < p2_score) printf("Player 2 wins!"); else printf("Tie!"); getchar(); getchar(); return 0; } int scrabble (char *input, int *AZ) { int i, x; int score = 0; for (i = 0; ; i++) { scanf ("%c", &input[i]); if (input[i] == '\n') break; // end input when user press 'Enter' // to count score - 1st make letter uppercase if (input[i] >= 'a' && input[i] <= 'z') input[i] = toupper(input[i]); // count only letters (ignore numbers, punctuation marks etc) if (input[i] >= 'A' && input[i] <= 'Z') { // get the ordinal index of letter x = (int)input[i] - 65; // get score from according index from score array score += AZ[x]; } } return score; }
Решение (Штукенция)
Долго я решала эту задачу, и для начала сделала программу без дополнительных функций, так как мне так проще было думать. В итоге первое решение получилось не слишком элегантным, длинным, но зато рабочим.
#include <cs50.h> #include <stdio.h> #include <ctype.h> #include <string.h> #include <stdlib.h> int main(void) { // Create array with the point values of each of 26 letters int values[26]={1,3,3,2,1,4,2,4,1,8,5,1,3,1,1,3,10,1,1,1,1,4,4,8,4,10}; // Get users input of word: printf("Player 1: "); string player1 = get_string(""); printf("Player 2: "); string player2 = get_string(""); // Turn characters from plaintxtx to ciphertext with function char c1; // character from user input player1 int n1 = 0; // value of letter player1 char c2; // character from user input player1 int n2 = 0; // value of letter player1 int sum1=0; // sum of letters values player 1 int sum2=0; // sum of letters values player 2 int textlen1=strlen(player1); int textlen2=strlen(player2); // Count sum of values for letters from 1 player int c_asci_1=0; // ASCII number of player 1 char LETTER (A->65) int c_asci_2=0; // ASCII number of player 2 char LETTER (A->65) int num_letter_1=0; // index of player 1 letter in alphabet int num_letter_2=0; // index of player 2 letter in alphabet int i=0; int j=0; for (i=0; i<=(textlen1-1); i++) // sum char by char values of letters player 1 { c1 = player1[i]; int check_c_1 = isalpha(c1); // check if char is letter if (check_c_1!=0) // if char of player 1 is letter { int check_upper_1 = isupper(c1); // check if char is uppercase if (check_upper_1>0) { c_asci_1 = (c1); // convert char LETTER to int ASCII number (A->65) num_letter_1=(c_asci_1-65); // find numer of upper letter in alphabet (index) } else if (check_upper_1==0) { c_asci_1 = (c1); num_letter_1=(c_asci_1-97); // convert char LETTER to int ASCII number (a->97) } n1=values[num_letter_1]; // asign value for letter sum1+=n1; } } for (j=0; j<=(textlen2-1); j++) // sum char by char values of letters player 2 { c2 = player2[j]; int check_c_2 = isalpha(c2); // check if char is letter if (check_c_2!=0) // if char of player 2 is letter { int check_upper_2 = isupper(c2); // check if char is uppercase if (check_upper_2>0) { c_asci_2 = (c2); // convert char LETTER to int ASCII number (A->65) num_letter_2=(c_asci_2-65); // find numer of upper letter in alphabet (index) } else if (check_upper_2==0) { c_asci_2 = (c2); num_letter_2=(c_asci_2-97); // convert char LETTER to int ASCII number (a->97) } n2=values[num_letter_2]; // asign value for letter sum2+=n2; } } if (sum1>sum2) { printf("Player 1 wins!\n"); } else if (sum1<sum2) { printf("Player 2 wins!\n"); } else if (sum1==sum2) { printf("Tie!\n"); } return 0; }
Далее я решила реализовать этот код более компактно при помощи функции compute_score()
, как требовалось в задании. В итоге код получился в несколько раз короче, видимо в этом и есть главная польза функций.
#include <cs50.h> #include <stdio.h> #include <ctype.h> #include <string.h> #include <stdlib.h> int compute_score(int c, int n, int values[]); int main(void) { // Create array with the point values of each of 26 letters int values[26] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10}; // Get users input of word: printf("Player 1: "); string player1 = get_string(""); printf("Player 2: "); string player2 = get_string(""); // Turn characters from plaintxtx to ciphertext with function char c; // character from user input int n = 0; // value of letter int sum1 = 0; // sum of letters values player 1 int sum2 = 0; // sum of letters values player 2 int textlen1 = strlen(player1); int textlen2 = strlen(player2); int i = 0; int n1 = 0; for (i = 0; i <= (textlen1 - 1); i++) // sum char by char values of letters player 1 { c = player1[i]; n1 = compute_score(c, n, values); sum1 += n1; } int j = 0; int n2 = 0; for (j = 0; j <= (textlen2 - 1); j++) // sum char by char values of letters player 2 { c = player2[j]; n2 = compute_score(c, n, values); sum2 += n2; } if (sum1 > sum2) { printf("Player 1 wins!\n"); } else if (sum1 < sum2) { printf("Player 2 wins!\n"); } else if (sum1 == sum2) { printf("Tie!\n"); } return 0; } int compute_score(int c, int n, int values[]) { // Count sum of values for letters from 1 player int c_asci = 0; // ASCII number of player 1 char LETTER (A->65) int num_letter = 0; // index of player 1 letter in alphabet int check_c = isalpha(c); // check if char is letter if (check_c != 0) // if char of player 1 is letter { int check_upper = isupper(c); // check if char is uppercase if (check_upper > 0) { c_asci = (c); // convert char LETTER to int ASCII number (A->65) num_letter = (c_asci - 65); // find numer of upper letter in alphabet (index) } else if (check_upper == 0) { c_asci = (c); num_letter = (c_asci - 97); // convert char LETTER to int ASCII number (a->97) } n = values[num_letter]; // asign value for letter } return n; }
Сыграем несколько раз, чтобы проверить правильность кода программы:
Что вы поняли, пока выполняли это задание?