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

от автора

Что такое 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.

Заключение

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

ссылка на оригинал статьи https://habrahabr.ru/post/327168/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *