-
22-09-15_pythonmain 2022. 9. 15. 12:52
---
테트리스 : 자료구조가 명확하게 나와 있어서, 이를 공부하기에 좋음.
* 현재는 혼자 코드 짜면서 주로 삽질 위주.... 검색해서 코드 붙여넣고 이런 식으로 많이 할 텐데, 그냥 넣지 말고 예쁘게 정리해서 짜는게 중요함. 그 부분이 미진할 수 있음.
----
이렇게 지나간 부분들이 남음. 지나간 부분들은 0으로 만들어 줄 필요가 있음. 블럭이 흔적이 남는 것들을 요렇게 해서 없애줄 수 있음.
//시작하면서 초기화 해 줌 : 블럭을 이동할 때 마다 새로 그리니까, 이전 흔적이 남지 않음 //지나간 흔적을 기본배경색으로 바꾸는 역할 for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ block2D[i][j] = 0; } }
요렇게 초반에 0으로 초기화 해주는 코드를 넣어주면 된다. 요렇게 초반에 0으로 초기화 해주는 코드를 넣어주면 된다. ----
충돌처리
지금은 바깥으로 나가도 에러가 안남 골때림. 1)충돌을 감지하는 함수를 하나 만들어 줘야 함.
두가지 종류의 충돌이 있음. 벽과 충돌, stack과 충돌 - 충돌하면 원래상태로 돌려놔라ㅏ
에러가 안나, 에러가 나면 try-catch로 잡을 수 있는데... 어떻게 하면 벗어나느 걸 잡을 수 있을까...
저기 저 소스가 하나 나간건데, 이게 회전도 되고.... 이걸 어케 잡느냐... 각자가 음수(가로 왼쪽 끝 칸)가 되거나 24인덱스(가로 오른쪽 끝칸)이 되지 않도록 조건을 짜서 검증한다고 하면, 위에 블럭 씌운 칸 하나 하나마다 다 걸어줘야 되니까, 함수를 짜더라도 너무 지저분해지고 길어짐...
인덱스 개념으로 접근하지 말아야 할 것 같음
-> 해결책 1. 지금 10X25인데, 눈에 안보이게 테두리를 감싸서 1 같은거로 감싸두자 ==>부작용 :
(지금 10진법 기준으로 (가로10칸)맞춰줬는데, 또 위아래도 25로 바꿔놨는데, 이렇게 감싸두면 12X27이니까, 다 재조정 해 줘야 함. 처음부터 그렇게 짰으면 몰라도.
보면 도형이 모두 4개 칸으로 되어 있음. ==> 4개가 안 되면 -> 충돌이라고 판단
//충돌은 두가지가 있는데,
벽과의 충돌은, 숫자를 다 세서 4가 안 되면 충돌이라고 판단
스택과의 충돌은, for문을 돌려서, 같은 지점에서 하나라도 0보다 동시에 큰 게 있으면 충돌하는걸로...
----
벽과의 충돌을 먼저 만들어보자
function isCrushWall(){ //for문 돌려서 블럭의 갯수가 4개면 false ==충돌하지 않았다, 4개가 아니면 true ==충돌했다 반환하는 거 짜보기 } function myclick(e){ //The function of the Using direction key if (e.code == 'ArrowUp') { changeStatus(); } if (e.code == 'ArrowDown') { b.i++; } if (e.code == 'ArrowLeft') { b.j--; } if (e.code == 'ArrowRight') { b.j++; } //call functions setBlock2DFromBlock(); // console.log(block2D); setScrin2D(); // console.log(scrin2D); //벽과 충돌하는 경우를 정의하자, 충돌 안하는 경우가 많으니 기본값 false var flagWall = false; //메서드를 하나 만들어 주자, boolean은 보통 is~~~라고 명명 flagWall = isCrushWall(); console.log("flagWall",flagWall); myrender(); }
flagWall이라는 변수를 하나 선언 해 주고, (벽과 충돌여부)
이걸 설정할 수 있는 메서드인 isCrushWall() 메서드를 설정해주자
function isCrushWall(){ //for문 돌려서 블럭의 갯수가 4개면 false ==충돌하지 않았다, //4개가 아니면 true ==충돌했다 반환하는 거 짜보기 //2중for문돌려서, 0보다 크면 false, 4보다 작으면 false var cnt = 0; //2중for문돌려서, 0보다 크면, count증가 for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ if(block2D[i][j]>0){ cnt++; } } } if(cnt==4){ //for문 돌려서 블럭의 갯수가 4개면 false ==충돌하지 않았다, return false; }else{ //4개가 아니면 true ==충돌했다 반환하는 거 짜보기 return true; } }
이렇게
그러면 표를 벗어나면(도형 갯수가 4개가 안되게 되면 충돌==true, 충돌했다는 의미의 true 값을 반환한다. 근데 이제
밑으로 뚫고 내려가면 에러가 나요 후...
하나의 경우가 더 생겼죠
stack(바닥블럭)과 충돌하는것도 해보자
function isCrushStack(){ } function myclick(e){ //The function of the Using direction key if (e.code == 'ArrowUp') { changeStatus(); } if (e.code == 'ArrowDown') { b.i++; } if (e.code == 'ArrowLeft') { b.j--; } if (e.code == 'ArrowRight') { b.j++; } //call functions setBlock2DFromBlock(); // console.log(block2D); setScrin2D(); // console.log(scrin2D); //벽과 충돌하는 경우를 정의하자, 충돌 안하는 경우가 많으니 기본값 false var flagWall = isCrushWall(); // stack과 충돌하는 경우를 정의해보자 var flagStack = isCrushStack(); console.log("flagWall",flagWall); myrender(); }
var flagWall = false;
flagWall = isCrushWall();이거 두 줄은 한줄로 정리해줬음
var flagWall = isCrushWall();
---
isCrushStack()메서드도 만들어보자
function isCrushStack(){ for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ //한 칸이 stack 값과 block값을 동시에 갖는 경우 ==충돌한 경우 if(block2D[i][j]>0 && stack2D[i][j]>0){ return true; //충돌했다 } } } return false; //두개의 값을 동시에 갖지 않으면 ==충돌하지 않았다. }
stack과 부딛힐때, wall 밖으로 나갈 때 이제 true가 반환된다 이제 바닥을 뚫고 나갈때 에러를 해결하자 안뚫고가게
setBlock2DFromBlock();에서 에러가 난다. 줄이 25번째까지 밖에 없으니까 더 못간다고 에러나는거 (out of bound 같은.... 그래서 도형이 안그려짐)
이런 에러가 난다 여기서 --
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/try...catch
try...catch - JavaScript | MDN
try...catch 문은 실행할 코드블럭을 표시하고 예외(exception)가 발생(throw)할 경우의 응답을 지정합니다.
developer.mozilla.org
자바스크립트의 try-catch
----
//바닥과 부딛히는 경우의 변수 설정 var flagUnder =false; //call functions //바닥을 뚫고 나가면 에러가 나니까 try-catch처리하고, error시 충돌했다는 true반환 try { setBlock2DFromBlock(); } catch (error){ flagUnder = true; }
이렇게 처리를 해 준다.
바닥을 뚷고 나가면 flagUnder=true값이 반환된다 이제 이걸 통합해줄거임. 어쨋든 부딛히면 true를 반환하도록
//충돌을 하나로 합침 var flagCrush = flagWall || flagStack || flagUnder; console.log("flagCrush",flagCrush);
요렇게 처리됨 ---
이제 충돌하면 나가지 않도록 처리하기
--> 나가지 않게X, 충돌하면 충돌하면서 새로 그린 화면이 아니라 바로 전에 그린 화면을 재호출 해주는 모양으로 해 주기
충돌한 경우(flagCrush==true)에
setBlock2DFromBlock(); 와
setScrin2D(); 를 다시 불러와서 다시 그리는 모양으로....
이 경우에는 try-catch 처리 할 필요가 없져 에러가 안 나니까
var bakType = b.type; var bakStatus = b.status; var baki = b.i; var bakj = b.j; //충돌을 하나로 합침 var flagCrush = flagWall || flagStack || flagUnder; //flagCrush가 true인 경우에 실행됨. if(flagCrush){ b.type = bakType; b.status = bakStatus; b.i = baki; b.j = bakj; setBlock2DFromBlock(); setScrin2D(); }
요걸 추가해줍니다.
그러면 충돌나는 경우에 넘어가지 않음!!! (넘어가면 넘어가기 이전 모양이 다시그려짐(재 렌더링 됨)) 자 이제...
stack이 되는 경우에 조건이 붙는데요..
충돌이 나는 경우에 쌓인다X
옆으로 가는 경우에는 쌓이면 안되니깐.
(조건)
1) 우선 내려와야 하고
2) flagCrush가 부딛혀야 함
--> 두 가지 조건이 일치하면, stack에 block을 반영하세요 (쌓이세요)
(지금은 block과 stack이 다른 레이어에 있으니까 ==> 그걸 scrin에 합쳐서 보여줄 뿐임
-->충돌하면, 겹쳐지지 않게 원복을 시킨 다음에 stack에 옮겨주기
if(flagCrush){ b.type = bakType; b.status = bakStatus; b.i = baki; b.j = bakj; setBlock2DFromBlock(); setScrin2D(); }
여기에 이제 추가를 해줘야 하지..
flagDown = false; //The function of the Using direction key if (e.code == 'ArrowUp') { changeStatus(); } if (e.code == 'ArrowDown') { b.i++; //이걸 추가해주고요 flagDown = true; } if (e.code == 'ArrowLeft') { b.j--; } if (e.code == 'ArrowRight') { b.j++; }
여기에 아래키를 누르면, flagDwn= true를 추가해주고
if(flagCrush){ b.type = bakType; b.status = bakStatus; b.i = baki; b.j = bakj; setBlock2DFromBlock(); setScrin2D(); if(flagDown){ moveBlock2DToStack2D(); } }
여기도 if문을 추가 해 주고, moveBlock2DToStack2D 함수를 작성한다
function moveBlock2DToStack2D(){ //stack으로 이동하면서 색도 바꿔줘야 하고 //stack으로 block을 이동도 시켜줘야함.. for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ //0보다 크면 i,j에 있는걸 이동시켜준다.. if(block2D[i][j]>0){ stack2D[i][j] = block2D[i][j]+10; } } } }
이렇게 하고
console.log(stack2D) 이렇게 콘솔로 확인을 해 주면
이렇게 쌓이는 모습을 볼 수 있음 (쌓이면 stack2D로 이동하면서, 값은 10을 더해줘서 색상도 바뀜. 색상이 바뀌는건 어제
이렇게 값을 다르게 설정 해 줬었음 ---
이제 stack쌓이면 새 블럭이 나오게 해봅시당
이걸 설정을 어 해서 해줄거예요 if(flagDown){ moveBlock2DToStack2D(); //b.type 하고 set... b.type = 7; b.status = 1; b.i = 1; b.j = 5; setBlock2DFromBlock(); setScrin2D(); }
이런 식으로 일단 예로 만들어서, 블럭 타입은 7번으로 놓고 1/5번 자리에서 나온다고 설정을 해 주면
요렇게 stack에 쌓이면 새 블럭이 나오게 됨! 블럭이 하나만 나오면 재미없으니까 여러 종류의 블럭을 랜덤으로 꺼내봅시다
if(flagDown){ moveBlock2DToStack2D(); //b.type 하고 set... b.type = parseInt(Math.random()*7)+1; b.status = 1; b.i = 1; b.j = 5; setBlock2DFromBlock(); setScrin2D(); }
Math.random을 사용합시다
이 메서드는 여기 참고
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math/random
Math.random() - JavaScript | MDN
Math.random() 함수는 0 이상 1 미만의 구간에서 근사적으로 균일한(approximately uniform) 부동소숫점 의사난수를 반환하며, 이 값은 사용자가 원하는 범위로 변형할 수 있다. 난수 생성 알고리즘에 사용
developer.mozilla.org
그럼 이제 랜덤으로 도형이 나옴 --
이제 한 줄이 다 차면 없애주도록 합시다.... 이게 자료구조의 끝판왕이예요...
얘네들을 없애줄거거든요 근데 이제 없애고, 위에 있던걸 아래로 또 끌고 내려와야 하거든여
python이나 javscript의 배열은 stack의 기능도 가진다고 함 그게 append
10개 채우면 없애는 걸 먼저 해 보자
새 도형을 꺼낼 때 == 바닥에 닿았을 때 -> 일단 0이 나오게...
if(flagDown){ moveBlock2DToStack2D(); //10개짜리인거 없애주겠습니다.. //10개짜리가 몇개 있는지 var cnt10 = getCnt10(); console.log("cnt10",cnt10) //b.type 하고 set... b.type = parseInt(Math.random()*7)+1; b.status = 1; b.i = 1; b.j = 5; setBlock2DFromBlock(); setScrin2D(); }
function getCnt10(){ return 0 }
이렇게 해서 test를 해 보면
바닥에 일단 닿으면, 출력이 된다. function getCnt10(){ //25번 돌아가면서 i의 모든 값이 0보다 크면 카운트.. var cnt =0; for(var i=0; i<25; i++){ if( stack2D[i][0]>0 && stack2D[i][1]>0 && stack2D[i][2]>0 && stack2D[i][3]>0 && stack2D[i][4]>0 && stack2D[i][5]>0 && stack2D[i][6]>0 && stack2D[i][7]>0 && stack2D[i][8]>0 && stack2D[i][9]>0 ){ cnt++; } } return cnt; }
이렇게 함수를 처리 해 주면, 10개가 된 stack의 갯수를 출력 해준다
stack이 10개가 된 갯수 cnt값을 반환한다. 이제 10개가 된 것들을 지워봅시다.
여기서 해당 함수를 호출하고 (이것보다 위에다가 하면 10개가 차기도 전에 지워지니까 저 위치에 적어줍시다. 이 remove10이 어려워요 이걸 잘 이해하면 자료구조를 잘 이해했다고 할 수있어요
function remove10(){ for(var i=0; i<25; i++){ if( stack2D[i][0]>0 && stack2D[i][1]>0 && stack2D[i][2]>0 && stack2D[i][3]>0 && stack2D[i][4]>0 && stack2D[i][5]>0 && stack2D[i][6]>0 && stack2D[i][7]>0 && stack2D[i][8]>0 && stack2D[i][9]>0 ){ stack2D[i][0] =0; stack2D[i][1] =0; stack2D[i][2] =0; stack2D[i][3] =0; stack2D[i][4] =0; stack2D[i][5] =0; stack2D[i][6] =0; stack2D[i][7] =0; stack2D[i][8] =0; stack2D[i][9] =0; } } }
이렇게도 짤 수 있겠고요
근데 그러면
이렇게 됨 밑으로 안내려감 ---
이렇게 짜면여
function remove10(){ //stack2D비슷한거니까 s2D라고 명명해봅시다 var s2D =[]; for(var i=0; i<25; i++){ if( stack2D[i][0]>0 && stack2D[i][1]>0 && stack2D[i][2]>0 && stack2D[i][3]>0 && stack2D[i][4]>0 && stack2D[i][5]>0 && stack2D[i][6]>0 && stack2D[i][7]>0 && stack2D[i][8]>0 && stack2D[i][9]>0 ){ //pass }else{ s2D.push(stack2D[i]); } } console.log("s2D",s2D); }
이렇게 됨!
10이 된 것들이 사라지고 아래로 내려간다.
javascript array push index
를 구글에 검색해보자..
https://hianna.tistory.com/396
[Javascript] 배열 중간에 값 추가, 삭제하기 (2) - splice() 함수
지난 번에는 unshift(), shift(), push(), pop() 함수를 사용하여, 배열의 맨 앞과 뒤의 원소를 추가, 삭제하는 방법을 알아보았습니다. [Javascript] 배열에 값 추가, 삭제하기 (앞, 뒤) (1) 이번에는 splice()..
hianna.tistory.com
[JavaScript] 자바스크립트 배열 추가, 삭제 방법 (push, pop, splice)
자바스크립트 배열 추가, 삭제 함수 배열 추가 : Array.push(), Array.unshift(), Array.splice() 배열 삭제 : Array.pop(), Array.shift(), Array.splice() 배열 요소를 추가하는 방법 var arr = ['a', 'b', 'c']..
gent.tistory.com
unshift를 써보자
--
//10개짜리가 몇개 있는지 var cnt10 = getCnt10(); remove10(cnt10);
parameter 'cnt10'을 넣어주고..
function remove10(cnt10){ //stack2D비슷한거니까 s2D라고 명명해봅시다 var s2D =[]; for(var i=0; i<25; i++){ if( stack2D[i][0]>0 && stack2D[i][1]>0 && stack2D[i][2]>0 && stack2D[i][3]>0 && stack2D[i][4]>0 && stack2D[i][5]>0 && stack2D[i][6]>0 && stack2D[i][7]>0 && stack2D[i][8]>0 && stack2D[i][9]>0 ){ //pass }else{ s2D.push(stack2D[i]); } } for(var i=0; i<cnt10;i++){ s2D.unshift([0,0,0,0,0, 0,0,0,0,0]); } console.log("s2D",s2D); }
이렇게 짜서 console로 확인 해 주면
이렇게 사라진다 이제 s2D모양대로 덮어씌우면 됨
for문 이용하는게 편하겠죠..
엥 근데
function remove10(cnt10){ //stack2D비슷한거니까 s2D라고 명명해봅시다 var s2D =[]; for(var i=0; i<25; i++){ if( stack2D[i][0]>0 && stack2D[i][1]>0 && stack2D[i][2]>0 && stack2D[i][3]>0 && stack2D[i][4]>0 && stack2D[i][5]>0 && stack2D[i][6]>0 && stack2D[i][7]>0 && stack2D[i][8]>0 && stack2D[i][9]>0 ){ //pass }else{ s2D.push(stack2D[i]); } } for(var i=0; i<cnt10;i++){ s2D.unshift([0,0,0,0,0, 0,0,0,0,0]); } //이 코드를 넣으면... for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ stack2D[i][j] = s2D[i][j]; } } console.log("s2D",s2D); }
저 반복문을 넣으면 될 거 같은데 이게
이렇게 달라짐. 다사라져버림 왜냐...
Call By reference, call by value에 의해 생기는 error
//
(부연설명)
이건 약간 what time is now? 같은 거임 몇시인지 알려주면 걍 정해진 값이 바뀌진 않음
call by refernece는 , 야 그 시계를 나에게 줘. 임.. 그러면 그 시계를 12시인데 3시로 내가 바꿔서 다시 시계를 돌려주면, 값이 바뀐 상태에서 넘어가는거
//
.
이게뭐냐...예시로 알아보자
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript"> function call_value(a){ a =2; } function call_ref(a){ a[0] =2; } var a = 1; var b = [1]; console.log("a",a); console.log("b",b[0]); </script> </head> <body> </body> </html>
이렇게 출력됨 위의 코드가 그런데 그런데 이제 이렇게 해보자
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript"> function call_value(a){ a =2; } function call_ref(a){ a[0] =2; } var a = 1; var b = [1]; console.log("a",a); console.log("b",b[0]); call_value(a); call_value(b); console.log("a",a); console.log("b",b[0]); </script> </head> <body> </body> </html>
이렇게 하면 값이 1,1,2,2,가 나올 거 같은데...
1,1,1,2로 예상한 값이랑 다르게 나온다... 왜..?
reference는 바뀌는데 value가 안바뀜....refence는 C에서의 pointer 개념임... 어디라고 저장된 곳을 알려줌 그런데 value는그냥 값임....
reference값이 있어서 value가 같이 바뀌어 버림... reference를 잘못 넣으면 컴퓨터가 오동작함.
----
tetris 코드에서는 위의 코드에서는 어디서 오동작을 하냐면..
for(var i=0; i<cnt10;i++){ s2D.unshift([0,0,0,0,0, 0,0,0,0,0]); }
일단 이거 찝찝합니다 배열은 refernce값으로 주니까
}else{ s2D.push(stack2D[i]); }
여기도 찝찝합니다 배열이거든요
---
사실은 이건 좋은 케이스예요 바로 안나오거든..
보통은 제일 찝찝하고 못찾겠는게 뭐냐면,
잘 나오다가 한번 안나오거나 잘 나와가 갑자기 안나오는거... 왜냐면 주소지가 바뀌니까...
----
그러면 이제 ref값을 value값으로 바꿔 줄 거예요
----
자 예시를 다시 만들어 보자
이렇게 만들었는데, 배열을 string이랑 합쳐서 뽑아주니까 string이 되었어요. 이건 java쪽에서만 허용되는 방법이지만.. 그러면 tetris에서도 문자열(value)로 바꿔서 넣어줍시다.
}else{ s2D.push(stack2D[i]+""); } } for(var i=0; i<cnt10;i++){ s2D.unshift([0,0,0,0,0, 0,0,0,0,0]+""); }
이렇게 문자열로 바꿔서 넣어주면
이렇게 문자로 들어갔다고 나오고, 1들이 남아있는걸 볼 수 있음 자 이제 수정해주자
function remove10(cnt10){ //stack2D비슷한거니까 s2D라고 명명해봅시다 var s2D =[]; for(var i=0; i<25; i++){ if( stack2D[i][0]>0 && stack2D[i][1]>0 && stack2D[i][2]>0 && stack2D[i][3]>0 && stack2D[i][4]>0 && stack2D[i][5]>0 && stack2D[i][6]>0 && stack2D[i][7]>0 && stack2D[i][8]>0 && stack2D[i][9]>0 ){ //pass }else{ s2D.push(stack2D[i]+""); } } for(var i=0; i<cnt10;i++){ s2D.unshift([0,0,0,0,0, 0,0,0,0,0]+""); } //지워진거 뺸 채로 새로 그려주기 for(var i=0; i<25; i++){ stack2D[i][0] = parseInt(s2D[i].split(",")[0]); stack2D[i][1] = parseInt(s2D[i].split(",")[1]); stack2D[i][2] = parseInt(s2D[i].split(",")[2]); stack2D[i][3] = parseInt(s2D[i].split(",")[3]); stack2D[i][4] = parseInt(s2D[i].split(",")[4]); stack2D[i][5] = parseInt(s2D[i].split(",")[5]); stack2D[i][6] = parseInt(s2D[i].split(",")[6]); stack2D[i][7] = parseInt(s2D[i].split(",")[7]); stack2D[i][8] = parseInt(s2D[i].split(",")[8]); stack2D[i][9] = parseInt(s2D[i].split(",")[9]); } console.log("s2D",s2D); }
아래쪽 반복문을 문자로 바꿔서 넣어주기
--
아래 for문 반복문은, s2D[i]번째에 String으로 쪼개 준(split) 문자들을 각각 코드 맨 뒤쪽의 [n]번째 내용을
//저 숫자 n번은 console.log에 찍힌거에서....확인이 되는데, 매 열의 몇 번째 것을 잘라냄
stack2D[i][n]번째 index에 넣어서 배열을 새로 만들어 주는 역할임
예시로 이렇게 출력 해 보면 요렇게 나오는 걸 볼 수 있음. --
그러면
이렇게 남는 건 남고 사라질 건 사라짐 Deep copy, Shallow Copy를 쓰면 되는데 사실,
Deep copy, Shallow Copy를 못 쓰면 이렇게 하나하나 밟아서 넣어주면 된다.
====
web socket으로 네트워크로 여럿이 테트리스를 하는 걸 다음에 또 해보자고요,.,.
오늘 숙제 미리 내겠음...
django로 채팅하는걸 카톡으로 소스하고 같이 보내주시면...제일 먼저 한 사람에게 금일봉 일만원을 하사하시겠다하심..
=====
오늘의 전체 코드
<html> <head> <title>테트리스</title> <style type="text/css"> td{ width: 20px; height: 20px; } </style> <script type="text/javascript"> class Block { constructor() { this.type = 2; this.status = 1; //공통값이 1이..default니까.. //이번에 i가 회전 중심점 this.i =2; this.j =2; } } var b = new Block(); var block2D =[ [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0] ]; var stack2D =[ [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [1,0,0,0,0, 0,0,0,0,0], [1,1,0,0,0, 0,0,0,0,0], [1,1,1,1,1, 1,1,1,1,0], [1,1,1,1,1, 1,1,1,1,0], [1,1,1,1,1, 1,1,1,1,0], [1,1,1,1,1, 1,1,1,1,0] ]; var scrin2D =[ [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0], [0,0,0,0,0, 0,0,0,0,0] ]; function setBlock2DFromBlock(){ //시작하면서 초기화 해 줌 : 블럭을 이동할 때 마다 새로 그리니까, 이전 흔적이 남지 않음 //지나간 흔적을 기본배경색으로 바꾸는 역할 for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ block2D[i][j] = 0; } } //1번도형 if(b.type ==1){ block2D[b.i ][b.j ] = b.type; block2D[b.i ][b.j+1 ] = b.type; block2D[b.i+1 ][b.j ] = b.type; block2D[b.i+1 ][b.j+1 ] = b.type; } //2번도형 if(b.type ==2){ if(b.status ==1){ //가로 1자 block2D[b.i ][b.j-1 ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i ][b.j+1 ] = b.type; block2D[b.i ][b.j+2 ] = b.type; } if(b.status ==2){ //세로 1자 block2D[b.i-1 ][b.j ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i+1 ][b.j ] = b.type; block2D[b.i+2 ][b.j ] = b.type; } } //3번도형 if(b.type ==3){ if(b.status ==1){ block2D[b.i ][b.j+1 ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i+1 ][b.j ] = b.type; block2D[b.i+1 ][b.j-1 ] = b.type; } if(b.status ==2){ block2D[b.i-1 ][b.j ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i ][b.j+1 ] = b.type; block2D[b.i+1 ][b.j+1 ] = b.type; } } //4번도형 if(b.type ==4){ if(b.status ==1){ block2D [b.i ][b.j-1 ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i+1 ][b.j ] = b.type; block2D[b.i+1 ][b.j+1 ] = b.type; } if(b.status ==2){ block2D[b.i-1 ][b.j+1 ] = b.type; block2D[b.i ][b.j+1 ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i+1 ][b.j ] = b.type; } } //5번도형 if(b.type ==5){ if(b.status ==1){ block2D[b.i-1 ][b.j ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i+1 ][b.j ] = b.type; block2D[b.i+1 ][b.j+1 ] = b.type; } if(b.status ==2){ block2D[b.i ][b.j-1 ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i ][b.j+1 ] = b.type; block2D[b.i-1 ][b.j+1 ] = b.type; } if(b.status ==3){ block2D[b.i-1 ][b.j-1 ] = b.type; block2D[b.i-1 ][b.j ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i+1 ][b.j ] = b.type; } if(b.status ==4){ block2D[b.i ][b.j-1 ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i ][b.j+1 ] = b.type; block2D[b.i+1 ][b.j-1 ] = b.type; } } //6번도형 if(b.type ==6){ if(b.status ==1){ block2D[b.i-1 ][b.j-1 ] = b.type; block2D[b.i-1 ][b.j ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i+1 ][b.j ] = b.type; } if(b.status ==2){ block2D[b.i ][b.j-1 ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i ][b.j+1 ] = b.type; block2D[b.i+1 ][b.j-1 ] = b.type; } if(b.status ==3){ block2D[b.i-1 ][b.j ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i+1 ][b.j ] = b.type; block2D[b.i+1 ][b.j+1 ] = b.type; } if(b.status ==4){ block2D[b.i-1 ][b.j+1 ] = b.type; block2D[b.i ][b.j-1 ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i ][b.j+1 ] = b.type; } } //7번도형 if(b.type ==7){ if(b.status ==1){ block2D[b.i-1 ][b.j ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i ][b.j-1 ] = b.type; block2D[b.i ][b.j+1 ] = b.type; } if(b.status ==2){ block2D[b.i-1 ][b.j ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i+1 ][b.j ] = b.type; block2D[b.i ][b.j+1 ] = b.type; } if(b.status ==3){ block2D[b.i ][b.j-1 ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i ][b.j+1 ] = b.type; block2D[b.i+1 ][b.j ] = b.type; } if(b.status ==4){ block2D[b.i ][b.j-1 ] = b.type; block2D[b.i ][b.j ] = b.type; block2D[b.i-1 ][b.j ] = b.type; block2D[b.i+1 ][b.j ] = b.type; } } } function setScrin2D(){ //시작하면서 초기화 해 줌 : 블럭을 이동할 때 마다 새로 그리니까, 이전 흔적이 남지 않음 //지나간 흔적을 기본배경색으로 바꾸는 역할 for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ scrin2D[i][j] = 0; } } //block2D와 stack2D에 i,j값이 0보다 큰 경우에는 0이 아닌 값을 scrin2D에 넣어주기, 반복문 //block의 것을 scrin에 for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ if(block2D[i][j]>0){ scrin2D[i][j] =block2D[i][j]; } } } //stack의 것을 scrin에 for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ if(stack2D[i][j]>0){ scrin2D[i][j] =stack2D[i][j]; } } } } function myrender(){ //tds를 불러와서 10진수를 이용하는 방법1, 이걸 선호 //td2D를 만들어서 만들어 주는 방법2 //색은 0, 1~7(살아있는 도형), 11~17(stack된 도형) var tds = document.querySelectorAll("td"); for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ if(scrin2D[i][j] == 0){ tds[i*10+j].style.backgroundColor = "white"; } //살아있는 도형 색상 if(scrin2D[i][j] == 1){ tds[i*10+j].style.backgroundColor = "#ff0000"; } if(scrin2D[i][j] == 2){ tds[i*10+j].style.backgroundColor = "#ee0000"; } if(scrin2D[i][j] == 3){ tds[i*10+j].style.backgroundColor = "#dd0000"; } if(scrin2D[i][j] == 4){ tds[i*10+j].style.backgroundColor = "#cc0000"; } if(scrin2D[i][j] == 5){ tds[i*10+j].style.backgroundColor = "#bb0000"; } if(scrin2D[i][j] == 6){ tds[i*10+j].style.backgroundColor = "#aa0000"; } if(scrin2D[i][j] == 7){ tds[i*10+j].style.backgroundColor = "#990000"; } //쌓인 도형 색상 if(scrin2D[i][j] == 11){ tds[i*10+j].style.backgroundColor = "#ff0044"; } if(scrin2D[i][j] == 12){ tds[i*10+j].style.backgroundColor = "#ee0044"; } if(scrin2D[i][j] == 13){ tds[i*10+j].style.backgroundColor = "#dd0044"; } if(scrin2D[i][j] == 14){ tds[i*10+j].style.backgroundColor = "#cc0044"; } if(scrin2D[i][j] == 15){ tds[i*10+j].style.backgroundColor = "#bb0044"; } if(scrin2D[i][j] == 16){ tds[i*10+j].style.backgroundColor = "#aa0044"; } if(scrin2D[i][j] == 17){ tds[i*10+j].style.backgroundColor = "#990044"; } } } } window.addEventListener("keydown", (e) => { //키를 누르면 호출 myclick(e); } ); function isCrushWall(){ //for문 돌려서 블럭의 갯수가 4개면 false ==충돌하지 않았다, //4개가 아니면 true ==충돌했다 반환하는 거 짜보기 //2중for문돌려서, 0보다 크면 false, 4보다 작으면 false var cnt = 0; //2중for문돌려서, 0보다 크면, count증가 for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ if(block2D[i][j]>0){ cnt++; } } } if(cnt==4){ //for문 돌려서 블럭의 갯수가 4개면 false ==충돌하지 않았다, return false; }else{ //4개가 아니면 true ==충돌했다 반환하는 거 짜보기 return true; } } function isCrushStack(){ for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ //한 칸이 stack 값과 block값을 동시에 갖는 경우 ==충돌한 경우 if(block2D[i][j]>0 && stack2D[i][j]>0){ return true; //충돌했다 } } } return false; //두개의 값을 동시에 갖지 않으면 ==충돌하지 않았다. } function moveBlock2DToStack2D(){ //stack으로 이동하면서 색도 바꿔줘야 하고 //stack으로 block을 이동도 시켜줘야함.. for(var i=0; i<25; i++){ for(var j=0;j<10;j++){ //0보다 크면 i,j에 있는걸 이동시켜준다.. if(block2D[i][j]>0){ stack2D[i][j] = block2D[i][j]+10; } } } } function myclick(e){ var bakType = b.type; var bakStatus = b.status; var baki = b.i; var bakj = b.j; flagDown = false; //The function of the Using direction key if (e.code == 'ArrowUp') { changeStatus(); } if (e.code == 'ArrowDown') { b.i++; flagDown = true; } if (e.code == 'ArrowLeft') { b.j--; } if (e.code == 'ArrowRight') { b.j++; } //바닥과 부딛히는 경우의 변수 설정 var flagUnder =false; //call functions //바닥을 뚫고 나가면 에러가 나니까 try-catch처리하고, error시 충돌했다는 true반환 try { setBlock2DFromBlock(); } catch (error){ flagUnder = true; } // console.log(block2D); setScrin2D(); // console.log(scrin2D); //벽과 충돌하는 경우를 정의하자, 충돌 안하는 경우가 많으니 기본값 false var flagWall = isCrushWall(); // stack과 충돌하는 경우를 정의해보자 var flagStack = isCrushStack(); //충돌을 하나로 합침 var flagCrush = flagWall || flagStack || flagUnder; // console.log("flagCrush",flagCrush); //flagCrush가 true인 경우에 실행됨. if(flagCrush){ b.type = bakType; b.status = bakStatus; b.i = baki; b.j = bakj; setBlock2DFromBlock(); setScrin2D(); if(flagDown){ moveBlock2DToStack2D(); //10개짜리인거 없애주겠습니다.. //10개짜리가 몇개 있는지 var cnt10 = getCnt10(); remove10(cnt10); console.log("cnt10",cnt10) //b.type 하고 set... b.type = parseInt(Math.random()*7)+1; b.status = 1; b.i = 1; b.j = 5; setBlock2DFromBlock(); setScrin2D(); } } myrender(); console.log(stack2D); } function remove10(cnt10){ //stack2D비슷한거니까 s2D라고 명명해봅시다 var s2D =[]; for(var i=0; i<25; i++){ if( stack2D[i][0]>0 && stack2D[i][1]>0 && stack2D[i][2]>0 && stack2D[i][3]>0 && stack2D[i][4]>0 && stack2D[i][5]>0 && stack2D[i][6]>0 && stack2D[i][7]>0 && stack2D[i][8]>0 && stack2D[i][9]>0 ){ //pass }else{ s2D.push(stack2D[i]+""); } } for(var i=0; i<cnt10;i++){ s2D.unshift([0,0,0,0,0, 0,0,0,0,0]+""); } //지워진거 뺸 채로 새로 그려주기 for(var i=0; i<25; i++){ stack2D[i][0] = parseInt(s2D[i].split(",")[0]); stack2D[i][1] = parseInt(s2D[i].split(",")[1]); stack2D[i][2] = parseInt(s2D[i].split(",")[2]); stack2D[i][3] = parseInt(s2D[i].split(",")[3]); stack2D[i][4] = parseInt(s2D[i].split(",")[4]); stack2D[i][5] = parseInt(s2D[i].split(",")[5]); stack2D[i][6] = parseInt(s2D[i].split(",")[6]); stack2D[i][7] = parseInt(s2D[i].split(",")[7]); stack2D[i][8] = parseInt(s2D[i].split(",")[8]); stack2D[i][9] = parseInt(s2D[i].split(",")[9]); } console.log("cnt10",cnt10); console.log("s2D",s2D); } function getCnt10(){ //25번 돌아가면서 i의 모든 값이 0보다 크면 카운트.. var cnt =0; for(var i=0; i<25; i++){ if( stack2D[i][0]>0 && stack2D[i][1]>0 && stack2D[i][2]>0 && stack2D[i][3]>0 && stack2D[i][4]>0 && stack2D[i][5]>0 && stack2D[i][6]>0 && stack2D[i][7]>0 && stack2D[i][8]>0 && stack2D[i][9]>0 ){ cnt++; } } return cnt; } function myinit(){ } // The function of the change figure status when press 'UP'key function changeStatus(){ if(b.type == 2 || b.type ==3 || b.type==4){ if(b.status==1){ b.status =2; }else if(b.status==2){ b.status=1; } } if(b.type == 5 || b.type ==6 || b.type==7){ if(b.status==1){ b.status =2; }else if(b.status==2){ b.status=3; }else if(b.status==3){ b.status=4; }else if(b.status==4){ b.status=1; } } } </script> </head> <body onload="myinit()"> <table border="1px"> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td><td></td> </tr> </table> </body> </html>
'main' 카테고리의 다른 글
22-09-16_jsp (4) 2022.09.16 22-09-15_jsp (4) 2022.09.15 22-09-14_jsp (1) 2022.09.14 22-09-14_python (1) 2022.09.14 22-09-13_jsp(2) (0) 2022.09.13