Coding 공부/IntelliJ

[IntelliJ_Springboot] 숫자게임#1

CBJH 2024. 5. 14.
728x90
반응형

1. 구조

  • controller 폴더
    • GameContoller : http://localhost:8080/games, http://localhost:8080/games/numberbaseball 페이지 get방식으로 templates의 html파일을 열어준다.
    • GameJsonController : ajax 비동기 방식으로 게임을 만들다보니 json 타입으로 값을 전달해야되서 사용한다. 버튼을 누르면 랜덤한 세자리 숫자를 생성하거나 입력한 숫자를 비교해 결과값을 출력하는데 사용한다.
  • util 폴더
    • Run : 숫자야구 로직을 구현한다. 
      • getAnswerNum() 랜덤 숫자 3개를 반환한다.
      • checkAnswerNum() 입력 받은 숫자와 생성한 숫자를 비교해 스트라이크, 볼 값을 문자열로 반환한다.
  • resources/templates
    • games.html 시작 화면(하이퍼 링크 구현을 위해 테스트)
    • numberbaseball.html 게임하는 화면. ajax를 사용해 비동기 방식으로 값을 보여준다.

 

2. 코드

2.1 컨트롤러

@Controller
@Log4j2
public class GameController {
    private Run run = new Run();

    @GetMapping("/games")
    public void selectGames(Model model) {}

    @GetMapping("/games/numberbaseball")
    public void selectNumberBaseball(Model model) {}
}
@RestController
@Log4j2
public class GameJsonController {
    private Run run = new Run();

    @PostMapping("/games/numberbaseball/createnumber")
    public ResponseEntity<int[]> createNumberBaseball() {
        int[] answerNum = run.getAnswerNum();
        return ResponseEntity.ok(answerNum); // int[] 배열을 JSON으로 반환
    }

    @PostMapping("/games/numberbaseball/checknumber")
    public ResponseEntity<String> checkNumberBaseball(
            @RequestParam("num1") int num1,
            @RequestParam("num2") int num2,
            @RequestParam("num3") int num3,
            @RequestParam("answerNum") int[] answerNum) { 
      // Collect inputNum from form
        int[] inputNum = { num1, num2, num3 };

        // Pass to your Run class's method
        String result = run.checkAnswerNum(inputNum, answerNum);

        return ResponseEntity.ok(result); // Return the result as a response
    }
}

 

2.2 유틸

public class Run {
    private int[] answerNum;
    private final int NUM_SIZE = 3;

    public int[] getAnswerNum(){
        int[] answerNum = new int[NUM_SIZE]; // 3개의 숫자를 저장할 배열
        int count = 0;  // 현재까지 채워진 숫자의 개수

        while (count < NUM_SIZE) {
            int temp = (int) (Math.random() * 10); // 0에서 9까지의 랜덤 숫자
            boolean flag = false;   // 중복 여부를 체크하는 플래그
            // 기존에 선택된 숫자들과 비교
            for (int j = 0; j < NUM_SIZE; j++) {
                if (temp == answerNum[j]) {
                    flag = true;    // 중복된 숫자 발견
                }
            }
            // 중복되지 않은 경우에만 배열에 추가
            if (!flag) {
                answerNum[count++] = temp;
            }
        }
        return answerNum;
    }

    public String checkAnswerNum(int[] inputNum, int[] answerNum){
        int ball_count = 0;
        int strike_count = 0;
        for (int i = 0; i < inputNum.length; i++) {
            for(int j = 0; j < inputNum.length; j++){
                if(answerNum[i] == inputNum[j]){
                    if(i==j){
                        strike_count++;
                    }else{
                        ball_count++;
                    }
                }
            }
        }
        return "B:"+ball_count + "  S:" + strike_count;
    }
}

 

