python之2048

1.生成棋盘

  1. 需求1: 生成4*4的棋盘, 其中数据结构选择列表嵌套列表;

  2. 需求2: 创建函数random_create, 在棋盘的一个随机位置插入一个数字2或者4;

  3. 需求3: 如果随机插入数字的位置已经有内容, 如何解决覆盖原有数字的问题.

  4. 需求4: 将生成的数据, 通过图像画出来;

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

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

在棋盘的随机两个位置重新赋值

random_create()
random_create()
print(field)

def draw_sep():
print(‘+’+ “—–+”*4)
draw_sep()

[0,2,0,2]
def draw_one_row(row):
print(“”.join(‘|{:^5}’.format(num) if num !=0 else “| ” for num in row)+’|’)

draw_one_row([0,2,0,2])

for row in field:
draw_sep()
draw_one_row(row)
draw_sep()

2.判断棋盘是否可移动

矩阵进行反转

li = [[0,0,0], [2,0,4], [0,0,0]]
def invert(field):
return [row[::-1] for row in field]

print(invert(li))

矩阵的转置

def transpose(field):
# *field ==== [1,2,3] [4,5,6] [7,8,9]
# zip(*field) ===== [1,4,7], [2,5,8] [3,6,9]
# list(zip(*field)) ====== [(1, 4, 7), (2, 5, 8), (3, 6, 9)] 但是将来元素需要修改,必须转换为列表
return [list(row) for row in zip(*field)]
print(transpose(li))

row = [0, 0, 2, 2] # 4=====[0,1,2]

print(row)

判断改行的每两个元素是否可移动

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

判断改行是否可移动

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(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 is_over(field):

if name == “main“:
print(is_move_right([[0,0,0], [0,2,0], [0,0,2]]))
assert is_move_right([[0,0,0], [0,2,0], [0,0,2]]) == True
assert is_move_left([[0,0,0], [0,2,0], [0,0,2]]) == True
print(is_move_up([[0,0,0], [0,2,0], [0,0,2]]))
assert is_move_up([[0,0,0], [0,2,0], [0,0,2]]) == True
assert is_move_up([[0,0,0], [0,0,0], [0,0,2]]) == True
assert is_move_up([[0,0,0], [0,0,0], [0,0,0]]) == False
assert is_move_down([[0,0,0], [0,0,0], [0,0,0]]) == False
assert is_move_down([[1,0,0], [0,0,0], [0,0,0]]) == True

3.移动棋盘

将棋盘每一行的非0数向前移动, 0向后移动;

def tight(row): # [2, 0, 2, 0]
# 最快的方式, 通过排序实现………..
return sorted(row, key=lambda x: 1 if x == 0 else 0)

#   # 1). 先拿出列表里面的非0数;
#   new_row = [item for item in row if item != 0]  # [2, 2]

#   # 2). 对于不够的长度补0, 使得总长度不变
#   # len(row) - len(new_row), 表示需要补0的个数;
#   # new_row+=xxx , [2,2,0,0]
#   new_row += [0 for i in range(len(row) - len(new_row))]

#   # 3). 返回生成的新列表  
#   return new_row

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 # [4, 0, 0, 0]

def move_row_left(row):
return tight(merge(tight(row)))

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

def move_right(field):
field = invert(filed)
return invert([move_row_left(row) for row in field])

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

def move_down(field):
return transpose([move_row_right(row) for row in transpose(field)])

if name == “main“:
try:
assert tight([2,0,2,0]) == [2, 2, 0, 0]
assert tight([2,2,2,2]) == [2, 2, 2, 2]
assert tight([0,2,0,0]) == [2, 0, 0, 0]
assert merge([2,4,0,0]) == [2, 4, 0, 0]
assert merge([4,4,0,0]) == [8, 0, 0, 0]
assert merge([2,2,4,4]) == [4, 0, 8, 0]
assert move_row_left([2,2,4,4]) == [4, 8, 0, 0]
print(move_row_left([2,2,4,4]))
except AssertionError as e:
print(e)
else:
print(“测试用例全部通过!”)

4.游戏结束条件

1. 何时用户游戏胜利?(当棋盘中出现num=2048时, 则代表用户胜利)

field = [[2048, 0, 0, 0], [0, 0, 0, 0], [0, 0, 4, 0], [0, 0, 0, 4]]

列表生成式实现4*4的矩阵转换为列表;

if max([item for row in field for item in row ]) >= 2048:
print(‘victory’)
else:
print(“继续游戏”)

导入模块chain方法的方式实现4*4的矩阵转换为列表;

from itertools import chain
if max(chain(*field)) >= 2048:
print(‘victory’)
else:
print(“继续游戏”)

2. 何时game over?(当用户在任何方向都不能移动时, 则代表游戏结束, 用户失败)

代表任何方向都不能移动, 目前返回的是False

def is_gameover():
return not any([is_move_up(field), is_move_down(field), is_move_left(field), is_move_right(field)])

5.2048升级版

import curses
from itertools import chain
from random import choice

import time

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 + '\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("当前分数:" + 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("游戏结束!!!!" + '\n')
    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):
    # *field ==== [1,2,3] [4,5,6] [7,8,9]
    # zip(*field)   =====  [1,4,7], [2,5,8] [3,6,9]
    # list(zip(*field)) ======  [(1, 4, 7), (2, 5, 8), (3, 6, 9)]  但是将来元素需要修改,必须转换为列表
    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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值