본문 바로가기
백엔드

자동차 경주 게임 - 객체지향

by 육빔 2024. 3. 23.
728x90
반응형

 

https://techblog.woowahan.com/2502/

 

생각하라, 객체지향처럼 | 우아한형제들 기술블로그

{{item.name}} 2년차 쪼랩이가 객체지향을 처음으로 접하고 공부를 하면서 나름대로 정리해보았습니다. 시작 인사 안녕하세요. B2B시스템개발팀 김승영입니다. 먼저, 이 글은 지난 02월에 작성되어

techblog.woowahan.com

 

저번 로또를 작성하면서 내 한계를 느끼고 객체지향 관련 찾아보다가 최고의 설명을 찾았다.

이번엔 위 내용을 토대로 배운 것을 활용해보려고 한다.

 

https://github.com/woowacourse/java-racingcar-precourse

 

GitHub - woowacourse/java-racingcar-precourse: 자동차 경주 게임 미션을 위한 저장소

자동차 경주 게임 미션을 위한 저장소. Contribute to woowacourse/java-racingcar-precourse development by creating an account on GitHub.

github.com

문제 설명이다.

객체지향적으로 바라보고 설계하고 구현하자

 

 

1. 객체들로 구성된 작은 세상으로 바라보자

 

일단 객체를 사용자, 게임기, 자동차, 자동차 이용자 총 4개로 분리시켰다. 

 

2. 객체들 간의 관계

 

사용자는 게임기에서 자동차 이용자와 라운드 횟수를 입력을 할 수 있다 

게임기는 자동차 이용자에게 자동차를 부여할 수 있다. 

또 게임을 시작시켜서 라운드 횟수만큼 진행시킬 수 있다.

 

3. 객체들의 분류

  • 사용자 객체는 ‘사용자 타입’의 인스턴스
  • 게임기 객체는 ‘게임기 타입’의 인스턴스
  • 자동차 이용자 모두 ‘자동차 이용자 타입’의 인스턴스
  • 자동차 객체는 ‘자동차 타입’의 인스턴스

4. 타입 간의 관계

 

 게임기 ------- 자동차이용자  -  자동차

      |                           

 사용자             

 

5. 객체지향 설계

 

객체지향의 세계는 협력하는 자율적인 객체들의 공동체

 

설계하고 구현하기

사용자 ----> 게임기

자동차 이용자 및 게임횟수를 입력하라

결과를 알려줘라

 

게임기 ---->자동차이용자

자동차 이용자를 생성해라

자동차 이용자를 각 자동차에 넣어서 반환한다

 

자동차이용자 ----> 자동차

각 이용자를 자동차에 넣어라

자동차를 반환한다

 

처음에 차량 객체를 생성한다.

이름하고 위치 값을 저장한다.

package racingcar.model;
public class Car { //자동차 객체 생성
    private String name;
    private int position = 0;

    public Car(String name, int position) {
        this.name = name;
        this.position = position;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPosition() {
        return position;
    }

    public void setPosition(int position) {
        this.position = position;
    }
}

 

다음은 게임기 클래스다.

package racingcar.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class RacingGame {

    public List<Car> saveCars(String[] carNames) {
        List<Car> cars = new ArrayList<>();
        for (int i = 0; i < carNames.length; i++) {
            String name = carNames[i];
            cars.add(new Car(name, 0));
        }
        return cars;
    }
    public void updatePhase(List<Car> cars) {
        Random random = new Random();
        for (int j = 0; j < cars.size(); j++) {
            int randomNum = random.nextInt(10);
            if (randomNum >= 4) {
                cars.get(j).setPosition(cars.get(j).getPosition() + 1);
            }
        }
    }
}

 

간단히 자동차 이용자 이름을 받아 차량안에 넣어주는 메서드와 랜덤하게 값을 증가시켜주는 메서드다.

 

 

그다음은 게임 결과를 보여주는 클래스다.

package racingcar.model;

import java.util.List;
import java.util.Random;

public class WinningResult {
    public int winningScore = 0;

