html, js, css 파일로 분리
[ bowling.html ]
body부분
<body>
<div id="container">
<label for="bowling">게임 횟수</label>
<select id="bowling" onchange="play(this.value)">
<option value="0">선택</option>
</select>
<button id="playButton">확인</button>
<button id="reloadButton" class="hideButton">reload</button>
</div>
</body>
script 부분
<script>
let select = document.getElementById("bowling"); // select요소
let option; // option요소
// 반복문으로 option값인 실행횟수 생성
for (let i = 0; i < 20; i++) {
option = document.createElement('option'); // option태그 생성
option.setAttribute("value", i+1); // option_value 값 지정
option.innerText = i+1; // option태그 내부값 지정
select.append(option); // select태그에 option들 추가
}
// 실행횟수 (기본값 = 0)
let optionValue = 0;
// 선택한 실행횟수로 option값 초기화
function play(option){
optionValue = option;
return optionValue;
}
let playbutton = document.getElementById("playButton"); // 확인버튼
let reloadButton = document.getElementById("reloadButton"); // reload버튼
// 확인버튼클릭
playbutton.addEventListener("click", showTable);
// 진행함수
function showTable(){
let order = 1; // 테이블이름을 위한 값
let option = optionValue; // 선택한 옵션값
if(option === 0){ // 선택하지 않은경우 팝업창 & 페이지reload
alert("게임횟수를 선택하세요");
reload();
}
while(option > 0){
playing(option, order); // 테이블 생성함수 실행
option--; // 선택한 옵션만큼만 실행
order++;
}
// 확인버튼 클릭하면 버튼변경(확인 => reload)
playbutton.classList.add("hideButton");
reloadButton.classList.add("showButton")
}
// reload버튼클릭
reloadButton.addEventListener("click", reload);
// 페이지 reload 함수
function reload(){
location.reload();
}
</script>
[ playing.js ]
(사용한 함수들)
randomNum(max)
입력값 => max정수값
출력값 => max까지의 랜덤숫자
createScore(n)
입력값 => n (0~10)
출력값 => frameNums = [firstNumber, secondNumber, bonusNumber]
calculatePlusScore(Nums1, Nums2, Nums3)
입력값 => frameNums[] 3개
출력값 => plus점수
calculateScore(n, frameNums)
입력값 => n (0~9) , 프레임점수배열 // 10프레임은 별도 계산
출력값 => total점수
playing(option, order) _ 테이블생성 및 위의 함수들로 반복문실행
입력값 => option(실행횟수)
=> order(테이블이름순서)
randomNum(max)
// 랜덤정수 생성함수
// - 최댓값을 매개변수로 받고, 매개변수 이하의 랜덤정수를 리턴
function randomNum(max) {
let number = Math.floor(Math.random() * (max + 1));
return number;
}
createScore(n)
// 점수생성 함수 [1투구, 2투구, 보너스]
// - 프레임 순서를 매개변수로 받고, 각 프레임 점수배열을 리턴
function createScore(n) {
// 랜덤점수생성
let firstNumber = randomNum(10); // 1투구점수
let secondNumber = randomNum(10 - firstNumber); // 2투구점수
let bonusNumber = 0; // 10프레임 보너스점수
// 10프레임 보너스점수 생성
if (n === 9) {
// strike인 경우 보너스점수 생성
if (firstNumber === 10) {
secondNumber = randomNum(10);
bonusNumber = randomNum(10 - secondNumber);
// spare인 경우 보너스점수 생성
} else if (firstNumber + secondNumber === 10) {
bonusNumber = randomNum(10);
}
}
// 각 프레임점수 [1투구, 2투구, 보너스]
let Nums = [firstNumber, secondNumber, bonusNumber];
return Nums;
}
calculatePlusScore(fNums1, fNums2, fNums3)
// plus점수 계산함수
// - 세개의 프레임점수를 매개변수로 받고, 각 프레임의 가산점을 리턴
function calculatePlusScore(fNums1, fNums2, fNums3) {
let plus = 0;
if (fNums1[0] === 10) {
// double인 경우
if (fNums2[0] === 10) {
plus = fNums2[0] + fNums2[1] + fNums3[0] + fNums3[1];
//console.log("더블 plus : " + plus);
// strike인 경우
} else {
plus = fNums2[0] + fNums2[1];
//console.log("스트라이크 plus : " + plus);
}
// spare인 경우
} else if (fNums1[0] + fNums1[1] === 10) {
plus = fNums2[0]
//console.log("스페어 plus : " + plus);
}
return plus;
}
calculateScore(n, frameNums)
// total 점수 계산 함수
// - 프레임순서, 프레임점수배열을 매개변수로 받고, 각 프레임의 총점을 리턴
function calculateScore(n, frameNums) {
let plus = 0;
let total = 0;
// plus 점수 계산
if (n === 8) { // 9프레임
plus = calculatePlusScore(frameNums[n], frameNums[n + 1], [0, 0])
} else { // 1~8 프레임
plus = calculatePlusScore(frameNums[n], frameNums[n + 1], frameNums[n + 2]);
}
// total 점수 계산
total = plus + frameNums[n][0] + frameNums[n][1];
return total;
}
playing(option, order)
// 테이블 생성 및 진행
function playing(option, order) {
// ****** 테이블생성 start ******
let table = document.createElement('table');
table.classList.add('table'+option);
for (let i = 0; i < 3; i++) { // 테이블행 생성
let row = table.insertRow();
for (let j = 0; j < 11; j++) { // 테이블열 생성
let cell = row.insertCell();
if (i === 0) { // 1행
cell.textContent = j + 1; // 프레임순서넣기
cell.classList.add("firstRow");
if (j === 10) {
cell.textContent = "Total"; // 1행 마지막열은 Total 넣기
}
} else if (i === 1 && j != 10) { // 2행
cell.classList.add("score");
// 1투구점수칸 생성
let span1 = document.createElement('span');
span1.classList.add("firstScore");
cell.appendChild(span1);
// 2투구점수칸 생성
let span2 = document.createElement('span');
span2.classList.add("secondScore");
cell.appendChild(span2);
// 보너스점수칸 생성
let span3 = document.createElement('span');
span3.classList.add("bonusScore");
// 10프레임에만 보너스점수칸 넣기
if (j === 9) {
cell.appendChild(span3);
}
if (j === 10) {
cell.classList.add("showTotal");
}
} else if (j != 10) { // 3행
cell.classList.add("totalScore");
}
}
}
// ****** 테이블생성 end ******
// 테이블이름 생성
let div = document.createElement('div');
div.innerText = "Game "+ order;
div.classList.add("gameTitle")
// 생성한 테이블&이름 body에 추가
document.body.append(div, table);
// 테이블의 마지막열 Total점수 표시를 위한 테이블정리
let lastCell = table.rows[1].cells[10];
lastCell.rowSpan = 2;
lastCell.classList.add("showTotal");
table.rows[2].cells[10].remove();
// 테이블 요소들 변수에 할당
let firstScore = document.querySelectorAll(".table"+option+" td span:first-child");
let secondScore = document.querySelectorAll(".table"+option+" td span:nth-child(2)");
let bonusScore = document.querySelector(".table"+option+" .bonusScore");
let totalScore = document.querySelectorAll(".table"+option+" .totalScore");
let showTotal = document.querySelector(".table"+option+" .showTotal");
let Nums = []; // 1투구, 2투구, 보너스(10프레임) 점수배열
let frameNums = []; // Nums들 배열
let total = []; // 총점(1투구+2투구+가산)
let bonusNumber = 0; // 10프레임 보너스점수
// 1~10프레임 점수생성 & 테이블에 넣기
for (let n = 0; n < 10; n++) {
// 점수생성
Nums = createScore(n); // [1투구, 2투구, 보너스]
frameNums[n] = Nums; // Nums들 배열
// 테이블에 1투구&2투구 점수표시
firstScore[n].innerText = open(Nums[0]);
secondScore[n].innerText = open(Nums[1]);
bonusNumber = Nums[2];
}
// 10프레임에 보너스 점수 표시
if ((frameNums[9][3] != 'P' || frameNums[9][3] == 'S') && frameNums[9][1] + bonusNumber === 10) {
bonusScore.innerText = "/";
} else {
bonusScore.innerText = open(bonusNumber);
}
// 1~10프레임 총점 계산 & 테이블에 넣기
for (let n = 0; n < 9; n++) {
// 각 프레임별 총점 계산
if (n === 0) { // 1프레임
total[0] = calculateScore(n, frameNums);
} else { // 2~9 프레임
total[n] = total[n-1] + calculateScore(n, frameNums);
}
// 테이블에 total점수 표시
totalScore[n].innerHTML = total[n];
}
// 10프레임 총점 & Total점수 표시
let TotalScore = total[8] + bonusNumber + frameNums[9][0] + frameNums[9][1] + frameNums[9][2];
totalScore[9].innerHTML = TotalScore;
showTotal.innerHTML = TotalScore;
// strike or spare인 경우 X or / 로 표시
for (let n = 0; n < 10; n++) {
console.log("frameNums "+(n+1)+ " : " + frameNums[n]);
// calculateScore 함수에서 추가한 문자열로 strike or spare 판별
if (frameNums[n][3] == "S") {
firstScore[n].innerText = "X";
} else if (frameNums[n][3] == "P") {
secondScore[n].innerText = "/";
}
}
console.log("*********************")
}
[ bowling.css]
#container{
display: flex;
align-items: center;
margin-left: 20px;
}
#bowling{
width: 45px;
height: 25px;
margin: 20px 10px;
}
#playButton, #reloadButton{
width: 50px;
height: 25px;
margin: 5px;
}
.hideButton{
display: none;
}
.showButton{
display: inline;
}
table{
border-collapse: collapse;
width: 500px;
margin: 10px 0 30px 20px;
}
.score{
white-space: nowrap;
padding: 0;
}
td{
border: 1px solid black;
border-collapse: collapse;
text-align: center;
padding: 7px;
}
td span{
display: inline-block;
border: 0.01px solid gray;
width: 20px;
padding: 7px;
}
.firstRow{
background-color: lightgray;
font-weight: bolder;
}
.showTotal{
font-weight: bolder;
}
Strike인 경우 10점대신 => X
Spare인 경우 점수대신 => /
Open(0점)인 경우 0점대신 => -
볼링 점수 테이블에 위처럼 넣어준다.
calculateScore(n, frameNums)
*** strike(S), spare(P), None(N) 판별문자를 frameNums배열 마지막 요소에 넣는 조건문 추가
// total 점수 계산 함수
// - 프레임순서, 프레임점수배열을 매개변수로 받고, 각 프레임의 총점을 리턴
function calculateScore(n, frameNums) {
let plus = 0;
let total = 0;
// plus 점수 계산
if (n === 8) { // 9프레임
plus = calculatePlusScore(frameNums[n], frameNums[n + 1], [0, 0])
} else { // 1~8 프레임
plus = calculatePlusScore(frameNums[n], frameNums[n + 1], frameNums[n + 2]);
}
// total 점수 계산
total = plus + frameNums[n][0] + frameNums[n][1];
// strike(S), spare(P) 판별문자 frameNums배열 마지막 요소에 추가
if(frameNums[n][0] === 10){
frameNums[n][3] = "S";
} else if(frameNums[n][0] + frameNums[n][1] === 10){
frameNums[n][3] = "P"
} else {
frameNums[n][3] = "N"
}
return total;
}
10프레임은 별도로 계산했기 때문에 문자도 별도로 추가해줬다.
createScore(n)
*** 10프레임은 strike(S), spare(P), None(N) 판별문자를 bonus점수 생성 시에 추가
(어차피 S or P 판별하여 bonus점수를 생성하기에 여기에서 문자만 추가해줌)
// 점수생성 함수 [1투구, 2투구, 보너스]
// - 프레임 순서를 매개변수로 받고, 각 프레임 점수배열을 리턴
function createScore(n) {
// 랜덤점수생성
let firstNumber = randomNum(10); // 1투구점수
let secondNumber = randomNum(10 - firstNumber); // 2투구점수
let bonusNumber = 0; // 10프레임 보너스점수
let SorP = "N";
// 10프레임 보너스점수 생성
if (n === 9) {
// strike인 경우 보너스점수 생성
if (firstNumber === 10) {
secondNumber = randomNum(10);
bonusNumber = randomNum(10 - secondNumber);
SorP = "S";
// spare인 경우 보너스점수 생성
} else if (firstNumber + secondNumber === 10) {
bonusNumber = randomNum(10);
SorP = "P"
}
}
이렇게 추가해주면 frameNums 배열 구성은 아래처럼 된다.
open(score) 함수 생성
// 0점 표시 함수
// - 점수가 0인경우 '-'로 표시
function open(score){
if(score == 0){
return "-";
} else {
return score;
}
}
open 함수는 각 투구 점수들 & 보너스점수가 테이블에 들어가는 시점에 적용시켰다.
// 1~10프레임 점수생성 & 테이블에 넣기
for (let n = 0; n < 10; n++) {
// 점수생성
Nums = createScore(n); // [1투구, 2투구, 보너스]
frameNums[n] = Nums; // Nums들 배열
// 테이블에 1투구&2투구 점수표시
firstScore[n].innerText = open(Nums[0]);
secondScore[n].innerText = open(Nums[1]);
bonusNumber = Nums[2];
}
// 10프레임에 보너스 점수 표시
bonusScore.innerText = open(bonusNumber);
예외케이스는 10프레임의 bonusNumber에 대한 적용
if (bonusNumber === 10) 보너스가 스트라이크
bonusScore.innerText = "X"
else ( frameNumber[9][2] + bonusNumber === 10 ) 보너스가 스페어
bonusScore.innerText = "/"
1. 보너스가 스트라이크인 경우
=> open 함수에 조건 추가
*** 2투구 점수가 10점인 경우에도 X가 들어가지만
다른 투구 점수들에 문자열을 넣는 로직이 이후 실행되기 때문에 /로 덮어씌워진다.
// 0점 표시 함수
// - 점수가 0인경우 '-'로 표시
function open(score){
if(score === 0){
return "-";
} else if(score === 10){ // bonusNumber가 10인 경우를 위해 추가
return "X";
} else {
return score;
}
}
2. 보너스가 스페어인 경우
// 10프레임에 보너스 점수 표시
if ((frameNums[9][3] == 'P' && frameNums[9][1] + bonusNumber === 10) {
bonusScore.innerText = "/";
} else {
bonusScore.innerText = open(bonusNumber);
}
이렇게 했더니 오류
조건문 수정
(S이면서)
bonusNumber =10 인 경우 => X (스트라이크) __ else의 open함수로 보내버린다.
frameNums[9][1] + bonusNumber = 10 인 경우 => / (스페어) __ if 조건문에 걸림
(P이면서)
frameNums[9][1] + bonusNumber = 10 인 경우 => / (스페어) 가 아닌 점수가 표시되어야 한다. __ else로 빠짐
(1 - 9 - 1 의 경우)
// 10프레임에 보너스 점수 표시
if ((frameNums[9][3] != 'P' || frameNums[9][3] == 'S') && frameNums[9][1] + bonusNumber === 10) {
bonusScore.innerText = "/";
} else {
bonusScore.innerText = open(bonusNumber);
}
오류잡았다 야호
선택한 게임 횟수만큼 점수판 생성 완료!
'업무 > 기타' 카테고리의 다른 글
[과제] MySQL 쿼리 작성 ( 2차 & 3차 ) (0) | 2024.03.04 |
---|---|
[과제] MySQL 쿼리 작성 (1차) (0) | 2024.02.29 |
[과제] 별찍기 (0) | 2024.02.23 |
[과제] 볼링게임_ 설계 (0) | 2024.02.18 |
[과제] 볼링게임(코드) (0) | 2024.02.18 |