热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python大作业100行代码面向对象_两百行代码搞定!使用Python面向对象做个小游戏...

大家好,欢迎来到Python实战专题。我们今天同样实现一个小游戏,这个小游戏非常有名,我想大家都应该玩过。它就是tictactoe

大家好,欢迎来到Python实战专题。

我们今天同样实现一个小游戏,这个小游戏非常有名,我想大家都应该玩过。它就是tic tac toe,我们打开chrome搜索一下就可以直接找到游戏了。format,png

由于我们使用Python来实现,并且不会制作UI界面,所以不会这么好看。虽然不够好看,但是逻辑却是一样的。并且和之前我们做的那些小游戏相比,今天做的这个游戏有一个非常大的特点就是非常适合设计AI。我们只需要用很简单的算法就可以做出一个还不错的ai来。当然我们循序渐进,先从最简单的游戏功能本身开始。

课题

今天的课题就是使用Python编写一个不带UI界面的tic tac toe的小游戏。

这一次,游戏当中会涉及两方,所以我们需要有判断游戏胜负手的相关逻辑。除此之外,由于涉及两个玩家,所以我们需要设计一个AI,让我们可以和电脑进行游戏。最后实现的效果差不多应该是这样的:format,png

也就是在游戏一开始的时候,支持玩家选择参与游戏的两方。这里我们先把AI算法的设计放一放,可以先做出随机选择的弱智AI。

游戏开始之后,双方交替行动,每次执行都会在屏幕上输出相应的具体信息,以及棋盘当前的情况。format,png

知识点

面向对象

tic tac的游戏虽然简单,但是它涉及的内容还是挺多的。需要棋盘,还需要玩家,还需要添加玩家以及执行步骤等等操作。这些逻辑如果不加以封装,全部都写成面向过程的话,会使得代码非常的混乱。很明显的,我们需要使用面向对象,对这些逻辑进行抽象和封装,来达到简化编码以及思考的目的。

我们目前的设计比较简单,也不需要用到继承以及抽象类等等高端的用法,就使用最基本的面向对象定义类就可以了。在Python当中定义一个类非常简单,通过关键字class完成。

比如:class Game:

pass

构造函数

一般来说当我们定义一个类的时候都需要为它设计构造函数,构造函数就是当我们创建这个类的实例的时候调用的方法。它会替我们完成一些初始化的工作。Python当中类的构造函数是__init__,我们直接在类当中实现它即可。class Game:

def __init__(self):

self.board = Board()

self.players = []

self.markers = ['O', 'X']

self.numbers = [1, -1]

比如在上面这个例子当中,我们就为Game这个类做了一些初始化的设定。比如给它赋予一个board以及players等等变量。

类方法

既然是类,自然会有属于类的类方法。类方法的定义和普通函数的定义是一样的,唯一不同的是它写在类的内部,并且第一个参数默认是self。self这个关键字相当于Java当中的this,指代的就是运行的时候调用方法的实例。

比如我们给Game这个类实现一个添加玩家的方法:class Game:

def __init__(self):

self.board = Board()

self.players = []

self.markers = ['O', 'X']

self.numbers = [1, -1]

def add_player(self, player):

if player == 'h' or player == 'human':

self.players.append(HumanPlayer())

elif player == 'r' or player == 'random':

self.players.append(RandomPlayer())

我们看下add_player这个方法内部的逻辑,我们在这个方法当中通过self关键字调用了类实例当中的变量。这就是为什么我们需要设定一个self参数的原因,当我们调用的时候,并不需要理会self这个参数,它是Python自动为我们填充的。

当然我们定义类方法的时候也可以定义没有self参数的方法,只不过这样的方法不再属于类的实例,而属于类本身。我们想要调用的话,只能通过类名来访问。

比如:class Test:

def say():

print("hello world")