2.3 Templates

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Games</title>
</head>
<body>
    <h1>Select Games!</h1>
    <a href="/games/numberbaseball">Number-Baseball</a>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>숫자야구 게임</title>
    <style>
        #wrap{
            width: 1200px;
            height: 600px;
            background-color: lightpink;
        }
        #header{
            width: 100%;
            height: 200px;
            background-color: aliceblue;
        }
        #contents{
            width: 100%;
            height: 400px;
            background-color: aquamarine;
        }
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
        $(document).ready(function() {
            createNumber()
            duplicationCheckNumber()
            checkNumber()
        });
        function checkNumber(){ //입력한 숫자를 체크해 BSO를 출력해주는 함수
            $('#checknumber').on('submit', function (event){
                event.preventDefault(); // 폼 기본 제출 방지
                $.ajax({
                    type:'POST',
                    url:'/games/numberbaseball/checknumber',
                    data: {
                        num1: $('#num1').val(), // 입력된 값 가져오기
                        num2: $('#num2').val(),
                        num3: $('#num3').val(),
                        answerNum: $('input[name="answerNum"]').val() // hidden 필드에서 answerNum 값 가져오기
                    },
                    success: function (result){
                        $('#contents').html('결과: '+result);
                    },
                    error : function (){
                        $('#contents').html('결과 출력에서 오류가 발생했습니다.')
                    }
                })
            })
        }
        function createNumber(){    //새로운 숫자 생성하는 함수
            $('#createNumberForm').on('submit', function(event) {
                event.preventDefault(); // 폼 기본 제출 방지
                $.ajax({
                    type: 'POST',
                    url: '/games/numberbaseball/createnumber',
                    success: function(answerNum) {
                        // 성공적으로 데이터를 받으면 실행
                        $('#contents').html('생성된 숫자: ' + answerNum.join(', '));
                        $('input[name="answerNum"]').val(answerNum); // 숨겨진 필드에 값을 설정
                    },
                    error: function() {
                        // 에러 발생 시 실행
                        $('#contents').html('숫자 생성에 에러가 발생했습니다.');
                    }
                });
            });
        }
        function duplicationCheckNumber(){ //input에 중복된 숫자 입력하면 제거하는 함수
            const inputs = document.querySelectorAll('input[type="number"]');
            inputs.forEach(input => {
                input.addEventListener('input', function() {
                    const values = Array.from(inputs).map(i => i.value);
                    const uniqueValues = new Set(values.filter(v => v !== '')); // 비어 있지 않은 값만 필터링

                    if (uniqueValues.size !== values.filter(v => v !== '').length) {
                        alert('중복된 숫자는 입력할 수 없습니다.');
                        this.value = ''; // 중복된 입력값 제거
                    }
                });
            });
        }
    </script>
</head>
<body>
<div id="wrap">
    <div id="header">
        <h1>숫자야구 게임</h1>
        <form id="createNumberForm" action="/games/numberbaseball/createnumber" method="post">
            <button type="submit">새로운 숫자 생성</button>
        </form>
        <form id = "checknumber" action="/games/numberbaseball/checknumber" method="post">
            <input type="number" id="num1" min="0" max="9">
            <input type="number" id="num2" min="0" max="9">
            <input type="number" id="num3" min="0" max="9">
            <input type="hidden" name="answerNum" value="answerNum">
            <button type="submit">입력</button>
        </form>
    </div>
    <div id="contents">컨텐츠</div>
</div>
</body>
</html>

 

3. 실행 화면

 

 

 

 

4. 추가 할 부분

  • 이상하게 숫자가 0~9까지 생성은 되는데, int[] 배열에 넣으면 0 값이 없다. 왜그런지는 더 알아볼 예정... 아시는 분들은 댓글로 알려주세요.
int temp = (int) (Math.random() * 10);
  • out 카운트 추가 할 예정입니다.
  • 이전까지 결과값을 누적해서 출력할 예정입니다.
  • 회원가입, 로그인 DB로 구현할 예정입니다.
  • id와 몇번 성공 했는지, out카운트 몇번만에 성공했는지 DB에 저장할 예정입니다.
  • 랭킹을 화면 우측 상단에 보여줄 예정입니다.(페이징 적용)

 

# 잡담..

  • FastAPI-Jinja2, Servlet, Express, Springboot 모두 비슷한 역할을 하다보니 사용법이 헷갈리네요.
  • html과 연동하는 부분도 변수를 불러오는 부분이 다 달라서 헷갈립니다.
  • 뷰와 컨트롤러가 교환하는 타입을 어떻게 처리되는지도 어려움이 있습니다.
  • ajax로 비동기 처리하는 방법이 자바 스크립트와 Jquery 문법이 익숙치 않아 콜백 함수를 사용하는 부분에 어려움이 있습니다.
  • JSON 타입으로 자료를 주고 받는 것에 서툴러서 항상 헷갈립니다.
  • Ajax를 사용하거나 Open API를 적용할 경우 JSON타입으로 자료를 주고 받으니, 사용법이 익숙해질때까지 계속해서 연습할 예정입니다.

댓글