Pull to refresh

Автономер на четырех языках. Часть 2

Reading time17 min
Views4.6K

Что такое 8037?


Это небольшая математическая игра: вы идете по улице, и просто считаете сумму цифр в автомобильных номерах. Эту игру мы реализуем в консольном варианте, на четырех языках: Swift, Objective-C, Java и C#.


В первой части мы написали часть приложения, которая спрашивает у пользователя ответ пока тот не введет слово для выхода из приложения. Как резонно заметили в комментариях, в таком случае правильнее все-таки использовать цикл вместо рекурсии. Поэтому первое, что мы сделаем — уберем рекурсию и напишем вместо нее цикл в методе startGame.


Swift:


func startGame() {
    var inputWord: String
    repeat {
        print(GreetingMessage.replacingOccurrences(of: ExitWordPlaceholder, with: self.exitWord))
        inputWord = readLine() ?? ""
    } while check(inputWord: inputWord)
}

private func check(inputWord: String) -> Bool {
    let isExitWord = (inputWord == self.exitWord)
    print(isExitWord ? GoodByeMessage : InputAcceptMessage.replacingOccurrences(of: InputWordPlaceholder, with: inputWord))
    return !isExitWord
}

Objective-C:


- (void)startGame {
    NSString *inputWord;

    do {
        NSLog(GreetingMessage, self.exitWord);
        inputWord = [self readLine];
    } while ([self checkInputWord:inputWord]);
}

- (BOOL)checkInputWord:(NSString *)inputWord {
    BOOL isExitWord = [inputWord isEqualToString:self.exitWord];
    isExitWord ? NSLog(@"%@", GoodByeMessage) : NSLog(InputAcceptMessage, inputWord);
    return !isExitWord;
}

Java:


void startGame() {
    String inputWord;

    do {
        System.out.println(String.format(GreetingMessage, exitWord));
        inputWord = readLine();
    } while (checkInputWord(inputWord));
}

private boolean checkInputWord(String inputWord) {
    boolean isExitWord = inputWord.equals(exitWord);
    System.out.println(isExitWord ? GoodByeMessage : String.format(InputAcceptMessage, inputWord));
    return !isExitWord;
}

C#:


public void startGame()
{
    string inputWord;
    do
    {
        Console.WriteLine(string.Format(GreetingMessage, exitWord));
        inputWord = Console.ReadLine();
    }
    while (checkInputWord(inputWord));
}

bool checkInputWord(string inputWord)
{
    bool isExitWord = inputWord.Equals(exitWord);
    Console.WriteLine(isExitWord ? GoodByeMessage : string.Format(InputAcceptMessage, inputWord));
    return !isExitWord;
}

Ну а дальше — мы, наконец, создадим класс нашей игры (как вы помните, мы специально создавали интерфейс (протокол) Game, который мы должны реализовать в нашем классе):


class Game8037: Game {

    // MARK: - Game

    func greet(with exitWord: String) {

    }

    func check(userAnswer: String) {

    }

}

Оставим пока что методы протокола пустыми, и займемся организацией функциональности класса. В первую очередь нам понадобится enum с уровнями сложности:


private enum Level: String {
    case easy
    case normal
    case hard1
    case hard2

    func forSelect() -> String {
        return LevelForSelect.replacingOccurrences(of: LevelPlaceholder, with: self.rawValue)
                .replacingOccurrences(of: LevelNumberPlaceholder, with: "\(self.hashValue+1)")
    }
}

В enum мы добавили метод forSelect() он будет для каждого уровня сложности создавать строку вида 1 - easy (номер уровня и его название). Это нам пригодится для предложения пользователю выбрать уровень сложности. Дальше нам понадобятся два свойства которые будут содержать в себе выбранный уровень и правильный ответ на задание:


private var level: Level
private var result: UInt32

Теперь мы можем написать наш инициализатор:


