溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

用python制作2048游戲的方法

發(fā)布時(shí)間:2020-08-07 11:32:37 來(lái)源:億速云 閱讀:155 作者:小新 欄目:編程語(yǔ)言

用python制作2048游戲的方法?這個(gè)問(wèn)題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見(jiàn)到的。希望通過(guò)這個(gè)問(wèn)題能讓你收獲頗深。下面是小編給大家?guī)?lái)的參考內(nèi)容,讓我們一起來(lái)看看吧!

2048游戲規(guī)則:簡(jiǎn)單的移動(dòng)方向鍵讓數(shù)字疊加,并且獲得這些數(shù)字每次疊加后的得分,當(dāng)出現(xiàn)2048這個(gè)數(shù)字時(shí)游戲勝利。同時(shí)每次移動(dòng)方向鍵時(shí),都會(huì)在這個(gè)4*4的方格矩陣的空白區(qū)域隨機(jī)產(chǎn)生一個(gè)數(shù)字2或者4,如果方格被數(shù)字填滿了,那么就GameOver了。

來(lái)一步步的進(jìn)行剖析:

(1)生成4*4的棋盤(pán), 其中數(shù)據(jù)結(jié)構(gòu)為列表嵌套列表

field = [[0 for j in range(4)] for i in range(4)]

(2)創(chuàng)建函數(shù)random_create, 在棋盤(pán)的一個(gè)隨機(jī)位置插入一個(gè)數(shù)字2或者4,其中2的幾率大

import random
def random_create():
    i = random.choice(range(4))
    j = random.choice(range(4))
    value = random.choice([2,2,2,4])
    field[i][j] = value

(3)如果隨機(jī)插入數(shù)字的位置已經(jīng)有內(nèi)容, 如何解決覆蓋原有數(shù)字的問(wèn)題

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)將生成的數(shù)據(jù), 通過(guò)圖像畫(huà)出來(lái)

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)矩陣的反轉(zhuǎn)

def invert(field):
    return [row[::-1] for row in field]

(6)矩陣的轉(zhuǎn)秩

def transpose(field):
    return [list(row) for row in zip(*field)]

(7)判斷棋盤(pán)是否可移動(dòng)

def is_row_change(row):
    # row
    # 判斷一行內(nèi)容是否可以移動(dòng)
    def is_change(i):
        # 判斷每?jī)蓚€(gè)元素之間是否可以移動(dòng)
        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)])

(8)判斷這個(gè)棋盤(pán)是否可左右上下移動(dòng)

def is_move_left(field):
    return any([is_row_change(row) for row in field])
def is_move_right(field):
    #  對(duì)于列表元素進(jìn)行反轉(zhuǎn)
    field = invert(field)
    print(field)
    return is_move_left(field)
def is_move_up(field):
    # 對(duì)于列表元素進(jìn)行轉(zhuǎn)置
    field = transpose(field)
    return is_move_left(field)
def is_move_down(field):
    # 反轉(zhuǎn)+ 轉(zhuǎn)置
    field = transpose(field)
    return is_move_right(field)

棋盤(pán)的移動(dòng),相加

def tight(row):   # [2, 0, 2, 0]
# 最快的方式, 通過(guò)排序?qū)崿F(xiàn)...........
    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):
# 如果兩個(gè)值相等, 前一個(gè)元素*2, 后一個(gè)元素改為0。
        if row[i] == row[i+1]:
            row[i] *= 2
            row[i+1] = 0
# 如果覆蓋成功, 就給得分
            global score
            score += row[i]
    return row

棋盤(pán)左右上下移動(dòng)相加

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))]))

(9)判斷游戲的勝利與結(jié)束

#判斷游戲何時(shí)勝利:當(dāng)棋盤(pán)中出現(xiàn)2048時(shí),就代表著游戲勝利
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')

這樣程序的各個(gè)部分就寫(xiě)好了,將各個(gè)部分封裝到一個(gè)類(lèi)里面,再導(dǎo)入curses模塊來(lái)控制游戲,就可以了。

