728x90
반응형
1. 구조
- controller 폴더
- GameContoller : http://localhost:8080/games, http://localhost:8080/games/numberbaseball 페이지 get방식으로 templates의 html파일을 열어준다.
- GameJsonController : ajax 비동기 방식으로 게임을 만들다보니 json 타입으로 값을 전달해야되서 사용한다. 버튼을 누르면 랜덤한 세자리 숫자를 생성하거나 입력한 숫자를 비교해 결과값을 출력하는데 사용한다.
- util 폴더
- Run : 숫자야구 로직을 구현한다.
- getAnswerNum() 랜덤 숫자 3개를 반환한다.
- checkAnswerNum() 입력 받은 숫자와 생성한 숫자를 비교해 스트라이크, 볼 값을 문자열로 반환한다.
- Run : 숫자야구 로직을 구현한다.
- 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타입으로 자료를 주고 받으니, 사용법이 익숙해질때까지 계속해서 연습할 예정입니다.
댓글