from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import time
import random
class WindowClass(QWidget):
def __init__(self):
super().__init__()
self.setMouseTracking(True)
self.setupUI()
self.worker = Cat(self)
self.worker.psignal.connect(self.draw_cat)
self.worker.scoresig.connect(self.ScoreDisplay)
self.worker.start()
self.show()
def setupUI(self):
self.setGeometry(100, 100, 912, 768)
self.mouse_x = 0
self.mouse_y = 0
self.cursor_x = 0
self.cursor_y = 0
self.index = 0
self.high_score, self.score, self.tsugi = 0, 0, 0
self.next_cat = QLabel(self)
self.next_cat.move(710, 128)
self.next_cat.resize(78, 78)
self.scorelabel = QLabel(self)
self.scorelabel.setText(str(0))
self.scorelabel.move(680, 100)
self.scorelabel.resize(50, 50)
self.high_score_label = QLabel(self)
self.high_score_label.resize(60, 60)
self.high_score_label.setFont(QFont('Times New Roman', 20))
self.high_score_label.move(680, 50)
self.high_score_label.setText(str(0))
self.neko = []
self.check = []
for i in range(10):
self.neko.append([0, 0, 0, 0, 0, 0, 0, 0])
self.check.append([0, 0, 0, 0, 0, 0, 0, 0])
# 딕셔너리가 아닌 리스트로 하니까 같은 메모리 영역을 공유하는 라벨 객체만 만들어져서 제대로 표현이 안되고 있었던 것
self.labels = {}
for y in range(10):
for x in range(8):
txt = str(x) + str(y)
self.labels[txt] = QLabel(self)
self.labels[txt].resize(78, 78)
self.labels[txt].setMouseTracking(True)
self.labels[txt].move(x * 72 + 21, y * 72 + 21)
# 커서 이미지
pixmap = QPixmap('Python_workspace\\mini_game\\image_dir\\neko_cursor.png')
self.cursor_image = QLabel(self)
self.cursor_image.setPixmap(pixmap)
self.cursor_image.move(24, 24)
# 배경 이미지
oImage = QImage('Python_workspace\\mini_game\\image_dir\\neko_bg.png')
sImage = oImage.scaled(QSize(912, 768))
palette = QPalette()
palette.setBrush(10, QBrush(sImage))
self.setPalette(palette)
self.cat_img = [None] * 8
# 고양이 이미지
for i in range(1,7):
self.cat_img[i] = QPixmap(f'Python_workspace\\mini_game\\image_dir\\neko{i}.png')
self.cat_img[7] = QPixmap('Python_workspace\\mini_game\\image_dir\\neko_niku.png')
def mouseMoveEvent(self, e):
self.mouse_x = e.x()
self.mouse_y = e.y()
self.visualize_cursor()
def mousePressEvent(self, e):
if self.neko[self.cursor_y][self.cursor_x] == 0:
if (24 <= self.mouse_x) and (self.mouse_x < 24 + 72 * 8) and (24 <= self.mouse_y) and (self.mouse_y < 24 + 72 * 10):
if self.over_neko() == False:
self.neko[self.cursor_y][self.cursor_x] = self.tsugi
self.tsugi = random.randint(1, 6)
self.set_neko()
self.draw_next()
else:
for y in range(10):
for x in range(8):
self.neko[y][x] = 0
self.score = 0
self.tsugi = 0
self.high_score_label.setText(str(self.high_score))
def visualize_cursor(self):
if (24 <= self.mouse_x) and (self.mouse_x < 24 + 72 * 8) and (24 <= self.mouse_y) and (self.mouse_y < 24 + 72 * 10):
self.cursor_x = int((self.mouse_x - 24) / 72)
self.cursor_y = int((self.mouse_y - 24) / 72)
self.cursor_image.move(self.cursor_x * 72 + 21, self.cursor_y * 72 + 21)
@pyqtSlot()
def draw_cat(self):
for y in range(10):
for x in range(8):
txt = str(x) + str(y)
if self.neko[y][x] > 0:
img = self.cat_img[self.neko[y][x]]
self.labels[txt].setPixmap(img)
else:
self.labels[txt].setPixmap(QPixmap())
@pyqtSlot(int)
def ScoreDisplay(self, sc):
self.score += sc
self.scorelabel.setText(str(self.score))
def check_neko(self):
for y in range(10):
for x in range(8):
self.check[y][x] = self.neko[y][x]
for y in range(1, 9):
for x in range(8):
if self.check[y][x] > 0:
if self.check[y - 1][x] == self.check[y][x] and self.check[y + 1][x] == self.check[y][x]:
self.neko[y - 1][x] = 7
self.neko[y][x] = 7
self.neko[y + 1][x] = 7
for y in range(10):
for x in range(1, 7):
if self.check[y][x] > 0:
if self.check[y][x - 1] == self.check[y][x] and self.check[y][x + 1] == self.check[y][x]:
self.neko[y][x - 1] = 7
self.neko[y][x] = 7
self.neko[y][x + 1] = 7
for y in range(1, 9):
for x in range(1, 7):
if self.check[y][x] > 0:
if self.check[y - 1][x - 1] == self.check[y][x] and self.check[y + 1][x + 1] == self.check[y][x]:
self.neko[y - 1][x - 1] = 7
self.neko[y][x] = 7
self.neko[y + 1][x + 1] = 7
if self.check[y + 1][x - 1] == self.check[y][x] and self.check[y - 1][x + 1] == self.check[y][x]:
self.neko[y + 1][x - 1] = 7
self.neko[y][x] = 7
self.neko[y - 1][x + 1] = 7
def sweep_neko(self):
num = 0
for y in range(10):
for x in range(8):
if self.neko[y][x] == 7:
self.neko[y][x] = 0
num = num + 1
return num
def over_neko(self):
for x in range(8):
if self.neko[0][x] > 0:
if self.high_score < self.score:
self.high_score = self.score
return True
return False
def draw_next(self):
if self.tsugi > 0:
self.next_cat.setPixmap(self.cat_img[self.tsugi])
def set_neko(self):
result = [random.randint(0, 7) for i in range(4)]
for x in result:
self.neko[0][x] = random.randint(0, 6)
class Cat(QThread):
psignal = pyqtSignal()
scoresig = pyqtSignal(int)
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
def run(self):
while(True):
self.drop_cat()
self.psignal.emit()
if self.drop_cat() == False:
self.parent.check_neko()
sc = self.parent.sweep_neko()
self.scoresig.emit(sc * 10)
time.sleep(0.1)
def drop_cat(self):
flg = False
for y in range(8, -1, -1):
for x in range(8):
if self.parent.neko[y][x] != 0 and self.parent.neko[y + 1][x] == 0:
self.parent.neko[y + 1][x] = self.parent.neko[y][x]
self.parent.neko[y][x] = 0
flg = True
return flg
if __name__ == "__main__":
app = QApplication(sys.argv)
main_W = WindowClass()
sys.exit(app.exec_())
저번에 한 것에 마무리로 최고 점수와 블럭이 3개 이상 이어졌으면 사라지게하는 것을 추가했으며, 난이도 조정을 위해 클릭 할 때마다 랜덤으로 4개 열에 랜덤한 고양이가 떨어지는 것을 추가했고, 다음으로 나올 고양이가 무엇인지 알 수 있게 되었다.
원래 책에서는 인덱스에 따른 진행을 사용했는데 여기서는 나는 그 방법을 쓰지 않았다.