    public void winningScore(List<Car> cars) {
        for (int m = 0; m < cars.size(); m++) {
            if (winningScore < cars.get(m).getPosition()) {
                winningScore = cars.get(m).getPosition();
            }
        }
    }

}

 

제일 큰녀석이 winningScore에 삽입

 

다음은 입력받는 메서드다.

 

package racingcar.view;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class InputView { //입력관련 메서드 집합
    Scanner sc = new Scanner(System.in);

    public String[] getNames() {
        System.out.print("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
        String inputname = sc.next();
        String[] names = inputname.split(","); //쉼표로 분리해서 넣기
        try {
            nameRange(names); //글자가 5개 이상이거나,
            sameName(names); //같은 이름이 있을 경우
        } catch (IllegalArgumentException e) {
            getNames();
        }
        return names;
    }

    private void nameRange(String[] names) {
        for (String name : names) {
            if (name.length() > 5) {
                System.out.print("글자가 5자리 아래여야만함");
                throw new IllegalArgumentException();
            }
        }
    }

    private void sameName(String[] names) {
        List<String> check = new ArrayList<>();
        for (String name : names) {
            if (check.contains(name)) {
                System.out.print("중복이름 X");
                throw new IllegalArgumentException();
            } else {
                check.add(name);
            }
        }
    }

    public int getRound() {
        System.out.print("시도할 회수는 몇회인가요?");
        String inputround = sc.next();
        int round = 0;
        try {
            round = Integer.parseInt(inputround);
        } catch (IllegalArgumentException e) {
            System.out.print("숫자나 입력하세여");
            getRound();
        }
        return round;
    }

}

 

 

다음은 출력 메서드다.

 

package racingcar.view;

import racingcar.model.Car;

import java.util.ArrayList;
import java.util.List;

public class OutputView {

    public void round(List<Car> cars) {
        for (Car car : cars) {
            System.out.print(car.getName());
            System.out.print(" : ");
            System.out.println("-".repeat(car.getPosition()));
        }
        System.out.println();
    }

    public void result(List<Car> cars, int firstPrize) {
        System.out.print("");
        List<String> winner = new ArrayList<>();
        for (int n = 0; n < cars.size(); n++) {
            if (cars.get(n).getPosition() == firstPrize) {
                winner.add(cars.get(n).getName());
            }
        }
        System.out.println(String.join(", ", winner));
    }
}

 

자동차 모양 나오기 & 우승한 사람 winner에 저장한 뒤 출력하는 메서드

 

 

마지막은 전체적은 흐름을 관리하는 Controller부분이다.

package racingcar.controller;

import racingcar.model.Car;
import racingcar.model.RacingGame;
import racingcar.model.WinningResult;
import racingcar.view.InputView;
import racingcar.view.OutputView;

import java.util.List;

public class RacingController {
    private final RacingGame racinggame = new RacingGame();
    private final WinningResult winningresult = new WinningResult();
    private final InputView inputView = new InputView();
    private final OutputView outputview = new OutputView();

    public void start() {
        String[] names = inputView.getNames();
        int round = inputView.getRound();
        List<Car> cars = racinggame.saveCars(names);
        roundResult(round, cars);
        winningresult.winningScore(cars);
        outputview.result(cars, winningresult.winningScore);
    }

    private void roundResult(int round, List<Car> cars) {
        System.out.println("");
        for (int i = 0; i < round; i++) {
            racinggame.updatePhase(cars);
            outputview.round(cars);
        }
    }
}

 

보면 시작해서 입력, 결과호출, 결과출력까지 관장하는 메서드다. 

 

객체지향 생활 체조 9가지 원칙

규칙 1: 한 메서드에 오직 한 단계의 들여쓰기(indent)만 한다.
규칙 2: else 예약어를 쓰지 않는다.
규칙 3: 모든 원시값과 문자열을 포장한다.
규칙 4: 한 줄에 점을 하나만 찍는다.
규칙 5: 줄여쓰지 않는다(축약 금지).
규칙 6: 모든 엔티티를 작게 유지한다.
규칙 7: 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.
규칙 8: 일급 콜렉션을 쓴다.
규칙 9: 게터/세터/프로퍼티를 쓰지 않는다.
 

 

객체지향 생활 체조 원칙을 지키면서 공부하자.

728x90
반응형

'백엔드' 카테고리의 다른 글

[Spring Boot] JPA @Id 전략  (0) 2024.08.15
[Spring Boot] 디렉터리 패키지 구조 - 도메인형, 계층형  (0) 2024.08.11
[Spring Boot] IoC, DI, AOP 정리  (0) 2024.08.11
[Spring Boot] Mapping 종류  (0) 2024.08.11
로또 - 객체지향  (1) 2024.03.18