[완료]애니팡! 자동화 [Java / Python] - 221104
Aim:
약 10년전, 스마트폰이 막 보급되기 시작했을때, 카카오에서 애니팡이라는 게임을 출시했었다. 전국민 모르는 사람이 없을정도로 인기가 많았고, 나 또한 재미있게 했었다. 단순한 게임이지만 친구들끼리 점수내기도 했었고, 공략법, 팁같은거를 많이 검색을 했었는데... 충격적인 영상을 봤다. 어떤 유저가 컴퓨터를 이용해서 자동으로 애니팡!(동물 3마리 이상 매칭) 시키는걸 봤다. 그 당시 되게 신기하게 봤었던 기억을 갖고 있다. (https://www.youtube.com/watch?v=4qwFwyhg7Nk)
(2016년엔 알파고가 이세돌을 바둑으로 압도적으로 이기는걸 군대에서 실시간으로 봤었고 컴퓨터 앞에서 정상 프로기사가 무너지는게 그 당시 믿기지 않았다. 인공지능이 엄청 발달했다는걸 느꼈었고 어떻게 그걸 만들었는지 신기할뿐이었다.)
나도 한번 비슷한걸 만들어보고 싶다. 재밌겠다~! ^0^
Hypothesis:
위에서부터 랜덤하게 (M,B,T,I) (A,B,C,D,E,F) 알파벳(종류 수를 정할 수 있다.)이 나오고 밑으로 쌓이고, 양옆, 위아래를 확인하여 애니팡이 가능하면 자리를 바꾼다. 애니팡이 생기면 해당 알파벳들을 삭제. 빈 자리만큼 위 알파벳들이 자리를 메꾸고, 맨위에는 랜덤하게 또 내려오게 만들고 싶다.
매번 움직이거나 판이 바뀔떄마다 출력(최대한 실시간으로 보이게끔 (1초 텀)). 애니팡이 없을경우 새로운 판을 다시 만들기.
Method: [Java] [Python]
1. Random 함수를 호출하여 해당 범위마다 알파벳(M,B,T,I) (A,B,C,D,E,F)을 가져온다. (8x8 사이즈) v(221019) v(221020)
2. 배열[0][0]~배열[0][7]까지 랜덤하게 넣는다. v(221019) v(221020)
3. 배열[0] 을 배열[1]로 넣고, 배열[0]에는 또 다른 랜덤 알파벳이 들어간다. v(221019) v(221020)
4. 배열[7]까지 차면 애니팡을 확인(가능하면 밑에서부터) v(2221019) v(221020)
5. 있으면 삭제( O 으로 바꿈)하고 공백을 위에서 한칸씩 내려오면서 메꾼다. v(2221019) v(221020)
6. 애니팡 없을때까지 반복 v(221019) v(221020)
7. potential 애니팡(양옆 위아래) 찾기 (이중 for문? / 메서드+for문?) v(221019) (221020) v(221020)
8. 있으면 위치를 바꿔서 애니팡(3개 1점, 4개 2점, 5개 3점... 8개 6점으로 카운트하기) v(221019) (221020) v(221020)
9. 팡이 생길때마다 바로바로 채워주기 v(221019) (221020) v(221020)
10. 더 이상 없을때까지 반복. (return Score) √(221019) (221020) v(221020)
Progress Notes:
[221018]
- Java부터 구현하려고 한다. 객체지향으로 (연습겸)하려고 했지만 효율적이지 않은것 같다. 9번까지 갔을떄 새로운 인스턴스를 만들려고 했지만, 어차피 Board는 하나로만 해도 괜찮을 것 같기때문에 static 을 줬다.
- 1~3번까지는 무난하게 했지만 4번부터 머리가 아프다.. 재귀함수로 구현을 하고 싶은데 잘 안될것 같다.
- 잘 안된다...4번은 행1 체크->열1 체크 순으로 해야될것 같다.
[221019]
- 애니팡 후, 문제가 생겼다. 새로운 char가 내려오면, 또 다시 체크를 해야하기때문에 루프가 많이돈다. O(3N^3). 크게 체감되진 않고 실행하는데 문제는 없으니, 일단은 넘어가고 나중에 다시 수정해야겠다.
- 7번 Potential 팡을 찾는게 생각보다 많은 경우의 수가 많아서 당황했다. A X A 의 경우도 있고, A A X 의 경우도 있고 .... A A X A A 의 경우도 있다. 가로, 세로로 나눈 후, 각각의 경우의 수에 대해 어떻게 해야할지 고민해봐야겠다.
- 생각해보니 간단했다. AAXAA 같은 경우의 수는 생각 안해도 되는데, 이유는 바꿔주기만 하고 4번을 호출해주면 알아서 카운트를 해준다. 다만 주의할건 대각선에 있는것부터 체크를 해주지 않으면, 4개팡! 이 가능해도 3개팡!만 된다.
- 팡!이 안될때가 있다. 처음부터 설계를 잘못하는 바람에 가독성이 너무 낮아졌다. 결과적으로 어디서 잘못된건지 찾을 수가 없어서 코드를 다 지우고 내일 다시 시작해야겠다.
[221020]
- 팡! 을 찾는 코드를 다시 작성하려고한다. 가독성이 안좋았던 이유중 하나는 경우의 수가 너무 많아서 그런것 같기도하다.
- 포문을 돌면서 row, column을 체크 하는데, [0][0]번째 같이, 모서리에서 찾을때 "out of bounds" 에러가 뜨기때문에, 따로 정의를 해줘야한다.
- 몇번의 시도 끝에 계속 헷갈려서 틀리게 된다.. 다른 방법이 있을텐데...
- 방법을 찾았다. 2차원 board 배열을 양옆, 위, 아래로 추가하는 것, 그리고 For문을 i=0부터 i<board.length-1 까지 도는것. 내가 원하던 속 시원한 답은 아니지만 일단 작동은 할것이다.
- 테스트를 해보면서 작동이 잘하는지 확인했고, 작동이 잘 되는것을 확인했다.
[221104]
- OpenCV 라는걸 처음 접해보면서 신기한 모듈들이 있다는걸 알고 난 후부터는 하나씩 들여다봤고, 프로젝트에 적용해볼만한게 보였다.
- Pillow , pynput, numpy, win32api 등... 잘만 조합하면 실제 애니팡에 적용이 될것 같아서 프로젝트에 들고와봤다.
- 저장된 이미지 값을 고정된 위치의 값과 비교하며 매핑을 해봤는데, 애니팡은 값이 조금씩 달라진다.
- 비슷한 스타크래프트2의 별난보석이라는 유즈맵에 비슷한게 있어서 여기에 적용을 해봤더니 잘된다.
Estimated Result:
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
->
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
->
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ B , M , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
->
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ B , M , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ O , O , I , T , B , M , I , T ]
[ O , O , T , I , M , B , T , I ]
[ O , O , I , T , B , M , I , T ]
->
[ O , O , T , I , M , B , T , I ]
[ O , O , I , T , B , M , I , T ]
[ O , O , T , I , M , B , T , I ]
[ M , B , I , T , B , M , I , T ]
[ B , M , T , I , M , B , T , I ]
[ M , B , I , T , B , M , I , T ]
[ B , M , T , I , M , B , T , I ]
[ M , B , I , T , B , M , I , T ]
->
[ M , B , T , I , M , B , T , I ]
[ I , T , I , T , B , M , I , T ]
[ M , B , T , I , M , B , T , I ]
[ M , B , I , T , B , M , I , T ]
[ B , M , T , I , M , B , T , I ]
[ M , B , I , T , B , M , I , T ]
[ B , M , T , I , M , B , T , I ]
[ M , B , I , T , B , M , I , T ]
-> ................
Code:
[Java] https://github.com/724thomas/AnniPangJava
(Java 와 파이썬 두개로 구현예정)
[Python] https://github.com/724thomas/AnnipangPython
Conclusion:
(JAVA)
(PYTHON)
- 8x8, (A,B,C,D,E,F) 총 6가지가 들어갈 수 있을때, 코드를 돌리면 나오는 결과값들 중 하나이다.
- 일단 작동이 된다. 작은 프로젝트이고 연산이 많이 필요없어서 결과값도 금방 나오긴 하다.
- 하지만 뿌듯함보다는 실망이 더 컸던 프로젝트다. 효율도, 설계도, 논리적인 사고도, 모두 부족하다는걸 느꼈다.
- 코드가 너무 더럽다. 아무생각없이 코드를 짰긴했지만 써보니 너무 지저분하다. 시간이 남으면 리팩토링을 해야겠다..
Bibliography:
[Java]
난수 생성방법
https://crazykim2.tistory.com/m/598 (침착곰 2021. 5. 27.)
Java convert int to char
https://www.javatpoint.com/java-int-to-char
Java 중첩 반복문 break (이중 For문 break)
https://ifuwanna.tistory.com/m/269 (IfUWanna 2020. 9. 15.)
Remove Duplicates from Sorted Array
https://www.youtube.com/watch?v=DEJAZBq0FDA&list=PLot-Xpze53lfQmTEztbgdp8ALEoydvnRQ&index=24 (Neetcode 2021. 9. 7.)
Contains Duplicate Leetcode 217 - Python
https://www.youtube.com/watch?v=3OamzN90kPg&list=PLot-Xpze53lfQmTEztbgdp8ALEoydvnRQ&index=34 (Neetcode 2021. 10. 26.)
Sleep 사용법
https://jink1982.tistory.com/185 (승미니1024 2018. 5. 23.)
[Python]
파이썬 객체지향 프로그래밍
파이썬 랜덤 모듈
https://wikidocs.net/79 (왕초보를 위한 파이썬)
지역변수, 전역변수
https://wikidocs.net/62 (왕초보를 위한 파이썬)
전역변수와 지역변수
https://python.bakyeono.net/chapter-3-4.html (연오의 파이썬)
keyboard 0.13.5
https://pypi.org/project/keyboard/
ModuleNotFoundError: No module named 'win32api'
https://jootc.com/p/201808241609 (JooTC 2018.08.24)
PyCharm can't install/import a package/libarary/module
https://intellij-support.jetbrains.com/hc/en-us/articles/360010202240 (Sergey Karpov 2022.11.02)