init?() {
    self.result = 0
    let levels = Level.easy.forSelect() + Level.normal.forSelect() + Level.hard1.forSelect() + Level.hard2.forSelect()
    print(StartGreeting.replacingOccurrences(of: LevelsPlaceholder, with: levels))

    let selectedLevel = readLine() ?? ""
    switch selectedLevel {
    case "\(Level.easy.hashValue+1)", Level.easy.rawValue:
        self.level = .easy
    case "\(Level.normal.hashValue+1)", Level.normal.rawValue:
        self.level = .normal
    case "\(Level.hard1.hashValue+1)", Level.hard1.rawValue:
        self.level = .hard1
    case "\(Level.hard2.hashValue+1)", Level.hard2.rawValue:
        self.level = .hard2
    default:
        print(ErrorLevelMessage)
        return nil
    }
}

Как видите, для начала, мы задаем значение по-умолчанию для свойства result (оно у нас пока что хранит в себе ноль). Дальше мы формируем информационную строку для пользователя о необходимости выбрать уровень сложности. В консоли это выглядит так:



Ну и потом, мы считываем введенный пользователем уровень сложности и, если он корректен — сохраняем его в свойстве level.


Теперь нам понадобится метод расчета правильного ответа на задание в зависимости от уровня:


private func result(with level: Level, and randomizer: Randomizer) -> UInt32 {
    let result: UInt32

    switch level {
    case .easy:
        result = randomizer.firstNumber + randomizer.secondNumber + randomizer.thirdNumber + randomizer.fourthNumber
    case .normal:
        result = randomizer.firstNumber*10 + randomizer.secondNumber + randomizer.thirdNumber*10 + randomizer.fourthNumber
    case .hard1:
        let firstNumber = (randomizer.firstNumber == 0) ? 1 : randomizer.firstNumber
        let secondNumber = (randomizer.secondNumber == 0) ? 1 : randomizer.secondNumber
        let thirdNumber = (randomizer.thirdNumber == 0) ? 1 : randomizer.thirdNumber
        let fourthNumber = (randomizer.fourthNumber == 0) ? 1 : randomizer.fourthNumber
        result = firstNumber * secondNumber * thirdNumber * fourthNumber
    case .hard2:
        result = (randomizer.firstNumber*10 + randomizer.secondNumber) * (randomizer.thirdNumber*10 + randomizer.fourthNumber)
    }

    return result
}

И, наконец, нужно реализовать методы протокола Game.
Метод greet(with exitWord: String):


func greet(with exitWord: String) {
    let randomizer = Randomizer()
    self.result = self.result(with: self.level, and: randomizer)
    let task = BaseGreeting.replacingOccurrences(of: FirstNumberPlaceholder, with: "\(randomizer.firstNumber)")
            .replacingOccurrences(of: SecondNumberPlaceholder, with: "\(randomizer.secondNumber)")
            .replacingOccurrences(of: ThirdNumberPlaceholder, with: "\(randomizer.thirdNumber)")
            .replacingOccurrences(of: FourthNumberPlaceholder, with: "\(randomizer.fourthNumber)")

    print(TaskMessage.replacingOccurrences(of: TaskPlaceholder, with: task)
            .replacingOccurrences(of: ExitWordPlaceholder, with: exitWord))
}

Тут мы создаем новый Randomizer и рассчитываем правильный ответ для текущего уровня сложности. После чего показываем пользователю задание.


Метод check(userAnswer: String):


func check(userAnswer: String) {
    if self.result == UInt32(userAnswer) {
        print(CorrectMessage)
    } else {
        print(WrongMessage)
    }
}

Тут все просто: мы просто сравниваем правильный ответ с тем, что ввел пользователь и выводим информационное сообщение на экран.


Итак полный текст класса в Swift выглядит так:


private let LevelsPlaceholder = "{levels}"
private let LevelNumberPlaceholder = "{levelNumber}"
private let LevelPlaceholder = "{level}"

private let FirstNumberPlaceholder = "{firstNumber}"
private let SecondNumberPlaceholder = "{secondNumber}"
private let ThirdNumberPlaceholder = "{thirdNumber}"
private let FourthNumberPlaceholder = "{fourthNumber}"

private let ExitWordPlaceholder = "{exitWord}"
private let TaskPlaceholder = "{taskPlaceholder}"

private let StartGreeting = "Hello, let's play. Please select difficulty level:\(LevelsPlaceholder)"
private let LevelForSelect = "\n\(LevelNumberPlaceholder) - \(LevelPlaceholder)"
private let BaseGreeting = "\(FirstNumberPlaceholder) \(SecondNumberPlaceholder) \(ThirdNumberPlaceholder) \(FourthNumberPlaceholder)"
private let TaskMessage = "The next task is \(TaskPlaceholder)\n(enter \"\(ExitWordPlaceholder)\" for exit)"
private let CorrectMessage = "Absolutely right.\n"
private let WrongMessage = "Sorry, you made a mistake. Try again.\n"
private let ErrorLevelMessage = "Sorry, you have selected wrong level. Good bye.\n"

class Game8037: Game {

    private enum Level: String {
        case easy
        case normal
        case hard1
        case hard2

        func forSelect() -> String {
            return LevelForSelect.replacingOccurrences(of: LevelPlaceholder, with: self.rawValue)
                .replacingOccurrences(of: LevelNumberPlaceholder, with: "\(self.hashValue+1)")
        }
    }

    private var level: Level
    private var result: UInt32

    init?() {
        self.result = 0
        let levels = Level.easy.forSelect() + Level.normal.forSelect() + Level.hard1.forSelect() + Level.hard2.forSelect()
        print(StartGreeting.replacingOccurrences(of: LevelsPlaceholder, with: levels))

        let selectedLevel = readLine() ?? ""
        switch selectedLevel {
        case "\(Level.easy.hashValue+1)", Level.easy.rawValue:
            self.level = .easy
        case "\(Level.normal.hashValue+1)", Level.normal.rawValue:
            self.level = .normal
        case "\(Level.hard1.hashValue+1)", Level.hard1.rawValue:
            self.level = .hard1
        case "\(Level.hard2.hashValue+1)", Level.hard2.rawValue:
            self.level = .hard2
        default:
            print(ErrorLevelMessage)
            return nil
        }
    }

    private func result(with level: Level, and randomizer: Randomizer) -> UInt32 {
        let result: UInt32

        switch level {
        case .easy:
            result = randomizer.firstNumber + randomizer.secondNumber + randomizer.thirdNumber + randomizer.fourthNumber
        case .normal:
            result = randomizer.firstNumber*10 + randomizer.secondNumber + randomizer.thirdNumber*10 + randomizer.fourthNumber
        case .hard1:
            let firstNumber = (randomizer.firstNumber == 0) ? 1 : randomizer.firstNumber
            let secondNumber = (randomizer.secondNumber == 0) ? 1 : randomizer.secondNumber
            let thirdNumber = (randomizer.thirdNumber == 0) ? 1 : randomizer.thirdNumber
            let fourthNumber = (randomizer.fourthNumber == 0) ? 1 : randomizer.fourthNumber
            result = firstNumber * secondNumber * thirdNumber * fourthNumber
        case .hard2:
            result = (randomizer.firstNumber*10 + randomizer.secondNumber) * (randomizer.thirdNumber*10 + randomizer.fourthNumber)
        }

        return result
    }

    // MARK: - Game

    func greet(with exitWord: String) {
        let randomizer = Randomizer()
        self.result = self.result(with: self.level, and: randomizer)
        let task = BaseGreeting.replacingOccurrences(of: FirstNumberPlaceholder, with: "\(randomizer.firstNumber)")
            .replacingOccurrences(of: SecondNumberPlaceholder, with: "\(randomizer.secondNumber)")
            .replacingOccurrences(of: ThirdNumberPlaceholder, with: "\(randomizer.thirdNumber)")
            .replacingOccurrences(of: FourthNumberPlaceholder, with: "\(randomizer.fourthNumber)")

        print(TaskMessage.replacingOccurrences(of: TaskPlaceholder, with: task)
            .replacingOccurrences(of: ExitWordPlaceholder, with: exitWord))
    }

    func check(userAnswer: String) {
        if self.result == UInt32(userAnswer) {
            print(CorrectMessage)
        } else {
            print(WrongMessage)
        }
    }

}

Реализация этого же класса в Objective-C:


// файл заголовка Game8037.h
@interface Game8037 : NSObject <Game>

