프로젝트명 : 2048
진행 기간 : 2020 7월 21일 ~ 2020년 7월 22일(2일)
개발 인원 : 3명
사용 기술 : Python
2048
간단한 게임 룰 :
1. 처음 시작할 때는 2 블록이 두 개 존재한다.
2. 키보드를 작동하면 모든 블록이 슬라이딩 한 방향으로 움직일 수 없을 때까지 이동한다.
즉, 위로 슬라이딩할 경우 모든 블록이 위로 이동한다. 슬라이딩 후에는 랜덤한 빈 공간에 2 또는 4 블록이 생성된다.
3. 숫자가 같은 블록이 슬라이딩할 때 부딪치면 블록이 합체되면서 숫자가 두 배가 된다.
예를 들면, 4 블록이 위/아래로 나란히 있을 때 위로 슬라이딩하면 4 블록 2개가 8 블록 하나로 합쳐지고 원래 있던 4 블럭 두개는 사라진다.
4. 위/아래/좌/우 모든 방향으로 슬라이딩을 못하면 게임이 종료되고 반대로 게임이 종료되기 전에 2048 블록을 만들면 성공한다.
개발 환경 : python 3.6
pip install pygame
이 코드를 꼭 cmd 관리자 모드로 열고 써야 코드가 돌아가니 참고해주세요 !
colors.py
GRID_COLOR = "#a39489"
EMPTY_CELL_COLOR = "#c2b3a9"
SCORE_LABEL_FONT = ("Verdana", 24)
SCORE_FONT = ("Helvetica", 36, "bold")
GAME_OVER_FONT = ("Helvetica", 42, "bold")
GAME_OVER_FONT_COLOR = "#ffffff"
WINNER_BG = "#ffcc00"
LOSER_BG = "#a39489"
CELL_COLORS = {
2: "#fcefe6",
4: "#f2e8cb",
8: "#f5b682",
16: "#f29446",
32: "#ff775c",
64: "#e64c2e",
128: "#ede291",
256: "#fce130",
512: "#ffdb4a",
1024: "#f0b922",
2048: "#fad74d"
}
CELL_NUMBER_COLOR = {
2: "#695c57",
4: "#695c57",
8: "#ffffff",
16: "#ffffff",
32: "#ffffff",
64: "#ffffff",
128: "#ffffff",
256: "#ffffff",
512: "#ffffff",
1024: "#ffffff",
2048: "#ffffff"
}
CELL_NUMBER_FONTS = {
2: ("Helvetica", 55, "bold"),
4: ("Helvetica", 55, "bold"),
8: ("Helvetica", 55, "bold"),
16: ("Helvetica", 50, "bold"),
32: ("Helvetica", 50, "bold"),
64: ("Helvetica", 50, "bold"),
128: ("Helvetica", 45, "bold"),
256: ("Helvetica", 45, "bold"),
512: ("Helvetica", 45, "bold"),
1024: ("Helvetica", 40, "bold"),
2048: ("Helvetica", 40, "bold"),
}
2048.py
import tkinter as tk
import colors as c
import random
import pygame
import time
class Game(tk.Frame) :
def __init__(self) :
tk.Frame.__init__(self)
self.grid()
self.master.title('2048')
self.main_grid = tk.Frame(self, bg = c.GRID_COLOR,
bd = 3, width = 600, height = 600)
self.main_grid.grid(pady = (100, 0))
self.make_GUI()
self.playmusic()
self.master.bind("<Left>", self.left)
self.master.bind("<Right>", self.right)
self.master.bind("<Up>", self.up)
self.master.bind("<Down>", self.down)
self.start_game()
self.mainloop()
def make_GUI(self) :
# make grid
self.cells = []
for i in range(4) :
row = []
for j in range(4) :
cell_frame = tk.Frame(self.main_grid,
bg = c.EMPTY_CELL_COLOR,
width = 150, height = 150)
cell_frame.grid(row=i, column=j, padx=5, pady=5)
cell_number = tk.Label(self.main_grid, bg=c.EMPTY_CELL_COLOR)
cell_number.grid(row=i, column=j)
cell_data = {'frame': cell_frame, 'number': cell_number}
row.append(cell_data)
self.cells.append(row)
# 점수 기록
score_frame = tk.Frame(self)
score_frame.place(relx=0.5, y=45, anchor='center')
tk.Label(score_frame, text='Score',
font=c.SCORE_LABEL_FONT).grid(row=0)
self.score_label = tk.Label(score_frame, text='0',
font=c.SCORE_FONT)
self.score_label.grid(row=1)
def start_game(self) :
self.matrix = [[0] * 4 for _ in range(4)]
row = random.randint(0, 3)
col = random.randint(0, 3)
self.matrix[row][col] = 2
self.cells[row][col]["frame"].configure(bg=c.CELL_COLORS[2])
self.cells[row][col]["number"].configure(bg=c.CELL_COLORS[2],
fg=c.CELL_NUMBER_COLOR[2],
font=c.CELL_NUMBER_FONTS[2],
text="2")
while(self.matrix[row][col] != 0) :
row = random.randint(0, 3)
col = random.randint(0, 3)
self.matrix[row][col] = 2
self.cells[row][col]["frame"].configure(bg=c.CELL_COLORS[2])
self.cells[row][col]["number"].configure(bg=c.CELL_COLORS[2],
fg=c.CELL_NUMBER_COLOR[2],
font=c.CELL_NUMBER_FONTS[2],
text="2")
self.score = 0
self.playmusic()
def stack(self) :
new_matrix = [[0] * 4 for _ in range(4)]
for i in range(4) :
fill_position = 0
for j in range(4) :
if self.matrix[i][j] != 0 :
new_matrix[i][fill_position] = self.matrix[i][j]
fill_position += 1
self.matrix = new_matrix
def combine(self) :
for i in range(4) :
for j in range(3) :
if self.matrix[i][j] != 0 and self.matrix[i][j] == self.matrix[i][j+1] :
self.matrix[i][j] *= 2
self.matrix[i][j+1] = 0
self.score += self.matrix[i][j]
def reverse(self) :
new_matrix = []
for i in range(4) :
new_matrix.append([])
for j in range(4) :
new_matrix[i].append(self.matrix[i][3-j])
self.matrix = new_matrix
def transpose(self) :
new_matrix = [[0] * 4 for _ in range(4)]
for i in range(4) :
for j in range(4) :
new_matrix[i][j] = self.matrix[j][i]
self.matrix = new_matrix
def add_new_tile(self) :
if any(0 in row for row in self.matrix) :
row = random.randint(0, 3)
col = random.randint(0, 3)
while(self.matrix[row][col] != 0) :
row = random.randint(0, 3)
col = random.randint(0, 3)
self.matrix[row][col] = random.choice([2, 4])
def update_GUI(self) :
for i in range(4) :
for j in range(4) :
cell_value = self.matrix[i][j]
if cell_value == 0 :
self.cells[i][j]["frame"].configure(bg=c.EMPTY_CELL_COLOR)
self.cells[i][j]["number"].configure(bg=c.EMPTY_CELL_COLOR, text = "")
else :
self.cells[i][j]["frame"].configure(bg=c.CELL_COLORS[cell_value])
self.cells[i][j]["number"].configure(bg=c.CELL_COLORS[cell_value],
fg=c.CELL_NUMBER_COLOR[cell_value], font=c.CELL_NUMBER_FONTS[cell_value],
text=str(cell_value))
self.score_label.configure(text=self.score)
self.update_idletasks()
# 상하좌우 이동 함수
def left(self, event) :
self.stack()
self.combine()
self.stack()
self.add_new_tile()
self.update_GUI()
self.game_over()
def right(self, event) :
self.reverse()
self.stack()
self.combine()
self.stack()
self.reverse()
self.add_new_tile()
self.update_GUI()
self.game_over()
def up(self, event) :
self.transpose()
self.stack()
self.combine()
self.stack()
self.transpose()
self.add_new_tile()
self.update_GUI()
self.game_over()
def down(self, event) :
self.transpose()
self.reverse()
self.stack()
self.combine()
self.stack()
self.reverse()
self.transpose()
self.add_new_tile()
self.update_GUI()
self.game_over()
# 이동 가능한지 판별하는 함수
def horizontal_move_exists(self) :
for i in range(4) :
for j in range(3) :
if self.matrix[i][j] == self.matrix[i][j+1] :
return True
return False
def vertical_move_exists(self) :
for i in range(3) :
for j in range(4) :
if self.matrix[i][j] == self.matrix[i+1][j] :
return True
return False
def game_over(self) :
if any(2048 in row for row in self.matrix) :
game_over_frame = tk.Frame(self.main_grid, borderwidth = 2)
game_over_frame.place(relx=0.5, rely=0.5, anchor='center')
tk.Label(game_over_frame,
text = "You Win!",
bg = c.WINNER_BG,
fg = c.GAME_OVER_FONT_COLOR,
font = c.GAME_OVER_FONT).pack()
self.stopmusic()
elif not any(0 in row for row in self.matrix) and not self.horizontal_move_exists() and not self.vertical_move_exists() :
game_over_frame = tk.Frame(self.main_grid, borderwidth = 3)
game_over_frame.place(relx=0.5, rely=0.5, anchor='center')
tk.Button(game_over_frame,
text =("Game over! \n 당신의 점수는 : %d " % self.score),
bg = c.LOSER_BG,
fg = c.GAME_OVER_FONT_COLOR,
font = c.GAME_OVER_FONT,
command = (self.master.after(3000, lambda: self.master.destroy()))).pack()
#self.master.after(3000, lambda: self.master.destroy())
self.stopmusic()
# 음악은 본인이 원하시는 걸로 넣으시면 됩니다.
def playmusic(self) :
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load("bgm.wav")
pygame.mixer.music.play()
def stopmusic(soundfile) :
"""stop currently playing music"""
pygame.mixer.music.stop()
def main() :
Game()
if __name__ == "__main__" :
main()
결론 : 간단하게 2일만에 완성 할 수 있는 프로젝트를 진행하였다. window와 pygame에 있는 mixer.music.play() 등 다양한 함수를 여러개 사용하며 사용 방법을 익힐 수 있었던 프로젝트이었다.
한계점 :
버튼을 누르면 바로 재실행 되게 하고 싶었으나 버튼의 색이 계속 background에 남게 떠서 버튼 누르면 화면이 n초 뒤에 종료되는 코드로 작성
'Project' 카테고리의 다른 글
[Python] 음성인식 비서 'Javis' 프로젝트 (0) | 2020.10.12 |
---|---|
[R] 사망률 최대 암의 발병 원인 분석 (0) | 2020.09.23 |