8-puzzle Game(stable-diffusion)

Daki·2022년 12월 28일
0

Toy 프로젝트

목록 보기
1/1
post-thumbnail

8-puzzle Game.

stable-diffusion api를 이용하여 퍼즐을 만들고,
Auto-play 기능 제공, 클리어 보상으로 이미지를 제공한다.

대학 과제로 8-puzzle이 나왔다.
대부분의 사람들은 요구사항만 충족시켰다.
그게 영민한 것이지만, 지금 아니면 언제 이런거 만들겠나 싶어 진심을 다 했다.


Figma를 이용해서 간단하게 도안을 만들었다.
이를, Qt-Designer로 간단하게 만들었다.
캡쳐해서 객체 이름을 추가로 달아서 저장했다.
(객체 이름을 명시적으로 표기 하더라도, 이게 뭐더라? 싶을 때가 종종 있다.)

위의 자료를 기반으로, 구현할 핵심 기능들을 일단 휘갈겼다.

기능들 중에서, 2번(퍼즐 밀기 기능)이 가장 중요하다고 생각했다.
그래서 빈 퍼즐 좌표를 관리하여, 바뀔 수 있는지 여부 & 바뀜 이벤트를
처리하는게 핵심이라 생각하고, 개발에 착수했다.


Python은 자주 애용하지만, PyQt를 제대로 써 본적이 없었다.
image를 N x N으로 분리, A* 알고리즘은 금방 해결하였으나, 문제가 생겼다.

  1. 9개의 piece 중, 어떤 piece가 눌렸는지 어떻게 알 것인가?
  2. 이미지를 어떻게 바꿀 것인가?

1번문제,
slot에서, sender()를 이용하여 signal이 발생한 객체를 얻을 수 있다는 걸, 구글이 알려줬다.

2번 문제, 골이 좀 아팠다.
QLabel에 이미지를 넣었으나, QLabel은 click-event가 없었다.
QPushButton을 사용하고, style-sheet로 이미지를 넣었다.
get_stylesheet()와, set_stylesheet()를 이용하여 이미지를 교체 하기로 했다.

주먹구구식, 쓰레기 같은 코드가 완성되었고, 프로토 타입이 완성 되었다.

한 4시간동안 두드려 완성했다.
하드코딩으로 만들어지고 구조도 쓰레기 같았지만, 동작은 했다.
자동으로 섞어주고, 클릭하여 퍼즐 교체 기능까지 완료가 되었다.

과제 중간 점검까지 제출해야 할 내용이 완성이 되었고,
다른 과제와 공부 때문에 한동안 방치했다.


한 달이 지나, 다시 코드를 켰다.
당시에 스트레스 받아서 대충 작성했던 코드들을 보니 화가 났다.

내 손에서 이런 쓰레기 같은 코드가 나왔다는게 참 부끄러웠다.

문제점은, style_sheet를 활용하여 퍼즐을 바꾼 것이다. 라고 판단했다.
main.py에서 모든 책임을 가지고 있는게 문제라고 생각했다.

지금이 객체지향을 공부할 적기라는 느낌이 들었다.
예전부터 읽어야지 했던 토끼 책을 주말 내내 읽었다. (물론 10%도 이해 못 했다.)


위 책을 대충 1회독 하고, MVC 패턴에 관한 글을 몇 개 읽었다.
그리고 다시 설계도를 그렸다.

속성을 고민하지 마라. "행위"를 고민해라, "속성"은 따라 오는 것이다.

토끼책에서, 위 구절이 참 인상 깊었기에 필요한 method를 먼저 정리 했다.
그리고 MVC가 어떻게 영향을 미칠 지에 대해서 이것저것 써 봤다.
일련의 흐름이 필요하겠는데? 라는 생각이 들었다.

학교 선배가, signal&slot을 이용하여 파이프라인을 구현했던 걸 본적이 있었다.
그 방식을 써 보고자, method의 흐름을 오른쪽 페이지에 간략하게 표현 했다.


파이프라인을 점잖게 그려봤다.

shuffle(), auto_play() 둘 다, click_puzzle()을 쓰면 된다는 걸 알았다.
click_puzzle()을 잘 만들면, shuffle과 auto_play는 굴러 들어온다.

Piece의 책임 분리가 중요하다고 느꼈고, piece 객체를 만들기로 했다.


dataclass를 만들었다.
앞서 계획한 method들이 필요한 속성들로 만들었다.


만악의 근원이였던, piece.
QPush를 상속하고, style_sheet에 의존했던, hover 이벤트를 직접 구현했다.
QIcon으로 이미지를 입히고, getter, setter로 이미지를 설정할 수 있게 했다.
__eq__, __str__도 편의를 위해 추가 하였다.


이렇게 Gui가 완성 되었다.
Stable-diffusion api는 gradio를 사용하여 개인 PC에서 돌렸다. 해당 글 참고

create 버튼 클릭 시,

  • request로 api를 호출 -> 무한 로딩 다이얼로그 생성
  • response 도착 시 -> 무한 로딩 다이얼로그 종료
  • 클리어 버튼 클릭시 -> 생성된 이미지 다운로드

위의 기능을 추가하여 이 프로젝트가 완성 되었다.


작동만 해도 학점은 나온다, 시간이 없다는 핑계로 대충 만든적이 너무나 많다.
내 실력도 대충이 될 것 같아, 이번엔 진심을 다 했다.

하루 종일 코드를 짜서 완성을 했다.
시간 가는 줄도 모르고 프로그램을 만들었다.
A* 알고리즘이 puzzle_click()에 바로 연결될 떄의 희열은 아직도 생생하다.

쉬운 내용들이지만, 저에겐 참 많은 도움이 되었습니다.
긴 글을 읽어주셔서 감사합니다.

profile
하기 싫어도 하자, 감정은 사라지고 결과는 남는다.

0개의 댓글