[HTML mini Project] 오목 - 1

DooDuZ·2022년 12월 22일
0
post-thumbnail

국비 지원으로 코딩을 배우고 3주 정도 지났을 즈음 수업에서 만들었던 틱택토를 응용해서, 주말에 오목 만들기에 도전했었다. 지금 보면 너무 부끄러운 코드지만 그래도 저렇게나마 뭘 했던 4달전의 두더지야 대견하다.


[프로젝트 계획]

1. 기존 틱텍토와 다른 방법으로 구현해보기 / 배열 사용x
2. 실제 바둑판을 앞에 두고 두는 것과 가장 흡사하게 구현하고자 함 / 무르기 기능 X
3. 세부 룰(33, 44 등에서 이어진 렌주룰) 구현 X / 돌이 5개가 연달아 놓이면 게임 종료 까지만 구현
4. 기능 구현 후 css까지 구현


이라는 계획이라고 하기도 좀 이상한 포부를 밝히며 코드를 치기 시작했는데

//js 코드 최상단
	// 전역 변수는 gameboard와 turn밖에 없다.
    // gameboard가 전역변수로 있는 건 이전 수업의 관성 때문... 관성으로 코드를 치면 불필요한 게 생긴다.
 let gameboard ; 
 let turn = 0

 function start_game(){
	gameboard = ''
	turn = 0
	for(let y = 1 ; y<=19 ; y++){
		gameboard += `<tr>`
		for(let x = 1 ; x<=19 ; x++){
			gameboard += `<td id='${x}_${y}' class='inner' onclick="click_btn('${x}_${y}')"></td>`
		}
		gameboard += `</tr>`
	}
	document.getElementById('board').innerHTML = gameboard
	outline_check()
}

프로젝트 계획 1의 기존 틱텍토와 다르게 구현한다는 말이 위에서 약간 드러난다. 틱텍토에선 배열과 인덱스를 통해서 게임 내용을 판단했는데, 여기선 div 하나 하나에 id로 좌표값을 넣어서 문서 전체를 읽는 식으로 게임을 구현했다. 좋은 방법이라고 생각하진 않았지만 이런식으로도 구현해보고 싶은 그런 마음이었다.

하여 놓여진 돌에 대한 체크도 아래와 같이

function click_test(e){
	if(document.getElementById(e).innerHTML=='<img src="흑돌.png">' || document.getElementById(e).innerHTML=='<img src="백돌.png">'){
		return true
	}	
}

문서의 상태를 직접 읽어서 판단했고...

function click_btn(e){
	if(turn==2){
		alert('게임종료')
		return
	}	
	if(click_test(e)){
		alert('이미 둔 자리입니다.')
		return
	}	
	if(turn==0){
		document.getElementById(e).innerHTML = '<img src="흑돌.png">'
		turn++
	}else{
		document.getElementById(e).innerHTML = '<img src="백돌.png">'
		turn--
	}
	if(check_winner()){
		if(turn==1){
			alert('흑돌 승리')
		}else{
			alert('백돌 승리')
		}
		turn = 2
	}
}

지금보면 매개변수로 쓰는 e도 조금 이상하지 않나 싶다. event나 element가 아니라 좌표를 표현하고싶었는데 왜 e였을까? 게다가 td에 온클릭을 넣어놓고 click_btn이라고 한 것도 지금보니 어이가 없다... 버튼이 어딨냐구 버튼이!!!

그러나 진짜 문제는 check_winner라는 함수에서 나타나는데

function check_winner(){	
	for(let y = 1 ; y <=19 ; y ++){
		for(let x = 1 ; x <= 15 ; x++){
			let data_x = document.getElementById(x+'_'+y).innerHTML
			let data_x2 = document.getElementById(x+1+'_'+y).innerHTML
			let data_x3 = document.getElementById(x+2+'_'+y).innerHTML
			let data_x4 = document.getElementById(x+3+'_'+y).innerHTML
			let data_x5 = document.getElementById(x+4+'_'+y).innerHTML 
			if(data_x!=''&& data_x==data_x2 && data_x==data_x3 && data_x==data_x4 && data_x==data_x5){
				return true
			}
		}
	} //가로 조건 종료
    . // 더
    . // 많은 
    . // 코드
}

가로 조건 검사 한번에 1915의 동작을 해야하는 슬픔... 이 있다.
저걸 세로 / 좌->우 대각선 / 우->좌 대각선 세가지 경우에 모두 사용한데다 마지막엔 19
19 판의 모든 돌을 count하는 반복문 까지 있으니 돌 한개 놓고 1000개가 넘는 값을 읽어야하는 배보다 배꼽이 더 큰 상황이 나와버렸다.


[개선점]

-매우 나쁜 코드임. 세부 룰 추가하여 처음부터 다시 만들 예정.

1. 배열을 사용하지 않았기 때문에 승리판단을 위해 매 착수마다 판 전체의 상황을 읽어야함(for 사용하여 1클릭 == 판 검사 361번). 매우 비효율적!!
2. 위의 방법으로 구현했기 때문에 click 이후의 상황과 이전의 상황을 구별할 방법이 없음 / 무르기 기능 구현 불가능
3. 배열을 이용하면 3*3금지 등의 룰을 부여할 때도 훨씬 편해질 것으로 생각됌.
4. 좌표 부여 시 ${x}{y} 사용하였으나 js가 number를 읽을 때 number사이에 있는 를 문자가 아니라 1,000 같은 단위로 인식하여 삭제하는 문제 발생.
ㄴ모든 ${x}_{y} 변수에 ''를 이용하여 문자열로 변환해줘서 해결. 그러나 아직 문법에 익숙하지 않은 우리에게 좋은 방법은 아닌듯 함.
ㄴ보다 효율적인 좌표 구현 방법 고민 필요
5. 바둑판 css 적용에 가상요소 사용하였으나 바둑판 내부와 외부, 4개의 꼭지점을 모두 나눠야 했어서 코드가 매우 길어짐. 보다 단순한 구조로 구현할 수 있도록 고민.


결국 느낀바가 많았던 나는 새로 알게된 2차원 배열이라는 놈을 이용해서 오목을 다시 만들어 보기로 한다. 적어도 개선점으로 적어둔 4번 부분은 확실히 좋아질 것으로 믿었다. 그 부분은 글이 길어지니 다음 글에 적어 보겠다..

profile
뇌세포에 CPR중

0개의 댓글