面向对象解决跳马问题

  • 面向对象
    • 什么是面向对象
    • 概念
    • 语法
  • 跳马问题
    • 问题
    • 解析
  • 源码参考
  • 本文参考资料

面向对象

什么是面向对象

面向对象的程序设计(Object Oriented Programming,OOP)简单来说就是以对象为中心来设计和开发程序,也就是说将实现的软件需求抽象成不同的对象和对象之间的交互过程。

概念

仅本问题涉及,并非全部概念
类:类就是类别或者类型,是用来定义对象的。
对象:对象是类的实例化,是以类为模板创造出来的。

eg:公元XXXX年,我们实现了可以用AI机器人作为自己的npy,此时单身了18年的张三,想找一个npy。此时张三有自己的择偶标准1,但是却找不到完全和自己的标准一致的,所以这时候就按照自己的标准用AI机器人创造了一个自己理想中的npy2

语法

class Npy(Object):pass
# Npy: 类的名字(可以随便换)
# Object: 父类名字(一般用Object)

跳马问题

问题

在一个n*m的棋盘上,P点上有一个中国象棋的马,Q点为马运动的终点。规定马只能往右走,求马从P到Q的路径数

解析

  • 捋清楚有哪几个对象,他们都能干些什么事情

    • 智能棋盘, 棋子
    • 棋盘:计算上面的棋子运动的所有路径,并找出符合要求的路径
    • 棋子:运动
  • 如何抽象出这些对象
    • 可以用类来抽象
    • 具体的某一个点可以用一组列表[x, y]来表达
  • 找出路径
    • 只要某一点[x, y]与终点的表达相同,那么就有一条路径符合要求。所以只要暴力枚举就能找到全部路径。

给出以下四个步骤

  • 第一步:让点动起来
    我们的点的的表达是[x, y],它的本质是一个列表,所以我们通过修改里面的数据达到让点动起来的效果。
    eg:[0, 0] -> [1, 2] ->[2, 4]
def move(points: list, x, y):res, lis = list(), points[:] # 保护原本的数据,防止出错# 让点动起来lis[0] += xlis[1] += yres.append(lis[:])return res
  • 然而实际棋盘是有边界的,所以我们应该加一个限制条件,防止它跳出棋盘。
def move(points: list, x, y, args: list):res, lis = list(), points[:]lis[0] += xlis[1] += yif (((lis[0] <= args[0]) and (lis[0] >= 0))and((lis[1] <= args[1]) and (lis[1] >= 0))):res.append(lis[:])return res
# args: 棋盘的大小,if中第一行限制棋的横坐标,第二行限制棋的纵坐标,使二者均在范围内。
  • 第二步:抽象出“点”类
    首先,这个点要知道自己的坐标
    其次,这个点的坐标要让棋盘知道
    所以得出以下代码:
class Point(Object):# __init__方法会在一个对象创建的时候自行调用,这时候我们只需要把它的位置"告诉"它就好了(参数输入)def __init__(self, *args):self.args = args # 函数中的参数前加一个*就变为一个不定参,其本质为一个元组(tuple)def givepoint(self):return list(self.args)# "告诉"棋盘自身"位置",并将不可修改的元组变为可修改的列表,便于前文所述的让点动起来。
  • 第三步:抽象出“棋盘”类
  1. 一个棋盘一定会有一个边界,而且这个棋盘能知道棋子的起点和终点位置
class CheckerBoard(object):def __init__(self, *args):self.args = argsdef findpoint(self, obj1, obj2):lis1, lis2, res = obj1.givepoint(), obj2.givepoint(), list()res.append(lis1)res.append(lis2)return tuple(res)# 用元组来保证起点终点不会被修改

