Reputation: 35
I'm currently creating a 2d array to represent elements on a grid to be laid out for a game. I would like to be able to Sum a specific block of elements, but I can't seem to get my function to work correctly, and I suspect there is a far easier way to do this.
Example of Array:
int[6,6] myArray = {{2,1,4,3,1,2,5}
,{4,2,3,3,1,2,4}
,{3,4,9,1,2,7,5}
,{1,6,2,1,3,4,2}
,{2,1,4,6,2,1,0}
,{6,2,8,1,6,5,7}
,{7,6,10,3,9,7,2}};
Current Code:
int BoxSum(int x, int y, int x1, int y1, int [,] arrayM) {
int Results = 0;
int xmod = (x1 - x) / Mathf.Abs (x1 - x);
int ymod = (y1 - y) / Mathf.Abs (y1 - y);
if (x1 > x & y1 > y) {
for (int ix = x; ix <= x1; ix ++) {
for (int iy = y; iy <= y1; iy++) {
Results += arrayM [ix, iy];
}
}
}
if (x1 > x & y1 < y) {
for (int ix = x; ix <= x1; ix ++) {
for (int iy = y; iy <= y1; iy--) {
Results += arrayM [ix, iy];
}
}
}
if (x1 < x & y1 < y) {
for (int ix = x; ix <= x1; ix --) {
for (int iy = y; iy <= y1; iy--) {
Results += arrayM [ix, iy];
}
}
}
if (x1 < x & y1 > y) {
for (int ix = x; ix <= x1; ix ++) {
for (int iy = y; iy <= y1; iy--) {
Results += arrayM [ix, iy];
}
}
}
return Results;
}
So, if I were to enter:
(BoxSum(1,1,5,5,myArray));
or
(BoxSum(5,5,1,1,myArray));
I would want to get 86 for both (independent of whether I enter x,y or x1,y1 first in the command). Right now they give me different results, 86 and 0.
Thank you for your help!
Upvotes: 2
Views: 129
Reputation: 840
If I'm reading your question right you just want one nest for loops so: edit: forgot the bit that sorts out the start and stop positions! Added it. Also taking phoogs suggestion of using math min and max
using System;
public class boxes{
public int[6,6] myArray;
public void boxes(){ // This is just a constructor.
myArray = {{2,1,4,3,1,2,5}
,{4,2,3,3,1,2,4}
,{3,4,9,1,2,7,5}
,{1,6,2,1,3,4,2}
,{2,1,4,6,2,1,0}
,{6,2,8,1,6,5,7}
,{7,6,10,3,9,7,2}};
}
public int BoxSum(int x, int y, int x1, int y1) {
int sum = 0;
int xstart = Math.Min(x1, x);
int ystart = Math.Min(y1, y);
int xend = Math.Max(x1, x);
int yend = Math.Max(y1, y);
for(int i=xstart;i<=xend;i++)
{
for(int j=ystart;j<=yend;j++)
{
sum += myArray[i,j];
}
}
return sum;
}
}
I wrote up a simple class, I'm assuming you have something similar. If the method is a member of the class that has your array in it you won't need to pass it to the method.
Upvotes: 2
Reputation: 43056
None of the existing answers explains why you got the wrong result in one case. The problem is a bug in the block that handles that case:
if (x1 < x & y1 < y) {
for (int ix = x; ix <= x1; ix --) {
for (int iy = y; iy <= y1; iy--) {
Results += arrayM [ix, iy];
}
}
}
It should be:
if (x1 < x & y1 < y) {
for (int ix = x; ix >= x1; ix --) {
for (int iy = y; iy >= y1; iy--) {
Results += arrayM [ix, iy];
}
}
}
This is a great example of why the Don't repeat yourself (DRY) principle is important. Spare yourself the headache and do as the other answers suggest.
Upvotes: 1
Reputation: 1792
If you want it to work regardless of which parameters are the high/low values, you could do something like this.
private int BoxSum(int x, int y, int x1, int y1, int[,] arrayM)
{
int lowestX = (x1 > x) ? x : x1;
int lowestY = (y1 > y) ? y : y1;
int highestX = (x1 > x) ? x1 : x;
int highestY = (y1 > y) ? y1 : y;
int sum = 0;
for (int i = lowestX; i < highestX; i++)
{
for (int j = lowestY; j < highestY; j++)
{
sum += arrayM[i, j];
}
}
return sum;
}
Upvotes: 3