@end

// файл реализации GameStart.m
const NSString *EasyLevelNumber = @"1";
const NSString *NormalLevelNumber = @"2";
const NSString *Hard1LevelNumber = @"3";
const NSString *Hard2LevelNumber = @"4";

const NSString *EasyLevelName = @"easy";
const NSString *NormalLevelName = @"normal";
const NSString *Hard1LevelName = @"hard1";
const NSString *Hard2LevelName = @"hard2";

const NSString *StartGreeting = @"Hello, let's play. Please select difficulty level:%@";
const NSString *LevelForSelect = @"\n%@ - %@";
const NSString *BaseGreeting = @"%i %i %i %i";
const NSString *TaskMessage = @"The next task is %@\n(enter \"%@\" for exit)";
const NSString *CorrectMessage = @"Absolutely right.\n";
const NSString *WrongMessage = @"Sorry, you made a mistake. Try again.\n";
const NSString *ErrorLevelMessage = @"Sorry, you have selected wrong level. Good bye.\n";

typedef enum {
    LevelEasy,
    LevelNormal,
    LevelHard1,
    LevelHard2
} Level;

@interface Game8037()

@property (assign, nonatomic) Level level;
@property (assign, nonatomic) NSInteger result;

@end

@implementation Game8037

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.result = 0;
        NSString *levels = [NSString stringWithFormat:@"%@%@%@%@",
                            [self levelForSelect:LevelEasy],
                            [self levelForSelect:LevelNormal],
                            [self levelForSelect:LevelHard1],
                            [self levelForSelect:LevelHard2]];

        NSLog(StartGreeting, levels);
        NSString *selectedLevel = [self readLine];
        if ([selectedLevel isEqualToString:EasyLevelNumber] || [selectedLevel isEqualToString:EasyLevelName]) {
            self.level = LevelEasy;
        } else if ([selectedLevel isEqualToString:NormalLevelNumber] || [selectedLevel isEqualToString:NormalLevelName]) {
            self.level = LevelNormal;
        } else if ([selectedLevel isEqualToString:Hard1LevelNumber] || [selectedLevel isEqualToString:Hard1LevelName]) {
            self.level = LevelHard1;
        } else if ([selectedLevel isEqualToString:Hard2LevelNumber] || [selectedLevel isEqualToString:Hard2LevelName]) {
            self.level = LevelHard2;
        } else {
            NSLog(@"%@", ErrorLevelMessage);
            return nil;
        }
    }
    return self;
}

- (NSString *)levelForSelect:(Level)level {
    NSString *levelNumber;
    NSString *levelName;

    switch (level) {
        case LevelEasy:
            levelNumber = EasyLevelNumber;
            levelName = EasyLevelName;
            break;
        case LevelNormal:
            levelNumber = NormalLevelNumber;
            levelName = NormalLevelName;
            break;
        case LevelHard1:
            levelNumber = Hard1LevelNumber;
            levelName = Hard1LevelName;
            break;
        case LevelHard2:
            levelNumber = Hard2LevelNumber;
            levelName = Hard2LevelName;
            break;
    }

    return [NSString stringWithFormat:LevelForSelect, levelNumber, levelName];
}

- (NSInteger)resultWithLevel:(Level)level andRandomizer:(Randomizer *)randomizer {
    NSInteger result = 0;

    switch (level) {
        case LevelEasy:
            result = randomizer.firstNumber + randomizer.secondNumber + randomizer.thirdNumber + randomizer.fourthNumber;
            break;
        case LevelNormal:
            result = randomizer.firstNumber*10 + randomizer.secondNumber + randomizer.thirdNumber*10 + randomizer.fourthNumber;
            break;
        case LevelHard1:
            result = (randomizer.firstNumber == 0 ? 1 : randomizer.firstNumber) * (randomizer.secondNumber == 0 ? 1 : randomizer.secondNumber) * (randomizer.thirdNumber == 0 ? 1 : randomizer.thirdNumber) * (randomizer.fourthNumber == 0 ? 1 : randomizer.fourthNumber);
            break;
        case LevelHard2:
            result = (randomizer.firstNumber*10 + randomizer.secondNumber) * (randomizer.thirdNumber*10 + randomizer.fourthNumber);
            break;
    }

    return result;
}

