python 으로 2048 미니 게임 실현

54944 단어
2048 게임 규칙: 간단 한 이동 방향 키 로 숫자 를 중첩 시 키 고 이 숫자 들 이 중첩 할 때마다 점 수 를 얻 으 며 2048 이라는 숫자 가 나 올 때 게임 이 승리 합 니 다.동시에 방향 키 를 움 직 일 때마다 이 4 * 4 의 격자 행렬 의 공백 구역 에서 무 작위 로 숫자 2 또는 4 가 생 성 됩 니 다. 만약 에 격자 가 숫자 로 채 워 지면 Gameover 는 한 걸음 한 걸음 씩 분석 합 니 다. 1) 4 * 4 의 바둑판 을 생 성 합 니 다. 그 중에서 데이터 구 조 는 목록 모자이크 목록 입 니 다.
field = [[0 for j in range(4)] for i in range(4)]

2) 창설 함수 randomcreate, 바둑판 의 무 작위 위치 에 숫자 2 또는 4 를 삽입 하면 2 확률 이 높 습 니 다.
import random
def random_create():
    i = random.choice(range(4))
    j = random.choice(range(4))
    value = random.choice([2224])
    field[i][j] = value

3) 숫자 를 무 작위 로 삽입 한 위치 에 내용 이 있 으 면 기 존 숫자 를 덮어 쓰 는 문 제 를 어떻게 해결 합 니까?
def random_creat():
    while True:
        i = random.choice(range(4))
        j = random.choice(range(4))
        if li[i][j] == 0:
            li[i][j] = 4 if random.randint(1, 100) > 80 else 2
            break


random_creat()
random_creat()

4) 생 성 된 데 이 터 를 그림 으로 그립 니 다.
def draw_sep():
    print('+-----' * 4 + '+')


def draw_num(row):
    print(''.join('|{:^5}'.format(num) if num != 0 else '|     ' for num in row) + '|')


for row in li:
    draw_sep()
    draw_num(row)
draw_sep()

5) 행렬 의 반전
def invert(field):
    return [row[::-1] for row in field]

6) 행렬 의 등급
def transpose(field):
    return [list(row) for row in zip(*field)]

6) 바둑판 이동 가능 여부 판단
def is_row_change(row):
    # row
    #             
    def is_change(i):
        #                
        if row[i] == 0 and row[i + 1] != 0:
            return True
        if row[i] != 0 and row[i + 1] == row[i]:
            return True
        else:
            return False

    return any([is_change(index) for index in range(len(row) - 1)])

이 바둑판 이 좌우 상하 로 이동 할 수 있 는 지 판단 하 다.
def is_move_left(field):
    return any([is_row_change(row) for row in field])


def is_move_right(field):
    #            
    field = invert(field)
    print(field)
    return is_move_left(field)

def is_move_up(field):
    #           
    field = transpose(field)
    return is_move_left(field)

def is_move_down(field):
    #   +   
    field = transpose(field)
    return is_move_right(field)

7) 바둑판 의 이동 에
def tight(row):   # [2, 0, 2, 0]
    #      ,       ...........
    return sorted(row, key=lambda x: if  x == 0 )
score = 0
#   
def merge(row): # [2,2,0,0]
    # [0,1,2]
    for i in range(len(row)-1):
        #        ,      *2,        0。
        if row[i] == row[i+1]:
            row[i] *= 2
            row[i+1] = 0
            #       ,     
            global score
            score += row[i]
    return row

바둑판 좌우 상하 이동 더하기
    def move_row_left(self, row):
        return self.tight(self.merge(self.tight(row)))

    def move_left(self, field):
        return [self.move_row_left(row) for row in field]

    def move_right(self, field):
        field = self.invert(field)
        return self.invert([self.move_row_left(row) for row in field])

    def move_up(self, field):
        return self.transpose([self.move_row_left(row) for row in self.transpose(field)])

    def move_down(self, field):
        return self.invert(self.transpose([self.move_row_left(row)
                                           for row in self.invert(self.transpose(field))]))

8) 게임 의 승리 와 끝 을 판단 한다
#        :      2048 ,        
def victory(field):
    li = [y for row in li for y in row]
    if max(li) >= 2048:
        print('Victory')
def game_over(filed):
    if all((is_move_left(filed), is_move_right(filed), is_move_up(filed), is_move_down(filed))) == False:
        print('Game Over')   

이렇게 프로그램의 각 부분 을 다 썼 습 니 다. 각 부분 을 하나의 클래스 에 밀봉 한 다음 에 curses 모듈 을 가 져 와 서 게임 을 제어 하면 됩 니 다. 다음은 완전한 코드 입 니 다.
import curses
from itertools import chain
from random import choice


class GameField(object):
    #      
    def __init__(self, width=4, height=4, win_value=8):
        self.width = width
        self.height = height
        self.win_value = win_value
        self.score = 0  #     
        self.highscore = 0  #    
        self.moves = {}
        self.moves['Left'] = self.is_move_left
        self.moves['Right'] = self.is_move_right
        self.moves['Down'] = self.is_move_down
        self.moves['Up'] = self.is_move_up

        self.movesDict = {}
        self.movesDict['Left'] = self.move_left
        self.movesDict['Right'] = self.move_right
        self.movesDict['Down'] = self.move_down
        self.movesDict['Up'] = self.move_up

    def reset(self):  #     
        if self.score > self.highscore:
            self.highscore = self.score  #      
        self.score = 0
        #   1:   4*4   ,               ;
        self.field = [[0 for j in range(self.width)]
                      for i in range(self.height)]

        #                 2  4
        self.random_create()
        self.random_create()

    def random_create(self):
        #                 2  4
        # field[0][3] = 2
        while True:
            i, j = choice(range(self.height)), choice(range(self.width))
            if self.field[i][j] == 0:
                self.field[i][j] = choice([2, 2, 2, 4])
                break

    def draw(self, stdscr):
        def draw_sep():
            stdscr.addstr('+' + "-----+" * self.width + '
'
) def draw_one_row(row): stdscr.addstr("".join('|{:^5}'.format(num) if num != 0 else "| " for num in row) + '|' + '
'
) # stdscr.clear() stdscr.addstr("2048".center(50, '-') + '
'
) stdscr.addstr(" :" + str(self.score) + '
'
) if self.highscore != 0: stdscr.addstr(" :" + str(self.highscore) + '
'
) for row in self.field: draw_sep() draw_one_row(row) draw_sep() # if self.is_win(): stdscr.addstr(" !!!!" + '
'
) if self.is_gameover(): stdscr.addstr(" !!!!" + '
'
) stdscr.addstr(" : (R)Restart Q(Quit)") def is_win(self): return max(chain(*self.field)) >= self.win_value def is_gameover(self): # , return not any([self.move_is_possible(direction) for direction in self.moves]) @staticmethod def invert(field): # return [row[::-1] for row in field] # print(invert(li)) @staticmethod # def transpose(field): return [list(row) for row in zip(*field)] @staticmethod def is_row_change(row): # row # 3. 。 def is_change(i): # 0 # if row[i] == 0 and row[i + 1] != 0: return True if row[i] != 0 and row[i] == row[i + 1]: return True return False return any([is_change(index) for index in range(len(row) - 1)]) # def is_move_left(self, field): return any([self.is_row_change(row) for row in field]) def is_move_right(self, field): # field = self.invert(field) print(field) return self.is_move_left(field) def is_move_up(self, field): # field = self.transpose(field) return self.is_move_left(field) def is_move_down(self, field): # + field = self.transpose(field) return self.is_move_right(field) def move_is_possible(self, direction): # 'left' # if direction in self.moves: return self.moves[direction](self.field) else: return False # 0 , 0 ; @staticmethod def tight(row): # [2, 0, 2, 0] # , ........... return sorted(row, key=lambda x: 1 if x == 0 else 0) def merge(self, row): # [2,2,0,0] # [0,1,2] for i in range(len(row) - 1): # , *2, 0。 if row[i] == row[i + 1]: row[i] *= 2 row[i + 1] = 0 # , self.score += row[i] return row # [4, 0, 0, 0] def move_row_left(self, row): return self.tight(self.merge(self.tight(row))) def move_left(self, field): return [self.move_row_left(row) for row in field] def move_right(self, field): field = self.invert(field) return self.invert([self.move_row_left(row) for row in field]) def move_up(self, field): return self.transpose([self.move_row_left(row) for row in self.transpose(field)]) def move_down(self, field): return self.invert(self.transpose([self.move_row_left(row) for row in self.invert(self.transpose(field))])) def move(self, direction): # 'left' # if direction in self.movesDict: # if self.move_is_possible(direction): self.field = self.movesDict[direction](self.field) self.random_create() return True else: return False def get_user_action(stdscr): action = stdscr.getch() if action == curses.KEY_UP: return 'Up' if action == curses.KEY_DOWN: return 'Down' if action == curses.KEY_LEFT: return 'Left' if action == curses.KEY_RIGHT: return 'Right' if action == ord('r'): return 'Restart' if action == ord('q'): return 'Exit' def main(stdscr): action = stdscr.getch() def init(): # game_field.reset() game_field.draw(stdscr) return 'Game' def game(): game_field.draw(stdscr) action = get_user_action(stdscr) if action == 'Restart': return 'Init' if action == 'Exit': return 'Exit' if game_field.move(action): if game_field.is_win(): return 'Win' if game_field.is_gameover(): return 'GameOver' return 'Game' def not_game(): game_field.draw(stdscr) while True: action = get_user_action(stdscr) if action == 'Restart': return 'Init' if action == 'Exit': return 'Exit' state_actions = { 'Init': init, 'Game': game, 'Win': not_game, 'GameOver': not_game, } game_field = GameField() state = 'Init' # , while state != 'Exit': # , , . state = state_actions[state]() curses.wrapper(main)