下面是完整的代碼:

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  # 當(dāng)前得分
        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):  # 重置棋盤(pán)
        if self.score > self.highscore:
            self.highscore = self.score  # 更新最高分
        self.score = 0
        # 需求1: 生成4*4的棋盤(pán), 其中數(shù)據(jù)結(jié)構(gòu)選擇列表嵌套列表;
        self.field = [[0 for j in range(self.width)]
                      for i in range(self.height)]
        # 在棋盤(pán)的一個(gè)隨機(jī)位置插入一個(gè)數(shù)字2或者4
        self.random_create()
        self.random_create()
    def random_create(self):
        # 在棋盤(pán)的一個(gè)隨機(jī)位置插入一個(gè)數(shù)字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 + '\n')
        def draw_one_row(row):
            stdscr.addstr("".join('|{:^5}'.format(num) if num != 0 else "|   " for num in row) + '|' + '\n')
        # 清屏
        stdscr.clear()
        stdscr.addstr("2048".center(50, '-') + '\n')
        stdscr.addstr("當(dāng)前分?jǐn)?shù):" + str(self.score) + '\n')
        if self.highscore != 0:
            stdscr.addstr("最高分:" + str(self.highscore) + '\n')
        for row in self.field:
            draw_sep()
            draw_one_row(row)
        draw_sep()
        # 判斷是否贏或者輸
        if self.is_win():
            stdscr.addstr("勝利!!!!" + '\n')
        if self.is_gameover():
            stdscr.addstr("游戲結(jié)束!!!!" + '\n')
        stdscr.addstr(" 游戲幫助: 上下左右鍵  (R)Restart     Q(Quit)")
    def is_win(self):
        return max(chain(*self.field)) >= self.win_value
    def is_gameover(self):
        # 任何方向都不能移動(dòng)的時(shí)候, 游戲結(jié)束
        return not any([self.move_is_possible(direction)
                        for direction in self.moves])
    @staticmethod
    def invert(field):
        # 矩陣進(jìn)行反轉(zhuǎn)
        return [row[::-1] for row in field]
        # print(invert(li))
    @staticmethod
    # 矩陣的轉(zhuǎn)置
    def transpose(field):
        return [list(row) for row in zip(*field)]
    @staticmethod
    def is_row_change(row):
        # row
        # 需求3. 判斷一行內(nèi)容是否可移動(dòng)。
        def is_change(i):  # 0
            # 判斷每?jī)蓚€(gè)元素之間是否可移動(dòng)
            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)])
    # 判斷這個(gè)棋盤(pán)是否可向左移動(dòng)
    def is_move_left(self, field):
        return any([self.is_row_change(row) for row in field])
    def is_move_right(self, field):
        #  對(duì)于列表元素進(jìn)行反轉(zhuǎn)
        field = self.invert(field)
        print(field)
        return self.is_move_left(field)
    def is_move_up(self, field):
        # 對(duì)于列表元素進(jìn)行轉(zhuǎn)置
        field = self.transpose(field)
        return self.is_move_left(field)
    def is_move_down(self, field):
        # 反轉(zhuǎn)+ 轉(zhuǎn)置
        field = self.transpose(field)
        return self.is_move_right(field)
    def move_is_possible(self, direction):  # 'left'
        # 判斷用戶(hù)選擇的方向是否可移動(dòng)
        if direction in self.moves:
            return self.moves[direction](self.field)
        else:
            return False
    # 將棋盤(pán)每一行的非0數(shù)向前移動(dòng), 0向后移動(dòng);
    @staticmethod
    def tight(row):  # [2, 0, 2, 0]
        # 最快的方式, 通過(guò)排序?qū)崿F(xiàn)...........
        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):
            # 如果兩個(gè)值相等, 前一個(gè)元素*2, 后一個(gè)元素改為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'
        # 判斷用戶(hù)選擇的方向是否可移動(dòng)
        if direction in self.movesDict:
            # 判斷是否可移動(dòng)
            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():
        # 初始化棋盤(pán)的操作
        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'
    # 如果當(dāng)前狀態(tài)不是退出, 那么一直執(zhí)行
    while state != 'Exit':
        # 執(zhí)行當(dāng)前狀態(tài)需要操作的內(nèi)容, 并返回, 下一次的狀態(tài)為什么.
        state = state_actions[state]()
curses.wrapper(main)

實(shí)現(xiàn)雙人版的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分?jǐn)?shù):' + str(self.score1) + ' ')
        stdscr.addstr('玩家2分?jǐn)?shù):' + str(self.score2) + '\n')
        for row in self.field1:
            stdscr.addstr('+' + '-----+' * self.width + '\n')
            stdscr.addstr("".join('|{:^5}'.format(num) if num != 0 else "|    " for num in row) + '|' + '\n')
        stdscr.addstr('+' + '-----+' * self.width + '\n')
        if self.is_win1():
            stdscr.addstr('勝利\n')
        if self.is_gameover1():
            stdscr.addstr('游戲結(jié)束\n')
        for row in self.field2:
            stdscr.addstr('+' + '-----+' * self.width + '\n')
            stdscr.addstr("".join('|{:^5}'.format(num) if num != 0 else "|    " for num in row) + '|' + '\n')
        stdscr.addstr('+' + '-----+' * self.width + '\n')
        if self.is_win2():
            stdscr.addstr('勝利\n')
        if self.is_gameover2():
            stdscr.addstr('游戲結(jié)束\n')
        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)

感謝各位的閱讀!看完上述內(nèi)容,你們對(duì)用python制作2048游戲的方法大概了解了嗎?希望文章內(nèi)容對(duì)大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI