Python_2048(完结)

Python_2048(完结)

前言

本游戏的难点在于四个方向的操作响应.
对四个操作的方向函数进行重新整理.以便更好的阅读与理解

##对行操作
把对行的操作拆分出来.因为四个方向的操作都要用到

# 合并一个列表
def change(rows: list):
    '''函数说明'''
    # 将一行进行合并重排,返回重排后的结果
    # 参数: 要合并重排的列表
    # 返回值: 重排后的列表
    
    # 第一步,先去0
    new_rows = [x for x in rows if x != 0]  # 这里用了列表的推导式生成不含0的列表
 
    '''
    以上代码等价于:
    new_rows = []
    for x in rows:
        if x != 0
        new_rows.append(x)
    '''
    result = []  # 用来存放结果

    # 实现分析:
    '''
    如果只有最后一个数,直接返回
    如果当前的数a与后面的数b相同,则添加a*2到结果列表,并将索引指向b后一个数
    如果当前的数a与后面的数b不相同,则添加a到列表,并将索引指向b
    直到索引指向最后一个数为止
    '''
    i = 0
    while i < len(new_rows):
        if i == (len(new_rows) - 1):
            result.append(new_rows[i])
            i += 1
        elif new_rows[i] != new_rows[i + 1]:
            result.append(new_rows[i])
            i += 1
        else:
            result.append(new_rows[i] * 2)
            i += 2
        while len(result) < 4:
            result.append(0)
    return result

如果将这个函数搞懂,那整个就不难懂了

左移操作

def move_left(grids: list):
    '''函数说明'''
    # 功能: 左移操作响应
    # 参数: 游戏列表
    # 返回值: 是否移动过

    ischanged = False  # 移动标识
    for i in range(4):
        temp = grids[i][:]  # 保存原数据
        grids[i] = change(grids[i])
        if temp != grids[i]:  # 判断与原来的数据有没有改动,从而破定是不是移动过
            ischanged = True
    return ischanged

右移操作

与左移比,唯一的不同就是左右顺序的问题

def move_right(grids):
    ''' 函数说明 '''
    # 功能: 响应右移操作
    # 参数: 游戏列表
    # 返回值: 是否移动过

    ischanged = False  # 移动标识
    for i in range(4):
        temp = grids[i]  # 保存原数据
        grids[i] = change(grids[i][::-1])[::-1]  # 这是的两个反转操作要理解操作前反转,操作后反转即可
        if temp != grids[i]:  # 判断与原来的数据有没有改动,从而破定是不是移动过
            ischanged = True
    return ischanged

上移操作

def move_up(grids):
    ''' 函数说明 '''
    # 功能: 响应上移操作
    # 参数: 游戏列表
    # 返回值: 是否移动过

    ischanged = False  # 移动标识
    for i in range(4):
        temp = [grids[j][i] for j in range(4)]  # 保存原数据
        tempres = change(temp)
        for j in range(4):
            grids[j][i] = tempres[j]
        if temp != tempres:  # 判断与原来的数据有没有改动,从而破定是不是移动过
            ischanged = True
    return ischanged

下移操作

def move_down(grids):
    ''' 函数说明 '''
    # 功能: 响应下移操作
    # 参数: 游戏列表
    # 返回值: 是否移动过

    ischanged = False  # 移动标识
    for i in range(4):
        temp = [grids[j][i] for j in range(4)]  # 保存原数据
        tempres = change(temp[::-1])[::-1]
        for j in range(4):
            grids[j][i] = tempres[j]
        if temp != tempres:  # 判断与原来的数据有没有改动,从而破定是不是移动过
            ischanged = True
    return ischanged

检测结束

for i in range(4):
        # 末填满 可移
        if 0 in grids[i]:
            return False
        # 左右方向可移, 可移
        if grids[i] != change(grids[i]) or grids[i] != change(grids[i][::-1])[::-1]:
            return False

        # 上下方向可移,可移 
        temp = [grids[j][i] for j in range(4)]
        if temp  != change(temp) or temp != change(temp[::-1])[::-1]:
            return False
    return True

主程序

def main():
    grids = []
    for i in range(4):
        grids.append([0, 0, 0, 0])
    init_game(grids)
    ischanged = False
    while 1:
        n = input("请输入操作:")
        if n == "a":
            ischanged = move_left(grids)
        elif n == "d":
            ischanged = move_right(grids)
        elif n == "w":
            ischanged = move_up(grids)
        elif n == "s":
            ischanged = move_down(grids)
        else:  # 按键不符合要求跳过
            continue
        if ischanged:
            # 移动过才添加新的数,否则,保持不变
            print("移动过")
            add_num(grids)
            isover = check_game(grids)
            if isover:
                print("游戏失败")
                break
        else:
            print("没有移动过")
        draw_grids(grids)

完整示例代码

from random import randint

'''程序说明'''
# 本程序实现了2048小游戏的命令行版
# 操作说明:a向左滑,d向右滑,w向上滑,s向下滑


def main():
    grids = []
    for i in range(4):
        grids.append([0, 0, 0, 0])
    init_game(grids)
    ischanged = False
    while 1:
        n = input("请输入操作:a向左滑,d向右滑,w向上滑,s向下滑")
        if n == "a":
            ischanged = move_left(grids)
        elif n == "d":
            ischanged = move_right(grids)
        elif n == "w":
            ischanged = move_up(grids)
        elif n == "s":
            ischanged = move_down(grids)
        else:  # 按键不符合要求跳过
            continue
        if ischanged:
            # 移动过才添加新的数,否则,保持不变
            print("移动过")
            add_num(grids)
            isover = check_game(grids)
            if isover:
                print("游戏失败")
                break
        else:
            print("没有移动过")
        draw_grids(grids)


