https://blog.naver.com/htmkt_no1/220688646573
2048 게임 룰은 위 링크 참고
내 생각
로직은 간단하다. 먼저 게임이 시작되면 board에 2 혹은 4가 랜덤으로 배정된다. 그리고 방향키를 누르면 모든 숫자가 그 방향으로 이동하며 같은 숫자는 더해진다. 방향키를 누르면 board 안 모든 요소에 class를 지우고 끝으로 보내면서 만약 옆자리에 class가 있으면 자리를 차지하고 innerHTML이 같으면 *2를 한다. 아마 버튼을 누를 때마다 for문으로 전체를 돌아서 i를 이용해 방향키와 같은 방향, 즉 옆에 있는 square를 체크해야 할 것이다.(추측) game over는 매번 생성마다 for를 돌려서 자리가 다 찼다면 게임 오버!
정답
숫자가 이동할 때 filter를 이용해 기존의 참(양수)만 남기고 빈 square만큼 0을 채워서 다시 배열을 만들어 filtered와 concat한다.
상쾌하게 createBoard()를 해준다. for문으로 square 생성하고 squares배열에 넣어준다. 그리고 generate()를 만든다. 랜덤 넘버를 만들어서 squares의 랜덤넘버에 해당하는 요소가 0이면 2로 바꿔준다. 그리고 checkForGameOver 실행. 0이 아니라면 즉, 이미 다른 숫자가 있다면 다시 generate()를 한다. 일단 checkForGameOver는 스킵! generate함수를 create에 넣어준다.
Control 함수
control함수로 각각 해당하는 4개의 함수를 실행하는 switch 혹은 if문을 한다. 여기서 중요한 거는 방향키를 누를 때마다 요소를 움직이는 함수뿐만 아니라 row나 col 전체를 돌아서 합산하는 함수 그리고 다시 방향쪽으로 이동(만약 두 square가 합쳐졌다면 자리가 하나 비니까)하고 generate를 해줘야 하기에 4가지 함수가 한 번에 발생한다. 그렇기 때문에 keyRight라는 함수를 만들고 e.keyCode를 하면 그 함수를 실행. keyRight 함수 안에 4개의 함수를 담아 동시에 실행한다.
정리
2048 로직을 보면 숫자가 랜덤으로 생성된다. 방향키를 누르면 그 방향으로 숫자가 이동하고 똑같은 row, col에 있다면 그 방향으로 움직이면서 합쳐진다. 즉, 방향 버튼을 누르는 순간 이동하고 계산하고 다시 이동하고 랜덤 번호가 생성되어야 한다.
숫자 이동
board 전체를 for로 돈다. 이제 target이 될 i를 정해야 하는데 나머지가 0, 즉 모든 row의 [0]를 기준으로 잡는다. 그리고 4개의 변수를 만든다. 이 4개의 변수는 각 row를 구성하는 4개의 square다. 그리고 그 변수 4개를 row라는 배열에 담는다.
이렇게 방향키를 누르면 UI와 js가 일치되어 나오는 것을 알 수 있다! 이제부터 살짝 헷갈리는데(사실 엄청) 키를 누르면 배열에 존재하는 숫자들이 모두 그 방향으로 이동해야 한다. filter를 한다. fliter를 하는 이유는 요소가 움직이면서 새로운 요소가 랜덤으로 생성되기 때문에 기준점을 두는 것. 즉 filtered한 배열의 요소는 랜덤 생성 전이니까 구분을 둬서 먼저 합산하고 생성하고 순차적으로 진행할 수 있다.
이렇게 배열에 존재하는 첫 번째 값을 가져온다. 여기서 filter가 조금 헷갈린다.
filter
i로 잡은 타켓들을 담은 배열에 filter를 하는데 만약 parseInt를 안 한다면 어떻게 될까.
요렇게 된다. 왜냐면 배열의 요소들이 string이기 때문이다. filter는 true인 것을 리턴한다. parseInt를 하면 0은 false이기 때문에 return되지 않는 것이다. 왜 null로 안 하고 0으로 board를 깔았나 생각했는데 이런 큰 그림을 보고 0으로 깔았구나. 진짜 이걸 생각한 사람은 너무나 천재적이라서 인류를 위해 큰 일을 해줬으면 좋겠다.
이제 filtered row엔 각 row에 존재하는 true 즉, 숫자가 남는다. 남는 칸을 구해야 한다. missing이란 변수를 만들고 row의 길이에서 filtered row의 길이를 뺀다. 그리고 missing만큼 0을 채운 새로운 배열을 만든다.
이제 뭔가 감이 온다. 이제 저 배열에 filtered를 concat해서 새로운 배열을 만든다.
방향키를 한 번 누르면 기존의 있던 2가 맨 오른쪽으로 가서 존재하게 되었다. 그리고 새로 새성된 2는 아직 적용되지 않았음을 알 수 있다. 이제 기존의 squares에 있었던 요소의 innerHTML을 새로운 배열에 적용하면 된다. 즉, 아까 맨 처음 만들었던 row 배열은 temp 역할을 한 것! left도 똑같이 만들고 concat 순서만 바꾸면 된다. up, down은 width를 기준으로 i를 바꾸면 된다.
숫자들 합
combine row와 combine column이 필요하다. for문을 돈다. 최종 타겟 전까지만 돌면 된다. col의 경우 width 전까지. 돌면서 i와 i+1이 같은지 확인한다. 같다면 새로운 변수에 담고 i가 그 변수가 된다. 물론 i+1은 0이 되어야 함.
--> 키를 눌렀을 때 이동하고 합하고 다시 이동하고 생성하는 함수 4가지가 동시에 발생하는 것이 어렵다!