python3实战--2048游戏

游戏介绍:

这里直接拿百度知道的说明 https://zhidao.baidu.com/question/1994394486771253027.html

2048游戏共有16个格子,初始时会有两个格子上安放了两个数字2,每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方随即出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。系统给予的数字方块不是2就是4,玩家要想办法在这小小的16格范围中凑出“2048”这个数字方块。


游戏分析:

4个操作基本都是一致的,这里我们就只拿向左(按键a)举例:

给定一个4*4的列表,

首先,将所有的大于0的数向该行的左边移动,用一个循环,先用切片切取一行(一列),然后对这行进行一个向左挪移,把不是0的数字左移,后面补0,保证长度为4,然后把这个得到的列表重新给到原来的列表,这样原来的列表就全部按照行靠左排列了。

第二步是将向左排列的列表,取每行,然后每行进行判断,如果相邻的单位相等,就把两个数相加,保存在左边的单元格里面,然后这2个数后面的数全部左移,末尾补0来保证长度为4,循环往复(实际不会有多少次的,一行最多2次相加),这样就得到了一个运算后的列表了。

以上是4个按键的响应和处理事件的思路实现。

然后还需要对操作的合法性进行判断,第一个是16个元素都大于0,而且向左(是指按键a或者其他按键对应的方向)的时候,第一列的4个元素和第二列相邻的都没有相等的,同时第二列与第三列,第三列与第四列都没有,这样的话,向左操作就是不合法的了,输出提示信息告诉玩家不能向左移动了。同理可得其他3个按键的操作判断依据。

游戏结束标志:

1,16个元素中有一个达到了2048就恭喜玩家,然后提示是否继续,如果继续,就保存一个标签,后面不要每次操作就提示是否继续,这样带来的游戏体验就会贼差,所以通过判断该标签就可以了。

2,16个元素,没有任何相邻的元素是相等的,那么游戏无法在任何方向进行移动了,游戏也就结束了,这样玩家挑战2048失败。


该游戏是在终端进行的,终端的输入都是需要按回车之后才执行的,所以这样肯定影响体验的,所以需要响应玩家的键盘输入,这里引入了pygame库,可以直接进行按键的捕获,event.type == KEYDOWN代表着按键按下了,进行响应的逻辑处理,event.type == KEYUP代表按键释放了,释放的时候打印4*4单元格的信息。

至此,整个游戏就完成了,可以在终端直接运行该游戏了。博主在终端试玩了一下,目前没有发现逻辑问题,但是遇到了一个小问题,在一段长时间没有任何操作的情况下,再输入a之后,终端没有响应了,这个只能留待后续对pygame库更清楚之后解决了。


游戏缺省的部分是取最大值,保存到文件中,然后在游戏结束的时候,读取文件中的值,与当前结果最大值进行比较,进行响应的提示。

源码:

"""
this game is 2048
"""
import random
import sys,random,time,pygame
from pygame.locals import  *

pygame.init()
screen = pygame.display.set_mode((6,5))

random_list = [2,2,2,2,2,4]

def add_random_number(lst):
    """random a number from random_list to  4*4 list if the position is 0"""
    while True:
        random_index = random.randint(0,15)
        if lst[random_index] == 0:
            random_number = random.choice(random_list)
            lst[random_index] = random_number
            break
        else:
            continue

def deal_add_left(lst):
    """
    give a ordered list to left,
    this func do add number cal,return list
         4     4     *     *
         2     2     2     *
         2     2     2     *
         8     4     *     *
    ----->
         8     *     *     *
         4     2     *     *
         4     2     *     *
         8     4     *     *

    """
    for i in range(4):
        l = lst[i*4:i*4+4]
        l = func_left(l)
        lst[i*4:i*4+4] = l

def move_to_left(lst):
    """
    give a 4*4 list,return 4 rows number ,every row move to left
    and then return 4*4 list
    """
    for i in range(4):
        l = lst[i*4:i*4+4]
        l = return_lst_left(l)
        lst[i*4:i*4+4] = l

    return lst

def deal_add_right(lst):
    """the same as deal_add_left(lst),
    but this func deal with right operate"""
    for i in range(4):
        l = lst[i*4:i*4+4]
        l = func_right(l)
        lst[i*4:i*4+4] = l

    return lst

def move_to_right(lst):
    """4*4 list ,all rows move to right"""
    for i in range(4):
        l = lst[i*4:i*4+4]
        l = return_lst_right(l)
        lst[i*4:i*4+4] = l

    return lst

def func_left(lst):
    """[2,4,4,2] union the nearly same element to left-> [2,8,2,0]"""
    for i in range(3):
        if lst[i] == lst[i+1] and lst[i] != 0:
            lst[i] = lst[i] << 1
            lst[i+1:4] = lst[i+2:4] + [0]
    return lst

def func_right(lst):
    """[2,4,4,2] union the nearly same element to left-> [0,2,8,2]"""
    for i in range(3,0,-1):
        if lst[i] == lst[i-1] and lst[i] != 0 and lst[i-1] != 0:
            lst[i] = lst[i] << 1
            lst[0:i] =  [0]+lst[0:i-1] 
    return lst

def deal_add_top(lst): 
    """get 4 column from 4*4 list,then do func_left for every column"""
    for i in range(4):
        l = lst[i:16:4]
        l = func_left(l)
        lst[i:16:4] = l
    return lst


