dha*_*ech 2 c# arrays subclass multidimensional-array
警告:我是C#newb.除了回答我的问题,如果您在看到我的代码后有任何一般的提示,欢迎他们.
假设我在C#中定义了一个大小为10x10的二维数组:
var arr = new int[10,10];
Run Code Online (Sandbox Code Playgroud)
访问索引超出0-9范围的元素是错误的.在某些应用程序中(例如,某些2D阵列代表世界的游戏),必须"包裹"阵列的边缘.所以举个例子
arr[-1, 0]
Run Code Online (Sandbox Code Playgroud)
实际上会引用arr [9,0]中的元素.
我一直在使用的一种方法是以下课程.我没有将System.Array子类化,因为C#显然禁止这样做.
用法示例:
var grid = new Grid(10,10);
grid.set(-1, 0, 100); // Set element at (-1,0) to value 100.
grid.at(-1,0); // retrieve element at (-1,0)
Run Code Online (Sandbox Code Playgroud)
班级本身:
class Grid
{
public int[,] state;
public int width { get { return state.GetLength(0); } }
public int height { get { return state.GetLength(1); } }
public Grid(int width_init, int height_init)
{
state = new int[width_init, height_init];
}
int mod(int a, int b)
{
if (a >= 0)
return a % b;
else
return (b + a % b) % b;
}
int wrap_x(int x) { return mod(x, width); }
int wrap_y(int y) { return mod(y, height); }
public int at(int x, int y)
{
return state[wrap_x(x), wrap_y(y)];
}
public void set(int x, int y, int val)
{
state[wrap_x(x), wrap_y(y)] = val;
}
// more stuff here...
}
Run Code Online (Sandbox Code Playgroud)
问题:是否有提供此类课程的游戏/创意编码框架?
问题:您能想到mod我在上面可以使用的更简单吗?
为了处理每个元素以及相应的"x"和"y",我使用以下方法:
public void each(Action<int, int, int> proc)
{
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
proc(x, y, state[x, y]);
}
Run Code Online (Sandbox Code Playgroud)
问题:我四处寻找在System.Array上定义的类似方法,但我找不到一个.我错过了吗?
问题:在上面,for(int x = 0; x < width; x++)表达"从零到N由1"的常用成语.有没有一种机制在C#中表达这一点?即我想把上面的内容写成:
width.up_to((x) =>
height.up_to((y) =>
proc(x, y, state[x, y]);
Run Code Online (Sandbox Code Playgroud)
哪里up_to是整数的方法.有没有up_to已定义的东西?
与mapScheme 类似,这里是一个map应用于Func每个元素及其相应索引的方法.它返回一个新的Grid.
public Grid map(Func<int, int, int, int> proc)
{
var grid = new Grid(width, height);
each((x, y, val) => grid.state[x, y] = proc(x, y, val));
return grid;
}
Run Code Online (Sandbox Code Playgroud)
问题:假设我设置了一个子类class World : Grid,它添加了额外的实例变量.上面的问题map是,当在一个实例上调用时World,你得到一个Grid,而不是一个World.我该怎么解决这个问题?这完全是错误的做法吗?也许更好的设计不是子类,Grid而是将其作为实例变量保留World.
对不起,提交时间很长.:-)
更新:我分别问了一个问题upto并得到了一些好的答案.
您可以做的一件事就是过载[,]:
public int this[int x, int y]
{
get { return state[wrap_x(x), wrap_y(y)]; }
set { state[wrap_x(x), wrap_y(y)] = value; }
}
Run Code Online (Sandbox Code Playgroud)
如果您发现语法更合适,那就去吧.
关于你的mod功能,我能提出的最好的建议是使那些变量(a和b)有意义.index而且maxSize你应该这样做.
其他的东西:
state变量应该是私有的.state数组.你的Grid班级成了Grid<T>.[,]过载,你可以摆脱你at和set功能.例:
public Grid(int[,] state)
{
this.state = state;
}
Run Code Online (Sandbox Code Playgroud)
mod 可以对任何值(多次环绕)进行有效修改.例:
int mod(int index, int maxSize)
{
while (index < 0) index += maxSize;
return index % maxSize;
}
Run Code Online (Sandbox Code Playgroud)
结果:
mod(0,10) => 0mod(1,10) => 1mod(-1,10) => 9mod(10,10) => 0mod(-10,10) => 0mod(11,10) => 1mod(-11,10) => 9| 归档时间: |
|
| 查看次数: |
1981 次 |
| 最近记录: |