生成接近中心的较小值的矩阵

时间:2016-08-27 15:02:42

标签: java math matrix

我希望生成一个整数矩阵,其边的整数较大,如下所示:

[23] [23] [23] [23] [23] 
[15] [15] [15] [15] [15] 
[10] [10] [10] [10] [10] 
[10] [7] [7] [7] [10] 
[10] [4] [4] [4] [10] 
[10] [3] [3] [3] [10] 
[10] [3] [2] [3] [10] 
[10] [3] [1] [3] [10] 
[10] [3] [1] [3] [10] 
[10] [3] [1] [3] [10] 
[10] [3] [2] [3] [10] 
[10] [3] [3] [3] [10] 
[10] [4] [4] [4] [10] 
[10] [7] [7] [7] [10] 
[10] [10] [10] [10] [10] 
[15] [15] [15] [15] [15] 
[23] [23] [23] [23] [23] `

到目前为止一切顺利!但是,我遇到的问题是保持顶部和底部的最大边缘值与右边缘和左边缘相同,如下所示:

[23] [23] [23] [23] [23] 
[23] [15] [15] [15] [23] 
[23] [10] [10] [10] [23] 
[23] [7] [7] [7] [23] 
[23] [7] [4] [7] [23] 
[23] [7] [3] [7] [23] 
[23] [7] [2] [7] [23] 
[23] [7] [2] [7] [23] 
[23] [7] [2] [7] [23] 
[23] [7] [2] [7] [23] 
[23] [7] [2] [7] [23] 
[23] [7] [3] [7] [23] 
[23] [7] [4] [7] [23] 
[23] [7] [7] [7] [23] 
[23] [10] [10] [10] [23] 
[23] [15] [15] [15] [23] 
[23] [23] [23] [23] [23] 

注意边缘都等于相同的最大数量23.让它们全部等于相同的数字是我遇到麻烦的地方(这是由于长度和宽度不同)。以下是我如何生成矩阵:

public void generateChanceMatrix(){
    double ratio = numPointsX/numPointsY; //The difference in length of x and y

    for (int i = 0; i < numPointsX; i++){ //for each point
        for (int j = 0; j < numPointsY; j++){

            double max = Math.abs((numPointsX /2) - i); // these are responsible for generating larger numbers as you approach the edge
            double max2 = Math.abs((numPointsY /2) - j)* ratio; //this ratio is how i try to even out the difference in length of x and y

            if (max2 > max){ //see if the y axis is larger than the x, choose the larger
                max = max2;
            }

            chanceMatrix[i][j] = (int) Math.pow(2.2, max/2); //make it exponential instead of linear
        }
    }
}

如何调整此值以确保所有边的值接近相同的最大值?对于那些好奇的人,我使用它来生成一个封闭的地图边界的游戏世界,见下文:

Ships flying around the world!

提前致谢!

2 个答案:

答案 0 :(得分:2)

我会根据与边缘的相对距离使用一些插值。即相对距离t在矩阵中间为零,边缘为1。然后你可以根据这个值进行简单的插值:

double relativeDiffX = 2 * abs(i - numPointsX / 2) / (numPointsX - 1);
double relativeDiffY = 2 * abs(j - numPointsY / 2) / (numPointsY - 1);
double t = max(relativeDiffX, relativeDiffY);
//now any interpolation
chanceMatrix[i][j] = (int) Math.pow(2.2, t); //this will produce values between 1 and 2.2

答案 1 :(得分:1)

我按部分解决问题:

  1. 设计一个算法,用增加值填充矩形矩阵(从0到最大宽度,高度)。
  2. 得到的矩阵可以对称重复(首先,通过水平对称,然后通过垂直对称),它应该得到最终的矩阵。
  3. 我们这样做:

    1. 填充算法:

      public int[][] generateChanceMatrix(Function function, int numPointsX, int numPointsY)
      {
              SymetricalMatrix symMatrix=new SymetricalMatrix(numPointsX, numPointsY);
              double r=((double)numPointsY) / numPointsX;
              for (int y=0; y < numPointsY; y++)
              {
                      for (int x=0; x < numPointsX; x++)
                      {
                              double value;
                              if (y <= r * x)
                              {
                                      value=function.getXValue(x);
                              }
                              else
                              {
                                      value=function.getYValue(y);
                              }
                              symMatrix.setCell(x, y, (int)value);
                      }
              }
              return symMatrix.getMatrix();
      }
      
    2. 产生水平和垂直对称矩阵的抽象SymmetricMatrix:

      private class SymetricalMatrix
      {
              private final int[][] matrix;
      
              private final double centerX;
      
              private final double centerY;
      
              private SymetricalMatrix(int width, int height)
              {
                      this.matrix=new int[height][width];
                      this.centerX=width / 2d;
                      this.centerY=height / 2d;
              }
      
              public void setCell(int x, int y, int value)
              {
                      double x1=x / 2d;
                      double y1=y / 2d;
                      this.matrix[(int)(this.centerY + y1)][(int)(this.centerX + x1)]=value;
                      this.matrix[(int)(this.centerY - y1)][(int)(this.centerX + x1)]=value;
                      this.matrix[(int)(this.centerY + y1)][(int)(this.centerX - x1)]=value;
                      this.matrix[(int)(this.centerY - y1)][(int)(this.centerX - x1)]=value;
              }
      
              public int[][] getMatrix()
              {
                      return this.matrix;
              }
      
      }
      
    3. 最后,根据需要改变X和Y函数的抽象:

      private interface Function
      {
              public double getXValue(int x);
      
              public double getYValue(int y);
      }
      
    4. 两个提议的实施:

          private class LinearFunction implements Function
          {
                  private final double kx;
      
                  private final double ky;
      
                  public LinearFunction(int maxValue, int numPointsX, int numPointsY)
                  {
                          this.kx=(double)maxValue / (numPointsX - 1);
                          this.ky=(double)maxValue / (numPointsY - 1);
                  }
      
                  @Override
                  public double getXValue(int x)
                  {
                          return this.kx * x;
                  }
      
                  @Override
                  public double getYValue(int y)
                  {
                          return this.ky * y;
                  }
          }
      
          private class PowerFunction implements Function
          {
                  private final double baseX;
      
                  private final double baseY;
      
                  public PowerFunction(int maxValue, int numPointsX, int numPointsY)
                  {
                          this.baseX=Math.pow(maxValue, 1d / (numPointsX - 1));
                          this.baseY=Math.pow(maxValue, 1d / (numPointsY - 1));
                  }
      
                  @Override
                  public double getXValue(int x)
                  {
                          return Math.pow(this.baseX, x);
                  }
      
                  @Override
                  public double getYValue(int y)
                  {
                          return Math.pow(this.baseY, y);
                  }
          }
      

      嗯,最终结果不是100%准确,因为即使在具有偶数行(或列)的矩阵中,这些值也不是完全对称的。关于四舍五入的事情,我很害怕。 : - (