# 游戏初始化
def init_game(grids):
    ''' 函数说明 '''
    # 用来初始游戏相关
    # grids: 二维四元素列表

    # 调用两次生成数字,参数为2,即生成数字是2数
    add_num(grids, 2)
    add_num(grids, 2)
    # 画游戏界面
    draw_grids(grids)


# 新增数字
def add_num(grids, *args):
    ''' 函数说明 '''
    # 用来往表格新增数字
    # grids: 二维四元素列表
    # *args: 没有参数时,随机生成,有参数时用参数
    i = randint(0, 3)
    j = randint(0, 3)
    while grids[i][j] != 0:
        i = randint(0, 3)
        j = randint(0, 3)

    # 如果args不为空,则用args的参数来作为新增的数
    if args:
        grids[i][j] = args[0]
        return

    num = randint(0, 9)  # 数字2的比例比数字4的比例稍大点.可以通过下述的条件来改变2者之间的比例
    if num < 7:
        grids[i][j] = 2
        return
    else:
        grids[i][j] = 4
        return

# 画格子
def draw_grids(grids):
    '''函数说明'''
    # 将游戏数据显示出来
    # grids:二维四元素列表

    print("#" * 25)  # 上辚框
    for i in range(4):
        for j in range(4):
            print("#" + str(grids[i][j]).rjust(5), end="")  # 格式化输出数字
        print("#")
    print("#" * 25)  # 下边框


# 左移
def move_left(grids: list):
    '''函数说明'''
    # 功能: 左移操作响应
    # 参数: 游戏列表
    # 返回值: 是否移动过

    ischanged = False  # 移动标识
    for i in range(4):
        temp = grids[i][:]  # 保存原数据
        grids[i] = change(grids[i])
        if temp != grids[i]:  # 判断与原来的数据有没有改动,从而破定是不是移动过
            ischanged = True
    return ischanged

# 右移


def move_right(grids):
    ''' 函数说明 '''
    # 功能: 响应右移操作
    # 参数: 游戏列表
    # 返回值: 是否移动过

    ischanged = False  # 移动标识
    for i in range(4):
        temp = grids[i]  # 保存原数据
        grids[i] = change(grids[i][::-1])[::-1]
        if temp != grids[i]:  # 判断与原来的数据有没有改动,从而破定是不是移动过
            ischanged = True
    return ischanged

# 上移


def move_up(grids):
    ''' 函数说明 '''
    # 功能: 响应上移操作
    # 参数: 游戏列表
    # 返回值: 是否移动过

    ischanged = False  # 移动标识
    for i in range(4):
        temp = [grids[j][i] for j in range(4)]  # 保存原数据
        tempres = change(temp)
        for j in range(4):
            grids[j][i] = tempres[j]
        if temp != tempres:  # 判断与原来的数据有没有改动,从而破定是不是移动过
            ischanged = True
    return ischanged

# 下移


def move_down(grids):
    ''' 函数说明 '''
    # 功能: 响应下移操作
    # 参数: 游戏列表
    # 返回值: 是否移动过

    ischanged = False  # 移动标识
    for i in range(4):
        temp = [grids[j][i] for j in range(4)]  # 保存原数据
        tempres = change(temp[::-1])[::-1]
        for j in range(4):
            grids[j][i] = tempres[j]
        if temp != tempres:  # 判断与原来的数据有没有改动,从而破定是不是移动过
            ischanged = True
    return ischanged

# 合并重排操作


def change(rows: list):
    '''函数说明'''
    # 将一行进行合并重排,返回重排后的结果
    # 参数: 要合并重排的列表
    # 返回值: 重排后的列表

    # 第一步,先去0
    new_rows = [x for x in rows if x != 0]  # 这里用了列表的推导式生成不含0的列表
    '''
    以上代码等价于:
    new_rows = []
    for x in rows:
        if x != 0
        new_rows.append(x)
    '''
    result = []  # 用来存放结果

    # 实现分析:
    '''
    如果只有最后一个数,直接返回
    如果当前的数a与后面的数b相同,则添加a*2到结果列表,并将索引指向b后一个数
    如果当前的数a与后面的数b不相同,则添加a到列表,并将索引指向b
    直到索引指向最后一个数为止
    '''
    i = 0
    while i < len(new_rows):
        if i == (len(new_rows) - 1):
            result.append(new_rows[i])
            i += 1
        elif new_rows[i] != new_rows[i + 1]:
            result.append(new_rows[i])
            i += 1
        else:
            result.append(new_rows[i] * 2)
            i += 2
    while len(result) < 4:
        result.append(0)
    return result

# 检测


def check_game(grids):
    for i in range(4):
        # 末填满 可移
        if 0 in grids[i]:
            return False
        # 左右方向可移, 可移
        if grids[i] != change(grids[i]) or grids[i] != change(grids[i][::-1])[::-1]:
            return False
        temp = [grids[j][i] for j in range(4)]
        if temp != change(temp) or temp != change(temp[::-1])[::-1]:
            return False
    return True


if __name__ == '__main__':
    main()

后记

一个简单的控件台小程序,被我们用朴素的方法完成了.
游戏还有很多可以优化与调整的地方
比如:

  • 加入分数的概念
  • 加入反悔的概念
  • 加入中途退出游戏的概念
  • 加入成就的概念
  • 加入2048游戏胜得的概念
    等等.
    创意是无限的.
    这里用一个最简单的示例,起一个抛砖引玉的功能.

编程的世界充满了奇思妙想.
今天是2048,也许,未来还会有其他有意思的游戏.发挥你无穷的想象力,创造属于自己的世界吧

猜你喜欢

转载自blog.csdn.net/weixin_41810846/article/details/111939107
今日推荐