python小游戏

摘要

Python 是一种跨平台的、开源的、免费的、解释型的高级编程语言。它具有丰富的、强大的库,能够把其他语言制作的各种模块很轻松地联结在一起,所以Python 常被称为“胶水”语言。Python 语言近几年发展势头迅猛,应用领域也非常广泛,在Web 编程、图形处理、黑客编程、大数据处理、网络爬虫、科学计算和游戏编程等领域都能找到Python 的应用。Python 语言的研究和发明主要是为了便于学习和应用,因此Python 语言是开源的,并且语法非常简单、容易编写和理解。本文通过对2048小游戏的设计与分析,掌握Python 语言在游戏开发领域的优势。

1 引言

当今社会是一个信息社会,一个知识经济的年代。自从世界上第一台计算机ENIAC于1946年问世到现在,计算机业飞速发展。随着以全球信息网络普及和全球信息共享为标志的“全球信息网络革命”的蓬勃兴起,世界已然进入在计算机信息管理领域的激烈竞争的时代,计算机,自然而然的变成了人们生活中必不可少的一部分。
过去,人们只要是借助电影,电视,音乐等方式来娱乐。而今天,以游戏为代表的电子娱乐正成为主流娱乐方式。因为CPU以及显卡等设备的高速发展,为人们开发出更加炫目多彩的游戏提供了可能。时代的发展,社会的进步,科学技术正以日新月异的速度飞速的向前发展。计算机技术的发展更是迅速而且广泛。可以说,计算机已经涉及到现代绝大部分行业。目前纷繁复杂的游戏软件比比皆是,无论在线的网路游戏还是桌面游戏,二维的还是三维立体空间的,多由单机版游戏孕育而来。学习简单的单机版游戏的制作,有利于初学者了解到游戏制作的理念。目前不论是在国内还是世界范围内,游戏产业都如雨后的春笋,蓬勃发展,越来越多更具娱乐性的游戏产品被开发出来。
为此,本文提出了基于Python语言开发的2048小游戏开发。根据游戏的运行流程及游戏元素的嵌入,将开发分为7个模块:创建游戏窗口及背景、数字块的创建、数字块的移动、游戏达成的提示、游戏失败的提示、游戏的重新开始、游戏分值的显示。

2 2048小游戏开发总体方案设计

2.1 游戏开发资源

目前互联网发展迅速,随之发展了各种强大的编程语言和实时电子游戏研发模块,比如Turtle模块,Turtle库是Python内置的图形化模块,属于标准库之一。由于Python的开源性和语言的流行,使得Python语言日趋成熟,在游戏的编程中提供强大的资源结构。按照游戏工业市场的飞机游戏开发需求,分析游戏的基本功能,在此基础上增加游戏的各类功能模块完善游戏。本设计所用到的编程语言是Python,版本是Python3.8,开发工具为Pycharm,根据现有资源,调用Turtle包,对游戏进行开发、运行及测试。游戏程序编辑、编译、调试、发布所有过程都是基于PC机平台运行。
2.2 游戏开发总体方案
游戏规则很简单,每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。系统给予的数字方块不是2就是4,玩家要想办法在这小小的16格范围中凑出“2048”这个数字方块。
游戏实现的功能如下:创建游戏窗口及背景、数字块的随机出现、数字块的移动、游戏成功失败提醒、游戏的重新开始、游戏分值的显示。软件程序为本设计的最核心的部分,每一个代码块都构成了设计的整体,因此,先由每个小功能入手,分别实现该设计的程序功能,然后封装,调用,在程序的主体中调用封装好的代码块,从而运行整个程序的整体。软件开发结构如图1所示,程序上为面向对象编程,大体上可分成数字块类,窗口显示类、游戏类3大类,再在主程序中继承实例化以及嵌套。
在这里插入图片描述
图1 2048小游戏开发结构图

3 2048小游戏程序详细设计

3.1 程序主函数

程序main函数主要进行定义和继承的相关操作,实现成员函数的定义和成员属性的定义,继承相关函数并添加相关的游戏特性。游戏运行整体流程图如图2所示。游戏运行中判断优先级别,层层嵌套功能模块,检测各项功能和监听游戏的相关事件,譬如监听玩家键盘输入和历史最高分数读取等等,最后运行整体程序。
在这里插入图片描述

3.2 游戏窗口创建功能模块

在游戏窗口实例中,分成两个部分,一个是游戏标题、当前分数、和最大分数,另一个是16个方块。游戏标题、当前分数、最大分数通过计算其各个位置的中心坐标再进行进行背景图的填充。16分方块在设计时需要确定每个方格的中心坐标,再定义一个列表allpos来存储每个16个方块的坐标,再通过循环把每个16个方块的坐标进行填充。

3.3 数字块的随机出现

在游戏刚开始或有游戏方块移动是,都会在空闲的方格中出现2或4数字方块。主要原理是在初始化16个方块时先把每个方块的默认值设置为0,在创建一个block_list列表,判断值为0的加入block_list列表中,再从中随机挑选一个元素,把值设置为2或4。

3.4 数字块的移动

通过监听键盘的上下左右键调用相关数字块移动函数。对相同数字块碰撞进行相加。

3.5 游戏成功失败提醒

游戏成功失败提醒主要是judge方法通过判断数字方块是否还有位置可移动来判断游戏是否失败,当全局变量score达到2048也回提醒玩家游戏成功。

3.6 游戏分值的显示

游戏分值主要是当相同数字块碰撞时,全局变量score会进行增加,并将score在窗口进行回写,当score大于最大分数时,会将score写入score.txt文件。

4 实现代码

4.1 主程序

主程序主要时创建主窗口,注册游戏所需相关图片,allpos列表是设置16个小方块的中心坐标,读取score.txt文件中最高分数的数值,进行游戏的初始化,对键盘上下左右键进行监听,调用相关函数。

1.	if __name__ == '__main__':  
2.	    ms = turtle.Screen()  
3.	    ms.setup(430, 630)  
4.	    ms.bgcolor('gray')  
5.	    ms.title('2048')  
6.	    ms.tracer(0)  
7.	    ms.register_shape('bg.gif')  
8.	    ms.register_shape('title.gif')  
9.	    ms.register_shape('score.gif')  
10.	    ms.register_shape('top_score.gif')  
11.	    block_dic = {}  
12.	    allpos = [(-150, 50), (-50, 50), (50, 50), (150, 50),  
13.	              (-150, -50), (-50, -50), (50, -50), (150, -50),  
14.	              (-150, -150), (-50, -150), (50, -150), (150, -150),  
15.	              (-150, -250), (-50, -250), (50, -250), (150, -250)]  
16.	    flag_win = True  
17.	    flag_win_lose_text = True  
18.	    score = 0  
19.	    with open('.\\score.txt', 'r') as f:  
20.	        top_score = int(f.read())  
21.	    show_score_text = BackGround()  
22.	    win_lose_text = BackGround()  
23.	    game = Game()  
24.	    game.init()  
25.	    game.grow()  
26.	  
27.	    ms.listen()  
28.	    ms.onkey(game.move_up, 'Up')  
29.	    ms.onkey(game.move_down, 'Down')  
30.	    ms.onkey(game.move_left, 'Left')  
31.	    ms.onkey(game.move_right, 'Right')  
32.	    ms.onkey(win_lose_text.win_lose_clear, 'Return')  
33.	    ms.onkey(game.restart, 'space')  
34.	    ms.mainloop()  

4.2 BackGround类