- (NSString *)descriptionOfLevel:(Level)level {
    NSString *result = @"";

    switch (level) {
        case LevelEasy:
            result = EasyLevelName;
            break;
        case LevelNormal:
            result = NormalLevelName;
            break;
        case LevelHard1:
            result = Hard1LevelName;
            break;
        case LevelHard2:
            result = Hard2LevelName;
            break;
    }

    return result;
}

- (NSString *)readLine {
    char inputValue;
    scanf("%s", &inputValue);
    return [NSString stringWithUTF8String:&inputValue];
}

#pragma mark - Game

- (void)greetWithExitWord:(NSString *)exitWord {
    Randomizer *randomizer = [[Randomizer alloc] init];
    self.result = [self resultWithLevel:self.level andRandomizer:randomizer];
    NSString *task = [NSString stringWithFormat:BaseGreeting,
                      randomizer.firstNumber,
                      randomizer.secondNumber,
                      randomizer.thirdNumber,
                      randomizer.fourthNumber];

    NSLog(TaskMessage, task, exitWord);
}

- (void)checkUserAnswer:(NSString *)userAnswer {
    if (self.result == [userAnswer integerValue]) {
        NSLog(@"%@", CorrectMessage);
    } else {
        NSLog(@"%@", WrongMessage);
    }
}

@end

Java:


public class Game8037 implements Game {

    private static final String EasyLevelNumber = "1";
    private static final String NormalLevelNumber = "2";
    private static final String Hard1LevelNumber = "3";
    private static final String Hard2LevelNumber = "4";

    private static final String EasyLevelName = "easy";
    private static final String NormalLevelName = "normal";
    private static final String Hard1LevelName = "hard1";
    private static final String Hard2LevelName = "hard2";

    private static final String StartGreeting = "Hello, let's play. Please select difficulty level:%s";
    private static final String LevelForSelect = "\n%s - %s";
    private static final String BaseGreeting = "%s %s %s %s";
    private static final String TaskMessage = "The next task is %s\n(enter \"%s\" for exit)";
    private static final String CorrectMessage = "Absolutely right.\n";
    private static final String WrongMessage = "Sorry, you made a mistake. Try again.\n";
    private static final String ErrorLevelMessage = "Sorry, you have selected wrong level. Good bye.\n";

    private enum Level {
        Easy {
            public String toString() {
                return EasyLevelName;
            }
        },
        Normal {
            public String toString() {
                return NormalLevelName;
            }
        },
        Hard1 {
            public String toString() {
                return Hard1LevelName;
            }
        },
        Hard2 {
            public String toString() {
                return Hard2LevelName;
            }
        }
    }

    private Level level;
    private int result;

    private Game8037(Level level) {
        this.level = level;
        this.result = 0;
    }

    @Nullable
    public static Game8037 Create() {
        String levels = String.format("%s%s%s%s", levelForSelect(Level.Easy), levelForSelect(Level.Normal), levelForSelect(Level.Hard1), levelForSelect(Level.Hard2));
        System.out.println(String.format(StartGreeting, levels));

        Game8037 game8037;

        String selectedLevel = readLine();
        switch (selectedLevel) {
            case EasyLevelNumber:
            case EasyLevelName:
                game8037 = new Game8037(Level.Easy);
                break;
            case NormalLevelNumber:
            case NormalLevelName:
                game8037 = new Game8037(Level.Normal);
                break;
            case Hard1LevelNumber:
            case Hard1LevelName:
                game8037 = new Game8037(Level.Hard1);
                break;
            case Hard2LevelNumber:
            case Hard2LevelName:
                game8037 = new Game8037(Level.Hard2);
                break;
            default:
                game8037 = null;
                System.out.println(ErrorLevelMessage);
                break;
        }

        return game8037;
    }

    private static String levelForSelect(Level level) {
        String levelNumber = "";
        String levelName = "";

        switch (level) {
            case Easy:
                levelNumber = EasyLevelNumber;
                levelName = EasyLevelName;
                break;
            case Normal:
                levelNumber = NormalLevelNumber;
                levelName = NormalLevelName;
                break;
            case Hard1:
                levelNumber = Hard1LevelNumber;
                levelName = Hard1LevelName;
                break;
            case Hard2:
                levelNumber = Hard2LevelNumber;
                levelName = Hard2LevelName;
                break;
        }

        return String.format(LevelForSelect, levelNumber, levelName);
    }

    private int resultWithLevelAndRandomizer(Level level, Randomizer randomizer) {
        int result = 0;

        switch (level) {
            case Easy:
                result = randomizer.firstNumber + randomizer.secondNumber + randomizer.thirdNumber + randomizer.fourthNumber;
                break;
            case Normal:
                result = randomizer.firstNumber*10 + randomizer.secondNumber + randomizer.thirdNumber*10 + randomizer.fourthNumber;
                break;
            case Hard1:
                int firstNumber = (randomizer.firstNumber == 0) ? 1 : randomizer.firstNumber;
                int secondNumber = (randomizer.secondNumber == 0) ? 1 : randomizer.secondNumber;
                int thirdNumber = (randomizer.thirdNumber == 0) ? 1 : randomizer.thirdNumber;
                int fourthNumber = (randomizer.fourthNumber == 0) ? 1 : randomizer.fourthNumber;
                result = firstNumber * secondNumber * thirdNumber * fourthNumber;
                break;
            case Hard2:
                result = (randomizer.firstNumber*10 + randomizer.secondNumber) * (randomizer.thirdNumber*10 + randomizer.fourthNumber);
                break;
        }

        return result;
    }

    static private String readLine() {
        java.util.Scanner scanner = new java.util.Scanner(System.in);
        return scanner.next();
    }

    @Override
    public void greet(String exitWord) {
        Randomizer randomizer = new Randomizer();
        result = resultWithLevelAndRandomizer(level, randomizer);

        String task = String.format(BaseGreeting, randomizer.firstNumber, randomizer.secondNumber, randomizer.thirdNumber, randomizer.fourthNumber);
        System.out.println(String.format(TaskMessage, task, exitWord));
    }

    @Override
    public void checkUserAnswer(String userAnswer) {
        int answer;

        try {
            answer = Integer.parseInt(userAnswer);
        } catch (Exception e) {
            System.out.println(WrongMessage);
            return;
        }

        if (result == answer) {
            System.out.println(CorrectMessage);
        } else {
            System.out.println(WrongMessage);
        }
    }
}

C#:


public class Game8037 : IGame
{
    const string EasyLevelNumber = "1";
    const string NormalLevelNumber = "2";
    const string Hard1LevelNumber = "3";
    const string Hard2LevelNumber = "4";

    const string EasyLevelName = "easy";
    const string NormalLevelName = "normal";
    const string Hard1LevelName = "hard1";
    const string Hard2LevelName = "hard2";

    const string StartGreeting = "Hello, let's play. Please select difficulty level:{0}";
    const string LevelForSelect = "\n{0} - {1}";
    const string BaseGreeting = "{0} {1} {2} {3}";
    const string TaskMessage = "The next task is {0}\n(enter \"{1}\" for exit)";
    const string CorrectMessage = "Absolutely right.\n";
    const string WrongMessage = "Sorry, you made a mistake. Try again.\n";
    const string ErrorLevelMessage = "Sorry, you have selected wrong level. Good bye.\n";

    enum Level { Easy, Normal, Hard1, Hard2 };

    Level level;
    int result;

    private Game8037(Level level)
    {
        this.level = level;
        result = 0;
    }

