如何用python写2048

2048游戏规则:简单的移动方向键让数字叠加,并且获得这些数字每次叠加后的得分,当出现2048这个数字时游戏胜利。同时每次移动方向键时,都会在这个4*4的方格矩阵的空白区域随机产生一个数字2或者4,如果方格被数字填满了,那么就GameOver了。

来一步步的进行剖析:

(1)生成4*4的棋盘, 其中数据结构为列表嵌套列表

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

(2)创建函数random_create, 在棋盘的一个随机位置插入一个数字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)如果随机插入数字的位置已经有内容, 如何解决覆盖原有数字的问题

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

(7)判断棋盘是否可移动

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

(8)判断这个棋盘是否可左右上下移动

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)

棋盘的移动,相加

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

(9)判断游戏的胜利与结束

#判断游戏何时胜利:当棋盘中出现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模块来控制游戏,就可以了。

相关推荐:《Python教程》

下面是完整的代码:

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)

实现双人版的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)

以上是 如何用python写2048 的全部内容, 来源链接: utcz.com/z/537460.html

回到顶部