BackGround主要绘制游戏窗口框架和游戏成功失败提示,draw_block方法主要是对16个方块进行背景填充,窗口分割线的绘画,标题图、当前分数、最高分数图片填充。judge方法是游戏失败成功的判断。win_lose_clear方法是当玩家玩到2048分或游戏失败,按提示操作后清楚提示文字。show_score显示当前分数,如果当前分数大于最大分数则写入score.txt文件。

1.	class BackGround(turtle.Turtle):  # 定义一个类,用来画除了数字方块之外的图形  
2.	    def __init__(self):  
3.	        super().__init__()  
4.	        self.penup()  
5.	        self.ht()  
6.	  
7.	    def draw_block(self):  
8.	        self.shape('bg.gif')  # 画出背景方块  
9.	        for i in allpos:  
10.	            self.goto(i)  
11.	            self.stamp()  
12.	        self.color('white', 'white')  # 画出其他背景  
13.	        self.goto(-215, 120)  
14.	        self.begin_fill()  
15.	        self.goto(215, 120)  
16.	        self.goto(215, 110)  
17.	        self.goto(-215, 110)  
18.	        self.end_fill()  
19.	        self.shape('title.gif')  
20.	        self.goto(-125, 210)  
21.	        self.stamp()  
22.	        self.shape('score.gif')  
23.	        self.goto(125, 245)  
24.	        self.stamp()  
25.	        self.shape('top_score.gif')  
26.	        self.goto(125, 170)  
27.	        self.stamp()  
28.	  
29.	    def judge(self):  # 游戏失败及达成2048的提示文字  
30.	        global flag_win, flag_win_lose_text  
31.	        self.color('blue')  
32.	        judge = 0  # 判断是否还有位置可以移动  
33.	        for i in block_dic.values():  
34.	            for j in block_dic.values():  
35.	                if i.num == 0 or i.num == j.num and i.distance(j) == 100:  
36.	                    judge += 1  
37.	        if judge == 0:  # 无位置可移动,游戏失败  
38.	            self.write('     GAME OVER\n重新开始请按空格键', align='center', font=('黑体', 30, 'bold'))  
39.	            flag_win_lose_text = False  
40.	        if flag_win is True:  # 此条件让2048达成的判断只能进行一次  
41.	            for k in block_dic.values():  
42.	                if k.num == 2048:  # 游戏达成  
43.	                    flag_win = False  
44.	                    self.write('     达成2048\n继续游戏请按回车键', align='center', font=('黑体', 30, 'bold'))  
45.	                    flag_win_lose_text = False  
46.	  
47.	    def win_lose_clear(self):  # 游戏失败及达成2048提示文字clear  
48.	        global flag_win_lose_text  
49.	        self.clear()  
50.	        flag_win_lose_text = True  
51.	  
52.	    def show_score(self):  # 分值的显示  
53.	        global score, top_score  
54.	        if score > top_score:  
55.	            top_score = score  
56.	            with open('.\\score.txt', 'w') as f:  
57.	                f.write(f'{top_score}')  
58.	        self.color('white')  
59.	        self.goto(125, 210)  
60.	        self.clear()  
61.	        self.write(f'{score}', align='center', font=('Arial', 20, 'bold'))  
62.	        self.goto(125, 135)  
63.	        self.write(f'{top_score}', align='center', font=('Arial', 20, 'bold'))  

4.3 Block类

Block在初始化时,将每个方块的值设置为0。draw方法是为方块进行值的绘画,dic_draw字典为每个不同数字设置不同的背景颜色。

1.	class Block(turtle.Turtle):  # 数字方块类  
2.	    def __init__(self):  
3.	        super().__init__()  
4.	        self.ht()  
5.	        self.penup()  
6.	        self.num = 0  
7.	  
8.	    def draw(self):  
9.	        self.clear()  
10.	        dic_draw = {2: '#eee6db', 4: '#efe0cd', 8: '#f5af7b',  
11.	                    16: '#fb9660', 32: '#f57d5a', 64: '#f95c3d',  
12.	                    128: '#eccc75', 256: '#eece61', 512: '#efc853',  
13.	                    1024: '#ebc53c', 2048: '#eec430', 4096: '#aeb879',  
14.	                    8192: '#aab767', 16384: '#a6b74f'}  
15.	        if self.num > 0:  # 数字大于0,画出方块  
16.	            self.color(f'{dic_draw[self.num]}')  # 选择颜色  
17.	            self.begin_fill()  
18.	            self.goto(self.xcor()+48, self.ycor()+48)  
19.	            self.goto(self.xcor()-96, self.ycor())  
20.	            self.goto(self.xcor(), self.ycor()-96)  
21.	            self.goto(self.xcor()+96, self.ycor())  
22.	            self.goto(self.xcor(), self.ycor()+96)  
23.	            self.end_fill()  
24.	            self.goto(self.xcor()-48, self.ycor()-68)  
25.	            if self.num > 4:  # 按照数字选择数字的颜色  
26.	                self.color('white')  
27.	            else:  
28.	                self.color('#6d6058')  
29.	            self.write(f'{self.num}', align='center', font=('Arial', 27, 'bold'))  
30.	            self.goto(self.xcor(), self.ycor()+20)  

4.4 Game类

Game类主要是对游戏进行初始化、方块的随机出现、方块的移动、游戏重新开始。init方法就是对游戏进行初始化操作,如背景图的填充和16个方块的初始化。restart方法是游戏重新开始,把游戏恢复到初始状态。grow从数值为0的方块中挑选一个方块设置为2或4。move_up、move_down、move_left、move_rigth方法为玩家每次按上下左右调用的方法,move_up、move_down按列把16个方块切成4列,move_left、move_rigth按行把16放开切成4行。Move方法主要时对方块操作后数字的回写,list_oper为正在对数字放开的操作。