2.这个棋盘能计算棋子所有的可能落点

    # 这是写在CheckerBoard类下的一段方法def getpoints(self, ways: list, func, args: tuple):lis, res = ways[:], list()for i in lis:# 棋子分别在四个方向上的可能出现落点res.append(func(i, 1, 2, args))res.append(func(i, 2, 1, args))res.append(func(i, 2, -1, args))res.append(func(i, 1, -2, args))return res
  • 但是,当棋子在顶点上时,只有两个方向可以运动(O->O1和O->O2)
    |___| O1|___|
    |___|___| O2|
    | -O |___|___|
    那么返回的列表会变成**[[x1, y1], [x2, y2], [], []]**
    这多出的空列表会导致下一次点的移动报错,所以要把空列表去掉。

    • 由于空列表的bool值是False,所以可以用for和if语句游历整个列表,并只保留列表中的非空列表(这话貌似很绕=_=||)
    # 这是写在CheckerBoard类下的一段方法def getpoints(self, ways: list, func, args: tuple):lis, res = ways[:], list()for i in lis:res.append(func(i, 1, 2, args))res.append(func(i, 2, 1, args))res.append(func(i, 2, -1, args))res.append(func(i, 1, -2, args))lis, res = res[:], list()for i in lis:if i:res.append(i[0])return res
  1. 最后只要让棋盘统计有多少个点经过了目标位置就好了
    # 这是写在CheckerBoard类下的一段方法def count(self, func, *point):way, ways, t = point[:], [], 0u = max(abs(point[0][0][0] - point[0][1][0]),abs(point[0][0][1] - point[0][1][1])) - 1 # 计算步骤最多要执行几次# 第一步的计算与后面步骤不同,由于ways创建时为空列表,会导致程序跑不起来,所以只能单独列出ways.append(func(way[0][0], 1, 2, self.args))ways.append(func(way[0][0], 2, 1, self.args))ways.append(func(way[0][0], 2, -1, self.args))ways.append(func(way[0][0], 1, -2, self.args))# 将空列表删去,并计算在第一步是否有到达的点res, ways = ways[:], list()for i in res:if i:ways.append(i[0])for i in ways:if (i == way[0][1]):t += 1for i in range(u):ways = self.getpoints(ways, func, self.args)res = []for i in ways:res.append(i)for i in res:if (i == way[0][1]):# 统计第一步之后到达目标点的个数t += 1return t
  • 对于最多执行数u的计算(只要一个简单的代数):
    确保执行次数最多:
    一个点以速度(v)走路程(s)所需的时间为(t),而一个单位时间内执行(x)次,那么执行次数 u = x * t = (x * s) / v
    带入数据:
    这里x=1是不变的,那么只要s最大,v最小,u则是最大的。
    s{max} 为x方向上的路程和y方向上的路程取最大值
    v{min} = 1,马走的是“日”字(一个1*2的方格)所以v最小值为1
    ps : 由于第一步是单独执行,不算在后面的执行次数,所以最后要减去1
  • 第四步:创建对象
# 找出需要的数据def findnum(num):lis, res, find = list(num), list(), "1234567890"for i in lis:if (i in find):res.append(i)return resdef set(setObj, question: str, order=1):var1, var2 = map(int, findnum(input(question)))if order:res = setObj(var1, var2)else:res = setObj(var2, var1)return res# 创建对象,进行计算board = set(CheckerBoard, "设置棋盘大小:", 0)p = set(Point, "起点位置:")q = set(Point, "终点位置:")print("共{}种路径".format(board.count(move, board.findpoint(p, q))))
  • 运行结果

源码参考


def move(points: list, x, y, args: list):res, lis = list(), points[:]lis[0] += xlis[1] += yif (((lis[0] <= args[0]) and (lis[0] >= 0))and((lis[1] <= args[1]) and (lis[1] >= 0))):res.append(lis[:])return resclass CheckerBoard(object):def __init__(self, *args):self.args = argsdef findpoint(self, obj1, obj2):lis1, lis2, res = obj1.givepoint(), obj2.givepoint(), list()res.append(lis1)res.append(lis2)return tuple(res)def getpoints(self, ways: list, func, args: tuple):lis, res = ways[:], list()for i in lis:res.append(func(i, 1, 2, args))res.append(func(i, 2, 1, args))res.append(func(i, 2, -1, args))res.append(func(i, 1, -2, args))lis, res = res[:], list()for i in lis:if i:res.append(i[0])return resdef count(self, func, *point):way, ways, t = point[:], [], 0u = max(abs(point[0][0][0] - point[0][1][0]),abs(point[0][0][1] - point[0][1][1])) - 1ways.append(func(way[0][0], 1, 2, self.args))ways.append(func(way[0][0], 2, 1, self.args))ways.append(func(way[0][0], 2, -1, self.args))ways.append(func(way[0][0], 1, -2, self.args))res, ways = ways[:], list()for i in res:if i:ways.append(i[0])for i in ways:if (i == way[0][1]):t += 1for i in range(u):ways = self.getpoints(ways, func, self.args)res = []for i in ways:res.append(i)for i in res:if (i == way[0][1]):t += 1return tclass Point(object):def __init__(self, *args):self.args = argsdef givepoint(self):return list(self.args)if __name__ == "__main__":def findnum(num):lis, res, find = list(num), list(), "1234567890"for i in lis:if (i in find):res.append(i)return resdef set(setObj, question: str, order=1):var1, var2 = map(int, findnum(input(question)))if order:res = setObj(var1, var2)else:res = setObj(var2, var1)return resboard = set(CheckerBoard, "设置棋盘大小:", 0)p = set(Point, "起点位置:")q = set(Point, "终点位置:")print("共{}种路径".format(board.count(move, board.findpoint(p, q))))

本文参考资料

  • 《Python 3.7编程快速入门》(潘中强 薛燚 著)

    • 第5章 类和对象

  1. 这里张三的[择偶标准]就是一个类 ↩︎

  2. 这个npy则是上述的类中的一个对象[一语双关](言外之意就是可以有很多个对象) ↩︎