2 인용 2048 게임 실현
import curses
import random
from itertools import chain


class GameField(object):
    def __init__(self, width=4, height=4, win_value=2048):
        self.width = width
        self.height = height
        self.win_value = win_value
        self.score1 = 0
        self.score2 = 0
        self.highscore = 0
        self.moves = {}
        self.moves['Left1'] = self.is_left_move
        self.moves['Right1'] = self.is_right_move
        self.moves['Up1'] = self.is_up_move
        self.moves['Down1'] = self.is_down_move
        self.moves['Left2'] = self.is_left_move
        self.moves['Right2'] = self.is_right_move
        self.moves['Up2'] = self.is_up_move
        self.moves['Down2'] = self.is_down_move
        self.movesDict1 = {}
        self.movesDict2 = {}
        self.movesDict1['Left1'] = self.left_move
        self.movesDict1['Right1'] = self.right_move
        self.movesDict1['Up1'] = self.up_move
        self.movesDict1['Down1'] = self.down_move
        self.movesDict2['Left2'] = self.left_move
        self.movesDict2['Right2'] = self.right_move
        self.movesDict2['Up2'] = self.up_move
        self.movesDict2['Down2'] = self.down_move

    def random_create1(self):
        while True:
            i, j = random.randint(0, self.height - 1), random.randint(0, self.width - 1)
            if self.field1[i][j] == 0:
                self.field1[i][j] = random.choice([2, 2, 2, 4])
                break

    def random_create2(self):
        while True:
            i, j = random.randint(0, self.height - 1), random.randint(0, self.width - 1)
            if self.field2[i][j] == 0:
                self.field2[i][j] = random.choice([2, 2, 2, 4])
                break

    def reset(self):
        self.field1 = [[0 for j in range(self.width)] for i in range(self.height)]
        self.score1 = 0
        self.field2 = [[0 for j in range(self.width)] for i in range(self.height)]
        self.score2 = 0
        self.random_create1()
        self.random_create1()
        self.random_create2()
        self.random_create2()

    def draw(self, stdscr):
        stdscr.clear()
        self.score1 = sum(chain(*self.field1))
        self.score2 = sum(chain(*self.field2))
        if max(self.score1, self.score2) > self.highscore:
            self.highscore = max(self.score1, self.score2)
        stdscr.addstr('   :' + str(self.highscore) + ' ')
        stdscr.addstr('  1  :' + str(self.score1) + ' ')
        stdscr.addstr('  2  :' + str(self.score2) + '
'
) for row in self.field1: stdscr.addstr('+' + '-----+' * self.width + '
'
) stdscr.addstr("".join('|{:^5}'.format(num) if num != 0 else "| " for num in row) + '|' + '
'
) stdscr.addstr('+' + '-----+' * self.width + '
'
) if self.is_win1(): stdscr.addstr('
'
) if self.is_gameover1(): stdscr.addstr('
'
) for row in self.field2: stdscr.addstr('+' + '-----+' * self.width + '
'
) stdscr.addstr("".join('|{:^5}'.format(num) if num != 0 else "| " for num in row) + '|' + '
'
) stdscr.addstr('+' + '-----+' * self.width + '
'
) if self.is_win2(): stdscr.addstr('
'
) if self.is_gameover2(): stdscr.addstr('
'
) stdscr.addstr(" 1: 2:wasd (R) (Q) ") def is_win1(self): return max(chain(*self.field1)) >= self.win_value def is_win2(self): return max(chain(*self.field2)) >= self.win_value def is_gameover1(self): return not any([self.is_move_possible1(direction) for direction in self.moves]) def is_gameover2(self): return not any([self.is_move_possible2(direction) for direction in self.moves]) @staticmethod def invert(field): return [row[::-1] for row in field] @staticmethod def transpose(field): return [list(row) for row in zip(*field)] @staticmethod def is_row_change(row): for i in range(len(row) - 1): if row[i] == 0 and row[i + 1] != 0: return True elif row[i] != 0 and row[i] == row[i + 1]: return True else: return False def is_left_move(self, field): return any([self.is_row_change(i) for i in field]) def is_right_move(self, field): return any([self.is_row_change(i) for i in self.invert(field)]) def is_up_move(self, field): return any([self.is_row_change(i) for i in self.transpose(field)]) def is_down_move(self, field): return any([self.is_row_change(i) for i in self.invert(self.transpose(field))]) def is_move_possible1(self, direction): if direction in self.moves: return self.moves[direction](self.field1) else: return False def is_move_possible2(self, direction): if direction in self.moves: return self.moves[direction](self.field2) else: return False @staticmethod def row_move(row): row = sorted(row, key=lambda x: 1 if x == 0 else 0) for i in range(len(row) - 1): if row[i] == row[i + 1]: row[i] *= 2 row[i + 1] = 0 return sorted(row, key=lambda x: 1 if x == 0 else 0) def left_move(self, field): return [self.row_move(i) for i in field] def right_move(self, field): return self.invert([self.row_move(i) for i in self.invert(field)]) def up_move(self, field): return self.transpose([self.row_move(i) for i in self.transpose(field)]) def down_move(self, field): return self.transpose(self.invert([self.row_move(i) for i in self.invert(self.transpose(field))])) def move1(self, direction): if direction in self.movesDict1 and self.is_move_possible1(direction): self.field1 = self.movesDict1[direction](self.field1) self.random_create1() return True else: return False def move2(self, direction): if direction in self.movesDict2 and self.is_move_possible2(direction): self.field2 = self.movesDict2[direction](self.field2) self.random_create2() return True else: return False def get_user_action(stdscr): action = stdscr.getch() if action == curses.KEY_UP: return 'Up1' elif action == curses.KEY_DOWN: return 'Down1' elif action == curses.KEY_LEFT: return 'Left1' elif action == curses.KEY_RIGHT: return 'Right1' elif action == ord('r'): return 'Restart' elif action == ord('q'): return 'Exit' elif action == ord('w'): return 'Up2' elif action == ord('s'): return 'Down2' elif action == ord('a'): return 'Left2' elif action == ord('d'): return 'Right2' def main(stdscr): def init(): game_field.reset() game_field.draw(stdscr) return 'Game' def game(): game_field.draw(stdscr) action = get_user_action(stdscr) if action == 'Restart': return 'Init' if action == 'Exit': return 'Exit' if action in ('Up1', 'Down1', 'Left1', 'Right1'): if game_field.move1(action): if game_field.is_win1(): return 'Win' if game_field.is_gameover1(): return 'GameOver' if action in ('Up2', 'Down2', 'Left2', 'Right2'): if game_field.move2(action): if game_field.is_win2(): return 'Win' if game_field.is_gameover2(): return 'GameOver' return 'Game' def not_game(): game_field.draw(stdscr) while True: action = get_user_action(stdscr) if action == 'Restart': return 'Init' if action == 'Exit': return 'Exit' game_field = GameField() state = 'Init' state_actions = { 'Init': init, 'Game': game, 'Win': not_game, 'GameOver': not_game } while state != 'Exit': state = state_actions[state]() curses.wrapper(main)

좋은 웹페이지 즐겨찾기