1.	class Game():  
2.	    def init(self):  
3.	        back = BackGround()   # 实例画出游戏的背景  
4.	        back.draw_block()  
5.	        for i in allpos:  # 画出16个海龟对应16个数字块  
6.	            block = Block()  
7.	            block.goto(i)  
8.	            block_dic[i] = block  
9.	  
10.	    def restart(self):  # 重开游戏的方法  
11.	        global score, flag_win_lose_text  
12.	        score = 0  
13.	        for i in block_dic.values():  
14.	            i.num = 0  
15.	            i.clear()  
16.	        win_lose_text.clear()  
17.	        game.grow()  
18.	        flag_win_lose_text = True  # 此flag为游戏达成或失败出现提示语后的判断,要提示语clear后才能继续move  
19.	  
20.	    def grow(self):  # 随机出现一个2或4的数字块  
21.	        block_list = []  
22.	        for i in allpos:  
23.	            if block_dic[i].num == 0:  
24.	                block_list.append(block_dic[i])  # 挑出空白方块的海龟  
25.	        turtle_choice = random.choice(block_list)  # 随机选中其中一个海龟  
26.	        turtle_choice.num = random.choice([2, 2, 2, 2, 2, 4])  # 赋属性num=2/4  
27.	        turtle_choice.draw()  
28.	        win_lose_text.judge()  
29.	        show_score_text.show_score()  
30.	        ms.update()  
31.	  
32.	    def move_up(self):  
33.	        allpos1 = allpos[::4]  # 切片为四列  
34.	        allpos2 = allpos[1::4]  
35.	        allpos3 = allpos[2::4]  
36.	        allpos4 = allpos[3::4]  
37.	        self.move_move(allpos1, allpos2, allpos3, allpos4)  
38.	  
39.	    def move_down(self):  
40.	        allpos1 = allpos[-4::-4]  
41.	        allpos2 = allpos[-3::-4]  
42.	        allpos3 = allpos[-2::-4]  
43.	        allpos4 = allpos[-1::-4]  
44.	        self.move_move(allpos1, allpos2, allpos3, allpos4)  
45.	  
46.	    def move_left(self):  
47.	        allpos1 = allpos[:4]  
48.	        allpos2 = allpos[4:8]  
49.	        allpos3 = allpos[8:12]  
50.	        allpos4 = allpos[12:16]  
51.	        self.move_move(allpos1, allpos2, allpos3, allpos4)  
52.	  
53.	    def move_right(self):  
54.	        allpos1 = allpos[-1:-5:-1]  
55.	        allpos2 = allpos[-5:-9:-1]  
56.	        allpos3 = allpos[-9:-13:-1]  
57.	        allpos4 = allpos[-13:-17:-1]  
58.	        self.move_move(allpos1, allpos2, allpos3, allpos4)  
59.	  
60.	    def move_move(self, allpos1, allpos2, allpos3, allpos4):  
61.	        if flag_win_lose_text is True:  
62.	            count1 = self.move(allpos1)  # 四列或四行依次移动  
63.	            count2 = self.move(allpos2)  
64.	            count3 = self.move(allpos3)  
65.	            count4 = self.move(allpos4)  
66.	            if count1 or count2 or count3 or count4:  # 判断是否有方块移动,有才能继续出现新的数字块  
67.	                self.grow()  
68.	  
69.	    def move(self, pos_list):  
70.	        num_list = []  # 为某一列或行的数字块海龟的坐标  
71.	        for i in pos_list:  
72.	            num_list.append(block_dic[i].num)  #  把这些海龟的NUM形成list  
73.	        new_num_list, count = self.list_oper(num_list)  #  只是list_oper的方法形成新的list  
74.	        for j in range(len(new_num_list)):  # 把新的list依次赋值给对应的海龟.num属性并调用draw()方法  
75.	            block_dic[pos_list[j]].num = new_num_list[j]  
76.	            block_dic[pos_list[j]].draw()  
77.	        return count  
78.	  
79.	    def list_oper(self, num_list):  # num_list的操作,假设其为【2,0,2,2】  
80.	        global score  
81.	        count = True  
82.	        temp = []  
83.	        new_temp = []  
84.	        for j in num_list:  
85.	            if j != 0:  
86.	                temp.append(j)  # temp=[2,2,2]  
87.	        flag = True  
88.	        for k in range(len(temp)):  
89.	            if flag:  
90.	                if k < len(temp)-1 and temp[k] == temp[k+1]:  
91.	                    new_temp.append(temp[k]*2)  
92.	                    flag = False  
93.	                    score += temp[k]  
94.	                else:  
95.	                    new_temp.append(temp[k])  # new_temp=[4,2]  
96.	            else:  
97.	                flag = True  
98.	        for m in range(len(num_list)-len(new_temp)):  
99.	            new_temp.append(0)  # new_temp=[4,2,0,0]  
100.	        if new_temp == num_list:  
101.	            count = False  # 此变量判断num_list没有变化,数字块无移动  
102.	        return(new_temp, count)  

5 总结和展望

本文围绕面向对象的编程思想,基于Python开发2048小游戏,包括创建游戏窗口及背景、数字块的随机出现、数字块的移动、游戏成功失败提醒、游戏的重新开始、游戏分值的显示,并且利用继承的技巧优化了代码。模块以对象划分,有界面模块、数字块模块、游戏模块; 难点在于数字块的移动,判断相同数字块发生碰撞的算法设计。整个软件按照预期目标大致实现了2048小游戏。整个游戏还存在一些不足。比如,如何在多人联网下进行游戏分值排行傍,及时分享自己的战绩等,都需要进一步研究。

参考文献:
[1]耿颖. 使用Python 语言的GUI 可视化编程设计 [J]. 单片机与嵌入式系统应用
[2]黑马程序员. Python 快速编程入门[M]. 北京: 人民邮电出版社, 2018.
[3]刘长龙.python高效开发实战[M] .北京:电子工业出版社,2019.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值