    public static Game8037 Create()
    {
        string levels = string.Format("{0}{1}{2}{3}", levelForSelect(Level.Easy), levelForSelect(Level.Normal), levelForSelect(Level.Hard1), levelForSelect(Level.Hard2));
        Console.WriteLine(string.Format(StartGreeting, levels));

        Game8037 game8037;

        string selectedLevel = Console.ReadLine();
        switch (selectedLevel)
        {
            case EasyLevelNumber:
            case EasyLevelName:
                game8037 = new Game8037(Level.Easy);
                break;
            case NormalLevelNumber:
            case NormalLevelName:
                game8037 = new Game8037(Level.Normal);
                break;
            case Hard1LevelNumber:
            case Hard1LevelName:
                game8037 = new Game8037(Level.Hard1);
                break;
            case Hard2LevelNumber:
            case Hard2LevelName:
                game8037 = new Game8037(Level.Hard2);
                break;
            default:
                game8037 = null;
                Console.WriteLine(ErrorLevelMessage);
                break;
        }

        return game8037;
    }

    static string levelForSelect(Level level)
    {
        string levelNumber = "";
        string levelName = "";

        switch (level)
        {
            case Level.Easy:
                levelNumber = EasyLevelNumber;
                levelName = EasyLevelName;
                break;
            case Level.Normal:
                levelNumber = NormalLevelNumber;
                levelName = NormalLevelName;
                break;
            case Level.Hard1:
                levelNumber = Hard1LevelNumber;
                levelName = Hard1LevelName;
                break;
            case Level.Hard2:
                levelNumber = Hard2LevelNumber;
                levelName = Hard2LevelName;
                break;
        }

        return string.Format(LevelForSelect, levelNumber, levelName);
    }

    int resultWithLevelAndRandomizer(Level level, Randomizer randomizer)
    {
        int result = 0;

        switch (level)
        {
            case Level.Easy:
                result = randomizer.firstNumber + randomizer.secondNumber + randomizer.thirdNumber + randomizer.fourthNumber;
                break;
            case Level.Normal:
                result = randomizer.firstNumber * 10 + randomizer.secondNumber + randomizer.thirdNumber * 10 + randomizer.fourthNumber;
                break;
            case Level.Hard1:
                int firstNumber = (randomizer.firstNumber == 0) ? 1 : randomizer.firstNumber;
                int secondNumber = (randomizer.secondNumber == 0) ? 1 : randomizer.secondNumber;
                int thirdNumber = (randomizer.thirdNumber == 0) ? 1 : randomizer.thirdNumber;
                int fourthNumber = (randomizer.fourthNumber == 0) ? 1 : randomizer.fourthNumber;
                result = firstNumber* secondNumber * thirdNumber * fourthNumber;
                break;
            case Level.Hard2:
                result = (randomizer.firstNumber * 10 + randomizer.secondNumber) * (randomizer.thirdNumber * 10 + randomizer.fourthNumber);
                break;
        }

        return result;
    }

    string descriptionOfLevel(Level level)
    {
        string result = "";

        switch (level)
        {
            case Level.Easy:
                result = "easy";
                break;
            case Level.Normal:
                result = "normal";
                break;
            case Level.Hard1:
                result = "hard1";
                break;
            case Level.Hard2:
                result = "hard2";
                break;
        }

        return result;
    }

    public void greet(string exitWord)
    {
        Randomizer randomizer = new Randomizer();
        result = resultWithLevelAndRandomizer(level, randomizer);

        string task = string.Format(BaseGreeting, randomizer.firstNumber, randomizer.secondNumber, randomizer.thirdNumber, randomizer.fourthNumber);
        Console.WriteLine(string.Format(TaskMessage, task, exitWord));
    }

    public void checkUserAnswer(string userAnswer)
    {
        int answer;

        try
        {
            answer = int.Parse(userAnswer);
        }
        catch
        {
            Console.WriteLine(WrongMessage);
            return;
        }

        if (result == answer)
        {
            Console.WriteLine(CorrectMessage);
        }
        else
        {
            Console.WriteLine(WrongMessage);
        }
    }
}

В Java и C# есть нюанс при создании объекта класса Game8037. Дело в том, что здесь нет failable инициализаторов, поэтому мы воспользовались статическим методом для создания объекта.


Нам остается добавить создание нашей игры в класс GameStart и воспользоваться методами greet(...) и check(...). Теперь класс GameStart выглядит так.


Swift:


class GameStart {

    private var exitWord: String
    private var game: Game

    init?(with exitWord: String) {
        self.exitWord = exitWord
        if let game = Game8037() {
            self.game = game
        } else {
            return nil
        }
    }

    func startGame() {
        var inputWord: String
        repeat {
            self.game.greet(with: self.exitWord)
            inputWord = readLine() ?? ""
        } while check(inputWord: inputWord)
    }

    private func check(inputWord: String) -> Bool {
        let isExitWord = (inputWord == self.exitWord)
        if isExitWord {
            print(GoodByeMessage)
        } else {
            self.game.check(userAnswer: inputWord)
        }
        return !isExitWord
    }

}

Objective-C:


@interface GameStart()

@property (strong, nonatomic) NSString *exitWord;
@property (strong, nonatomic) id<Game> game;

@end

@implementation GameStart

- (instancetype)initWithExitWord:(NSString *)exitWord {
    self = [super init];
    if (self) {
        self.exitWord = exitWord;
        self.game = [[Game8037 alloc] init];
    }
    return self;
}

- (void)startGame {
    if (self.game) {
        NSString *inputWord;

        do {
            [self.game greetWithExitWord:self.exitWord];
            inputWord = [self readLine];
        } while ([self checkInputWord:inputWord]);
    }
}

- (BOOL)checkInputWord:(NSString *)inputWord {
    BOOL isExitWord = [inputWord isEqualToString:self.exitWord];
    if (isExitWord) {
        NSLog(@"%@", GoodByeMessage);
    } else {
        [self.game checkUserAnswer:inputWord];
    }
    return !isExitWord;
}

- (NSString *)readLine {
    char inputValue;
    scanf("%s", &inputValue);
    return [NSString stringWithUTF8String:&inputValue];
}

@end

Java:


public class GameStart {

    private static final String GreetingMessage = "Please enter your answer (enter \"%s\" for exit):";
    private static final String InputAcceptMessage = "You entered \"%s\".\n";
    private static final String GoodByeMessage = "Good bye.\n";

    private String exitWord;
    private Game game;

    public GameStart(String exitWord) {
        this.exitWord = exitWord;
        this.game = Game8037.Create();
    }

    void startGame() {
        if (game != null) {
            String inputWord;

            do {
                game.greet(exitWord);
                inputWord = readLine();
            } while (checkInputWord(inputWord));
        }
    }

    private boolean checkInputWord(String inputWord) {
        boolean isExitWord = inputWord.equals(exitWord);
        if (isExitWord) {
            System.out.println(GoodByeMessage);
        } else {
            game.checkUserAnswer(inputWord);
        }
        return !isExitWord;
    }

    private String readLine() {
        java.util.Scanner scanner = new java.util.Scanner(System.in);
        return scanner.next();
    }

}

C#:


public class GameStart
{
    const string GreetingMessage = "Please enter your answer (enter \"{0}\" for exit):";
    const string InputAcceptMessage = "You entered \"{0}\".\n";
    const string GoodByeMessage = "Good bye.\n";

    readonly string exitWord;
    readonly IGame iGame;

    public GameStart(string exitWord)
    {
        this.exitWord = exitWord;
        iGame = Game8037.Create();
    }

    public void startGame()
    {
        if (iGame != null)
        {
            string inputWord;
            do
            {
                iGame.greet(exitWord);
                inputWord = Console.ReadLine();
            }
            while (checkInputWord(inputWord));
        }
    }

    bool checkInputWord(string inputWord)
    {
        bool isExitWord = inputWord.Equals(exitWord);
        if (isExitWord)
        {
            Console.WriteLine(GoodByeMessage);
        }
        else
        {
            iGame.checkUserAnswer(inputWord);
        }
        return !isExitWord;
    }
}

Как видите, у нас добавилось свойство game типа Game (или IGame в C#). Также в методе startGame() мы вызываем self.game.greet(...), а в методе check(...)self.game.check(...). Таким образом, в будущем можно будет вместо Game8037 подставить туда любую другую игру, которая реализует наш протокол Game.


Заключение


На этом работа над нашим приложением окончена, исходный код всего этого можно найти здесь. Всем спасибо за внимание, замечания, критику, советы, пожелания. :)

Tags:
Hubs:
Total votes 11: ↑9 and ↓2+7
Comments5

Articles