Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python:表示包裹自身的方形网格(圆柱体)_Python_Oop - Fatal编程技术网

python:表示包裹自身的方形网格(圆柱体)

python:表示包裹自身的方形网格(圆柱体),python,oop,Python,Oop,我正在为一个包裹在自身上的正方形网格上发生的事情建模(即,如果你走到最高点,你会在最低点结束,就像一个圆柱体;如果你走到右边,你只会碰到边界)。我需要跟踪各种代理的位置、不同点的资源量,并根据某些规则计算代理将移动的方向 最好的建模方法是什么 我是否应该创建一个表示点的类,该类具有返回每个方向上相邻点的方法?如果是这样的话,我可能需要将其设置为可散列的,以便可以将其用作包含完整网格的字典的键(我假设这样的网格应该是一个字典?) 或者我应该创建一个类来描述整个网格,而不是将单个点作为独立对象公开

我正在为一个包裹在自身上的正方形网格上发生的事情建模(即,如果你走到最高点,你会在最低点结束,就像一个圆柱体;如果你走到右边,你只会碰到边界)。我需要跟踪各种代理的位置、不同点的资源量,并根据某些规则计算代理将移动的方向

最好的建模方法是什么

我是否应该创建一个表示点的类,该类具有返回每个方向上相邻点的方法?如果是这样的话,我可能需要将其设置为可散列的,以便可以将其用作包含完整网格的字典的键(我假设这样的网格应该是一个字典?)

或者我应该创建一个类来描述整个网格,而不是将单个点作为独立对象公开

或者我应该只使用常规(x,y)元组,并在其他地方使用允许查找邻居的方法吗

我需要建模的很多东西还没有明确定义。此外,我预计曲面的几何图形可能有一天会发生变化(例如,它可以在两个方向上包裹自己)

编辑:另一个问题:我是否应该将资源数量的信息附加到每个点实例;或者我应该有一个单独的类,它包含按点索引的资源映射

我需要跟踪位置 在各种代理中 不同点的资源,以及 计算代理的方向 将基于某些特定的 规则

对我来说,这听起来像一张图表,尽管我试图在每个问题中看到一张图表。您提到的所有操作(移动、存储资源、查找移动位置)在图形中都非常常见。您还可以轻松地更改拓扑,从圆柱体到圆环体或以任何其他方式

唯一的问题是它比其他表示法占用更多的空间


另一方面,您可以使用创建图形,甚至可能使用一些图形算法来计算代理的位置。

如果您想要一个无需太多工作的hashable
Point
类,可以对tuple进行子类化,并添加您自己的邻居方法

class Point(tuple):
    def r_neighbor(self):
        return Point((self[0] + 1, self[1]))
    def l_neighbor(self): 
        [...]

x = Point((10, 11))
print x
print x.r_neighbor()
元组构造函数需要一个iterable,因此在
点((10,11))
中使用双参数;如果要避免这种情况,可以始终重写
\uuuuu new\uuuuu
(重写
\uuuuuuu init\uuuuuu
是毫无意义的,因为元组是不可变的):

这可能也是应用模块化算法的地方——尽管这实际上取决于您正在做什么:

def __new__(self, x, y, gridsize=100):
    return super(Point, self).__new__(self, (x % gridsize, y % gridsize))
或者启用任意维度网格,并返回到使用
\uuuu new\uuuu
中的元组:

def __new__(self, tup, gridsize=100):
    return super(Point, self).__new__(self, (x % gridsize for x in tup))
关于您关于资源的问题:因为
Point
是一个不可变的类,所以它不适合存储关于可能更改的资源的信息。一个默认的dict会很方便;您不必初始化它

from collections import defaultdict

grid = defaultdict(list)
p = Point((10, 13))
grid[(10, 13)] = [2, 3, 4]
print grid[p]                  # prints [2, 3, 4]
print grid[p.r_neighbor]       # no KeyError; prints []
如果您想要更大的灵活性,可以使用dict而不是defaultdict中的列表;但是
defaultdict(defaultdict)
不起作用;您必须创建一个新的defaultdict工厂函数

def intdict():
    return defaultdict(int)

grid = defaultdict(intdict)
或者更简洁地说

grid = defaultdict(lambda: defaultdict(int))
然后


听起来很像你会使用模数的东西,不管你如何表示地图。用
a[i%len(a)]
索引列表将产生总括。关于你的编辑,请参阅下文谢谢这是一个很好的建议。在这个特殊的例子中,我不能使用它,因为我需要视线的概念(如果我保持x,y坐标的话,定义视线要容易得多),但我会在其他情况下使用它。谢谢,这比定义
\uuuuuuuu散列\uuuuu
方法要好。谢谢你关于存储额外资源的附加注释。除了它的
元组
部分之外,
点本身不是可变的吗?换句话说,如果我向Point添加一个新的实例变量,它不是可以完全更改而不会出现任何微妙的复杂情况吗?简单地说,因为
tuple
中的
子类,
Point
必须是不可变的。简而言之,不可变类型在其
\uuuu new\uuu
函数中设置其属性。一旦完成,它们就不能被更改,即使是通过一个子类。因此,由于
Point
使用tuple的
\uuuuu new\uuuuu
函数(在本例中通过
super
访问)创建实例,因此结果是一个不可变的
点。不变性的好处是它使散列更容易、更一致。如果
是可变的,
的位置可能会改变,但散列不会改变,因此
将散列到
网格
中的相同位置。作为补充,如果您想拥有一个可变的
资源
类,您可以将
作为该类的属性。甚至有办法使
为只读,这样可用资源可以更改,但位置锁定到实例。
grid = defaultdict(lambda: defaultdict(int))
p = Point((10, 13))
grid[(10, 13)]["coins"] = 50
print grid[p]["coins"]              # prints 50
print grid[p.r_neighbor]["coins"]   # prints 0; again, no KeyError