在Test这个类当中我们实现了一个没有self关键字的say方法,如果我们通过Test的实例去调用它一定会出错。因为我们在通过实例调用方法的时候,Python会自动为我们把实例作为第一个参数传入。这样就导致了接受和传输的参数对应不上,于是引发报错,如果我们想要调用这个say方法,应该这样:Test.say()

也就是说这个方法不再属于类创建的实例,而属于类本身。可以理解成Java类当中的static关键字修饰的方法。

方法的方法

Python当中对于方法的定义是比较灵活的,我们可以给一个类创建方法,同样也可以在一个方法的内部创建另外一个方法。比如下面这个例子:def outer(arg1, arg2):

def inner(arg1, arg2):

return arg1 + arg2

return inner(arg1, arg2)

由于Python支持函数式编程,所以方法内部的方法还可以实现像是闭包、 装饰器等等功能。不过这里我们用不到那么高端的用法,只需要会最基本的就可以了。最基本的也就是在函数内部定义一个函数,主要在这个inner函数当中是可以使用outer当中的定义的变量的。比如:def outer(arg1):

arg2 = 10

def inner(arg1):

return arg1 + arg2

return inner(arg1)

上述的代码没有问题,不过还有一点需要注意。在inner当中虽然可以访问到outer中定义的参数和变量,但是它是不可以修改的。如果想要修改,需要使用nonlocal关键字声明这是一个外层变量。

比如:def outer(arg1):

arg2 = 10

def inner(arg1):

nonlocal arg2

arg2 += 1

return arg1 + arg2

return inner(arg1)

通过在方法内实现方法,可以进一步简化函数内部代码的逻辑,把一些很复杂的函数功能进行进一步的拆分和简化。了解这个用法,也是后面学习闭包、函数式编程等进阶内容的基础。

尾声

这一次的课题相比之前的,整体的实现难度相差不大,主要是涉及的Python文件变多了,之前都是单文件运行的Python程序。这一次需要编写多个文件,以及这一次引入了面向对象的概念,需要对一些功能进行抽象。所以总体上还是有一定难度的,如果大家做不出来的话,可以点击查看原文,获取我的github地址。

在这一次的项目当中,我们创建的是最简单的随机选择的AI,完全没有任何难度。在接下来的课题当中,我们将会使用一些ai算法,给它加上一些ai,让它变得聪明起来,甚至变得不可战胜。

感兴趣的同学不妨小小期待一下,今天的文章就到这里,感谢你的阅读。如果喜欢本文的话,不妨给个三连吧~



推荐阅读
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 探讨一个显示数字的故障计算器,它支持两种操作:将当前数字乘以2或减去1。本文将详细介绍如何用最少的操作次数将初始值X转换为目标值Y。 ... [详细]
  • Java 中 Writer flush()方法,示例 ... [详细]
  • 本文介绍了如何使用 Spring Boot DevTools 实现应用程序在开发过程中自动重启。这一特性显著提高了开发效率,特别是在集成开发环境(IDE)中工作时,能够提供快速的反馈循环。默认情况下,DevTools 会监控类路径上的文件变化,并根据需要触发应用重启。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • Java 中的 BigDecimal pow()方法,示例 ... [详细]
  • Java 类成员初始化顺序与数组创建
    本文探讨了Java中类成员的初始化顺序、静态引入、可变参数以及finalize方法的应用。通过具体的代码示例,详细解释了这些概念及其在实际编程中的使用。 ... [详细]
  • 本文介绍如何利用动态规划算法解决经典的0-1背包问题。通过具体实例和代码实现,详细解释了在给定容量的背包中选择若干物品以最大化总价值的过程。 ... [详细]
  • 本文详细探讨了Java中的24种设计模式及其应用,并介绍了七大面向对象设计原则。通过创建型、结构型和行为型模式的分类,帮助开发者更好地理解和应用这些模式,提升代码质量和可维护性。 ... [详细]
  • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
author-avatar
一夜知秋50050
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有