2주차가 끝났다.
이번 과제는 간단한 자동차 경주 게임을 구현하는것이다.
요구사항은 아래와 같다.
프로그램 실행 예시는 다음과 같다.
경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)
jay,tiger,lion
시도할 횟수는 몇 회인가요?
3
실행 결과
jay :
tiger : -
lion :
jay :
tiger : --
lion :
jay : -
tiger : ---
lion : -
최종 우승자 : tiger
이전 과제와는 달리, 클래스를 나눌 필요가 있어보였다. 자동차 경주게임이라는건, 일단 자동차가 있어야 할 테고 (Car 클래스), 차를 가지고 게임을 하는룰이라든지, 승리조건, 게임의 순서 등.. 게임이라는 포괄적인 개념으로 RacingGame이라는 클래스가 필요해 보였다. 자동차와, 경주게임이라는 두 개념이 상호작용할 수 있도록 만들어야겠다고 생각했다.
먼저 Car 클래스와 RacingGame 클래스를 만들었다.
자동차는 어떤 상태를 가질까?
먼저 요구사항에서 "각 자동차에 이름을 부여할 수 있다." 라고 했다.
String carName을 만들어 주었다.
자동차는 이동을 할 수 있다. 구현하려는 프로그램을 보면 게임동안의 이동횟수를 기준으로 승리를 판단한다. 이동횟수를 저장할 수 있어야 겠다. int moveCount을 만들어 주었다.
게임을 하려면 일단 차들이 필요하지 않을까?
List<Car> cars를 만들어주었다. ArrayList나 LinkdedList중 무엇으로도 구현할 수 있기에 List로 일단 두었다.
요구사항을 보면 "사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다."고 했다.
int tryCount를 만들어 주었다.
주요고민중 하나는 RacingGame을 어떻게 초기화 시켜야 하나 였다. 사용자가 하는 입력은
1. 쉼표를 기준으로 구분하는 자동차 목록
2. 게임간 몇번의 이동을 할 것인지 이동횟수
2가지이다. 생성자의 파라미터로 자동차목록과 이동횟수를 넣어주는게 게임의 유효성(개체는 생성과 동시에 유효해야 한다)를 충족시켜 주는 것일까에 대한 고민을 하였다. 과제 당시 야구 한국시리즈시즌이어서 네이버에 야구를 검색해서, 어떻게 처리하는지 보았다.
(회고를 적는 현재는 축구를 검색해서 볼 수 있었다.) 네이버에 "한국 축구 일정"을 쳐보면
이렇게 각 경기에 대한 대략 적인 정보가 나온다. 각 경기경기가 하나의 게임 객체라고 볼 수 있는데, 이때, 경기팀, 경기시간, 경기장소 등은 정해져 있는 것을 볼 수 있다.
허나 전력 비교 버튼을 눌러서 확인해 보았을때, 출전 선수 명단은 확정이 되지 않은상태로, 후에 업데이트 하는 방식을 채택하고 있었다. 여기서 영감을 받아, 자동차 경주 게임에서 출전하는 자동차들은 초기화 이후에 지정해주기로 하였다.
또 마찬가지로 이동횟수도 초기화 이후에 지정해주기로 하였다.
쉼표를 기준으로 구분하는 자동차 목록을 사용자로부터 입력받을 때, Car 클래스에서 static 메서드로 받아 <List>Car 타입으로 반환을 해주었다. 처음에는 RacingGame클래스에서 입력값으로부터 자동차 객체를 만들어서 RacingGame의 상태 cars에 저장하려고 했지만 이 방법은 OOP 적이지 않다고 생각한다. 자동차들이 게임에 참가를 해서 경주를 뛰는 것이지, 게임에서 자동차를 만들어서 경주를 뛰는 것이 아니기에 좀 어색하다고 생각한다.
그래서 public static List<Car>Car::createCars(String input) 메서드를 만들었다. 그리고 이 메서드를 호출결과값(List<Car>을 RacingGame의 registerCars(List<Car>) 라는 메서드로 넘겨주기로 했다.
입력을 받았으니 게임을 해야겠다. RacingGame 클래스에서 게임을 하고 게임 결과를 출력해주는 doGame()이라는 메서드를 만들었다. 반복문을 이용해 사용자가 입력한 tryCount만큼 반복하고 각 반복마다, 전진조건을 충족한 RacingGame에 등록된 Car 객체
(List<Car> 중 하나)를 이동시켰다.
또 이동한 횟수마다 Car 클래스의 메서드 printMoveCount()를 호출해서 Jay : --- <- 이런식으로 콘솔에 출력되도록 하였다.
이동 횟수만큼 반복문을 실행한 이후, 이동 횟수가 가장 많은 자동차를 출력하는 함수를 doGame() 내부에서 호출하여 최종 우승자를 콘솔에 출력되도록 하였다.
Application 클래스에 코드를 작성하고 나니 뭔가 이상한 점이 보였다.
public class Application {
public static void main(String[] args) {
RacingGame game = new RacingGame();
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
List<Car> cars = Car.createCars(Console.readLine());
game.registerCars(cars);
System.out.println("시도할 횟수는 몇 회인가요?");
game.setTryCount(Integer.parseInt(Console.readLine()));
game.doGame();
Console.close();
}
게임에 자동차들을 등록하는 함수, 시도할 횟수(이동횟수)를 입력하는 함수, 게임을 실행하는 함수가 보였다.
어플리케이션 클래스까지가 프로그램의 일부고, 코딩의 범위인데, 이 프로그램은 '자동차 경주 프로그램'이다. 간단하게 보자면 사용자가 자동차들, 이동횟수를 입력하고 입력이 끝나면 게임을 수행하여 콘솔에 게임의 결과를 보여준다.
사용자에게 이 프로그램의 과정은 입력 -> 출력 이렇게 보여진다. 그런데 프로그래머 입장에서 사용자에게 입력 -> 출력 이렇게 보여진다고 프로그래머도 그렇게 코드를 짜는게 맞나? Application 클래스에서 입력하는 곳은 2곳인데, 출력을 담당하는 곳은 없네, doGame메서드 안에 게임프로세스와 출력이 공존하네. 아니 왜 입력은 따로 있으면서 게임을 하는것과 게임의 결과는 같은곳에 있는 것이지? 입력도 doGame에 넣어서 Application 클래스에서 game.doGame()만 호출하면? 그렇다면 public이라는 접근제어자가 무슨 소용이지? 나눠야겠다! 라고 생각해서 doGame() -> doGame(), printResult() 로 메서드를 두개 쪼개게 되었다.
쪼개고 나니 각 메서드들의 책임이 분산되었다! 이번과제는 OOP에 대해 더욱 생각할 수 있게 된 과제 였던 것 같다.
과제가 끝난후 스터디원분들과 처음으로 대면하여 코드리뷰를 진행하였다. 내가 짠 코드를 남들에게 보여주며 설명하는 경험이 적어 조금 긴장되기도 했지만 재미있었다. 코드의 전반적인 흐름과 왜 이런식으로 짰는지를 설명하고 리뷰를 받았다. 꽤 건설적인 피드백을 받을 수 있었다. 경주 게임에서 전진하는 조건은 게임안에 있는 조건이니 Car 클래스의 moveOrStay()메서드 안이 아닌 RacingGame으로 빼면 좋겠다는 피드백이 있었는데, 내가 생각하지 못한 점을 깨달게 해주어 좋았다. 다른 스터디원분들의 코드를 보면서도 많은 점을 배울 수 있었고, 자극이 되었다.
과제를 구현하면서 StringTokenizer의 내부구현을 파헤쳐보았고 JUnit에 대해서도 학습하게 되었으며, Git에 대해 더 잘 알고 활용할 수 있게되었다.만 어째서인지 당초 목표했던 깊이있는 학습후 정보공유를 하는 것에 있어 소홀하지 않았나 싶다. 이제 3주차다. 프리코스를 통해 내가 목표했던 것들에 충실할 수 있어야겠다.
oop정리1 - OOP definition, 4 main feature (0) | 2025.01.25 |
---|---|
우아한테크코스 웹 백엔드 7기 프리코스 4주차 회고 (0) | 2024.12.06 |
우아한테크코스 웹 백엔드 7기 프리코스 3주차 회고 (0) | 2024.12.05 |
우아한테크코스 웹 백엔드 7기 프리코스 1주차 회고 (0) | 2024.10.21 |
포큐아카데미 COMP2200 C 언매니지드 프로그래밍 수강후기 (1) | 2024.08.24 |
댓글 영역