- PVSM.RU - https://www.pvsm.ru -

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

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

Что такое 8037?

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

В первой части [1] мы написали часть приложения, которая спрашивает у пользователя ответ пока тот не введет слово для выхода из приложения. Как резонно заметили в комментариях, в таком случае правильнее все-таки использовать цикл вместо рекурсии. Поэтому первое, что мы сделаем — уберем рекурсию и напишем вместо нее цикл в методе 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 (оно у нас пока что хранит в себе ноль). Дальше мы формируем информационную строку для пользователя о необходимости выбрать уровень сложности. В консоли это выглядит так:

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

Ну и потом, мы считываем введенный пользователем уровень сложности и, если он корректен — сохраняем его в свойстве 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 %sn(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.

Заключение

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

Автор: s_suhanov

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/java/254950

Ссылки в тексте:

[1] первой части: https://habrahabr.ru/post/326568/

[2] здесь: https://github.com/ssuhanov/8037

[3] Источник: https://habrahabr.ru/post/327168/