def return_lst_left(lst):
    """give a list(4 number),return a list which all number left ordered if it > 0
    [2,0,4,4] ---->[2,4,4,0]"""
    l = []
    for x in lst:
        if x > 0:
            l.append(x)
    l += [0,0,0,0]
    l = l[0:4]
    return l

def move_to_top(lst):
    """the same as move_to_left"""
    for i in range(4):
        l = lst[i:16:4]
        l = return_lst_left(l)
        lst[i:16:4] = l

    return lst

def deal_add_buttom(lst): 
    """the same as move_to_right"""
    for i in range(4):
        l = lst[i:16:4]
        l = func_right(l)
        lst[i:16:4] = l
    return lst

def return_lst_right(lst):
    """give a list(4 number),return a list which all number right ordered if it > 0
    [2,0,4,4] ---->[0,2,4,4]"""
    l = []
    while len(lst) > 0:
        x = lst.pop()
        if x > 0:
            l.append(x)
    l += [0,0,0,0]
    l = l[0:4]
    l.reverse()
    return l

def move_to_buttom(lst):
    """the same as move_to_right"""
    for i in range(4):
        l = lst[i:16:4]
        l = return_lst_right(l)
        lst[i:16:4] = l
    return lst

def print_result(lst):
    """print result as following:
     4     2     *     *
     4     *     *     *
     4     *     *     *
     8     2     *     2
    """
    for i in range(4):
        for j in range(4):
            if lst[i*4+j] == 0:
                print("%6s"%"*",end="")
            else:
                print("%6d"%lst[i*4+j],end="") 
        print()
    print()

def action_a(number_list_test):
    deal_add_left(move_to_left(number_list_test))
def action_d(number_list_test):
    deal_add_right(move_to_right(number_list_test))
def action_w(number_list_test):
    deal_add_top(move_to_top(number_list_test))
def action_s(number_list_test):
    deal_add_buttom(move_to_buttom(number_list_test))

def deal_error_op_s_w(number_list_test):
    """key_s or key_w pressed,judge whether can operate"""
    count = 0 #count number of a element >0 in a list
    for x in number_list_test:
        if x > 0:
            count += 1
    if count == 16: #all element > 0
        cal = 0 #if nearly element is not equal,cal+1;
        #if cal ==12,it stand for no element is equal with it's nearby element
        for i in range(3):
            for j in range(4):
                #compare by row,row 1 compare with row 2
                if number_list_test[i*4+j] == number_list_test[(i+1)*4+j]:
                    return False
                else:
                    cal += 1
        if cal == 12:
            return True
    else:   
        return False

def deal_error_op_a_d(number_list_test):  
    """key_a or key_d pressed,judge whether can operate""" 
    count = 0
    for x in number_list_test:
        if x > 0:
            count += 1
    if count == 16:
        cal = 0 
        for i in range(4):
            for j in range(3):
                #compare by column,column 1 compare with column 2
                if number_list_test[i*4+j] == number_list_test[i*4+j+1]:
                    return False
                else:
                    cal += 1
        if cal == 12:
            return True
    else:   
        return False

def win_game(number_list_test):
    """if one element >= 2048,player win"""
    for x in number_list_test:
        if x >= 2048:
            print("Congratulation on your perfect preformance!")
            return True
    return False


def main1():
    pygame.init()
    screen = pygame.display.set_mode((1,1))
    number_list_test = [
    0,4,0,2,
    2,0,2,0,
    0,2,2,0,
    8,0,0,2,
    ]
    # random.shuffle(number_list_test)
    print_result(number_list_test)
    tag = False#if player reach 2048,save the choice of continue or not
    while True:
        if deal_error_op_s_w(number_list_test) == True and deal_error_op_a_d(number_list_test) == True:
            print("Game over!")
            exit()
        else:
            for event in pygame.event.get():
                if event.type ==KEYDOWN:
                    keys = pygame.key.get_pressed()
                    if keys[97]:#a
                        if deal_error_op_a_d(number_list_test) == False:
                            action_a(number_list_test)
                            add_random_number(number_list_test)
                            # print_result(number_list_test)
                        else:
                            print("cant move to left")
                    elif keys[115]:#s
                        if deal_error_op_s_w(number_list_test) == False:
                            action_s(number_list_test)
                            add_random_number(number_list_test)
                            # print_result(number_list_test)
                        else:
                            print("can't move to buttom")
                    elif keys[119]:#w
                        if deal_error_op_s_w(number_list_test) == False:
                            action_w(number_list_test)
                            add_random_number(number_list_test)
                            # print_result(number_list_test)
                        else:
                            print("can't move to top")
                    elif keys[100]:#d
                        if deal_error_op_a_d(number_list_test) == False:
                            action_d(number_list_test)
                            add_random_number(number_list_test)
                            # print_result(number_list_test)
                        else:
                            print("can't move to right")
                    elif keys[112]: #q
                        #to add move action if needed
                        pass
                    else:
                        exit()
                elif event.type == KEYUP:
                    print_result(number_list_test)
        if tag == False:
            win = win_game(number_list_test)
            if win:
                next = input("continue or not,press y/Y to continue")
                if next == 'y' or next == 'Y':
                    tag = True
                    continue
                else:
                    exit()

if __name__ == "__main__":
    main1()
注明:该游戏也是昨天看同桌rao-j-j开发了2048,然后我拿他的手机试玩了一下之后才开发的,之前根本不知道这个游戏怎么玩的。不完善的地方后续修补了。



  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值