Python 面向对象解决跳马问题相关推荐

  1. python面向对象的优点_Python面向对象编程——总结面向对象的优点

    Python面向对象编程--总结面向对象的优点 一.从代码级别看面向对象 1.在没有学习类这个概念时,数据与功能是分离的 def exc1(host,port,db,charset): conn=co ...

  2. 面向对象解决了全局变量问题?

    2019独角兽企业重金招聘Python工程师标准>>> 全局变量的应用场景 程序中的某些资源之多能有一个,比如计数器.配置信息.程序运行状态等,而且许多地方需要访问他,那么这个资源就 ...

  3. 这可能是Python面向对象编程的最佳实践

    作者 | 崔庆才 来源 | 进击的Coder(ID:FightingCoder) Python 是支持面向对象的,很多情况下使用面向对象编程会使得代码更加容易扩展,并且可维护性更高,但是如果你写的多了 ...

  4. Python 面向对象 基础

    编程范式概述: 面向过程 和 面向对象 以及函数式编程 面向过程:(Procedure Oriented)是一种以事件为中心的编程思想. 就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实 ...

  5. python对象编程例子-这是我见过最详细的Python面向对象编程!建议收藏!

    原标题:这是我见过最详细的Python面向对象编程!建议收藏! 面向对象编程和函数式编程(面向过程编程)都是程序设计的方法,不过稍有区别. 面向过程编程: 1. 导入各种外部库 2. 设计各种全局变量 ...

  6. python面向对象编程的优点-Python面向对象编程——总结面向对象的优点

    Python面向对象编程--总结面向对象的优点 一.从代码级别看面向对象 1.在没有学习类这个概念时,数据与功能是分离的 def exc1(host,port,db,charset): conn=co ...

  7. python编程基础是什么-Python面向对象编程基础解析(一)

    1.什么是面向对象 面向对象(oop)是一种抽象的方法来理解这个世界,世间万物都可以抽象成一个对象,一切事物都是由对象构成的.应用在编程中,是一种开发程序的方法,它将对象作为程序的基本单元. 2.面向 ...

  8. python面向对象生动讲解_Python面向对象语法精讲

    本专题的内容结构: 第一部分主要是:面向对象基础 第二部分主要是:面向对象进阶 第一部分的结构: unit1:面向对象编程模式: (1),面向对象编程思想 (2),面向对象的三个特征 (3),Pyth ...

  9. 【Python进阶】实战Python面向对象基本编程

    欢迎来到专栏<Python进阶>.在这个专栏中,我们会讲述Python的各种进阶操作,包括Python对文件.数据的处理,Python各种好用的库如NumPy.Scipy.Matplotl ...

  10. Python面向对象中反射和双下的正确用法

    一.反射 反射:程序可以访问,检测和修改它本身状态或行为的一种能力(自省) python面向对象中的反射:通过字符串的形式操作对象相关的属性 python中的一切事物都是对象(都可以使用反射) 四个可 ...

最新文章

  1. python 列表拼接_【Python杂货铺】速学python基础
  2. MySQL实现差集(Minus)和交集(Intersect)
  3. where显示null行_Python 之 MySql“未解之谜”14-- 都是 NULL 惹的祸(下)
  4. 【第一章】MySQL数据概述
  5. JSTL标签使用说明
  6. Spark Structured Steaming 聚合、watermark 以及 window操作,结合输出模式的研究总结
  7. python写给初学者的一封信
  8. 光功率 博科交换机_交换机是否支持查看光模块型号及收发光功率
  9. Android实现序列化方式
  10. 查看linux主机多少位,linux怎么查看系统是32位还是64位的方法
  11. 小孩子爱玩手机学计算机编程好吗,学习编程教育对孩子的哪些重要意义
  12. 【java注解--使用注解封装自动拼接sql 】
  13. Angr-CTF学习笔记11-13
  14. java的默认访问权限_java类的访问权限
  15. java实现qq抢红包_java抢红包功能实现
  16. PHP公众号群发用户过多,公众号四次群发用完怎么办?
  17. matlab 风资源,自己开发的风资源分析工具包WindAnalysis
  18. 【概念】操作手册和用户手册的区别及制作
  19. 纠结建模的话,手绘3D建模提高你的模型制作能力和美术绘制能力
  20. VMP (VMProtect)脱壳

热门文章

  1. Nginx的alias/root/try_files实战
  2. XMind12周的学习使用-变成厉害的人成长记录
  3. 软件测试过程与方法_第4周单元测试
  4. 用Angular实现图片上传问题
  5. 厉害了,苹果应用内购买抽成半年狂赚49亿美元
  6. 第一序列任小粟的能力_《第一序列》陈无敌刚烈正义,自封大圣,可任小粟做不得慈悲唐僧...
  7. 爱因斯坦的逻辑思维题
  8. maya餐具图片_有哪些价格低但是逼格高很文艺又实用的物品呢?
  9. 介词 by during for from
  10. 推广的euclid_欧几里得(Euclid)与拓展的欧几里得算法