上一篇文章本人详细说明了在游戏中生成钻石矿的流程,这一篇文章将构建代码。
先来看看化简的公式的结果(参考):
其中,z值需要大量样本统计频率算出加权平均数,10是假定的。另外,公式的x,y,z的顺序在MC是x,z,y。在编辑的时候如果是宽屏编辑这个图片长度很长,因此代码也很长。所以为了简化代码量和追求稳定性还是用视频的方法。话不多说,上C#的代码:
private void CalculateButton_Click(object sender, RoutedEventArgs e)
{
CoordinateAzimuthBlock.Text = "Coordinate azimuth:";
DistanceBlock.Text = "Distance:";
ErrorBlock.Text = "Error:";
// coordinate storage
string[] coordinate = CoordinateBox.Text.Split(new[] { ",", "(", ")" }, StringSplitOptions.None);
if (coordinate.Length == 0)
{
MessageBox.Show("No coordinate numbers' pair, please check out.");
return;
}
double x = Convert.ToDouble(coordinate[1]);
double y = Convert.ToDouble(coordinate[2]);
double z = Convert.ToDouble(coordinate[3]);
// version constant value
int versionconstant;
if (VersionBox.Text == "1.16")
{
versionconstant = 60009;
}
else if (VersionBox.Text == "1.17")
{
versionconstant = 60011;
}
else
{
MessageBox.Show("No version number, please check out.");
return;
}
VersionConstantBlock.Text = versionconstant.ToString();
// c1, c2 defination
long stableconstant1 = 25214903917;
long stableconstant2 = 281474976710655;
// seed constant(s1) solution
long seedconstant;
try
{
seedconstant = Convert.ToInt64(SeedBox.Text) ^ (stableconstant1 & stableconstant2);
}
catch (Exception)
{
MessageBox.Show("No seed number, please check out.");
return;
}
// seed array solution(s2,s3,s4,s5)
long seedconstant_1st = (seedconstant * stableconstant1) + 11;
seedconstant_1st &= stableconstant2;
long seedconstant_2nd = (seedconstant_1st * stableconstant1) + 11;
seedconstant_2nd &= stableconstant2;
long seedconstant_3rd = (seedconstant_2nd * stableconstant1) + 11;
seedconstant_3rd &= stableconstant2;
long seedconstant_4th = (seedconstant_3rd * stableconstant1) + 11;
seedconstant_4th &= stableconstant2;
// A and B solution
long i = ((seedconstant_1st >> 16 << 32) + (seedconstant_2nd << 16 >> 32)) | 1;
long j = ((seedconstant_3rd >> 16 << 32) + (seedconstant_4th << 16 >> 32)) | 1;
ValueIBlock.Text = i.ToString();
ValueJBlock.Text = j.ToString();
// X and Y finding
long block_X = (long)Math.Floor(x / 16);
long block_Y = (long)Math.Floor(y / 16);
XBlock.Text = block_X.ToString();
YBlock.Text = block_Y.ToString();
// block constant(b0,b1) solution
long blockconstant = (16 * block_X * i) + (16 * block_Y * j);
blockconstant ^= Convert.ToInt64(SeedBox.Text);
blockconstant += versionconstant;
long blockconstant0 = blockconstant ^ (stableconstant1 & stableconstant2);
// block arrays(b2,b3) solution
long blockconstant_1st = (blockconstant0 * stableconstant1) + 11;
blockconstant_1st &= stableconstant2;
long blockconstant_2nd = (blockconstant_1st * stableconstant1) + 11;
blockconstant_2nd &= stableconstant2;
// destination X and Y as well as x and y
long destinationblock_X = blockconstant_1st >> 44;
long destinationblock_Y = blockconstant_2nd >> 44;
long absolotecorrdinate_x = block_X * 16 + destinationblock_X;
long absolotecorrdinate_y = block_Y * 16 + destinationblock_Y;
DestinationxBlock.Text = absolotecorrdinate_x.ToString();
DestinationyBlock.Text = absolotecorrdinate_y.ToString();
double distance_x = absolotecorrdinate_x - x;
double distance_y = absolotecorrdinate_y - y;
double distance_z = z - 10;
// measures
double true_distance_xyz = Math.Sqrt(Math.Pow(distance_x, 2) + Math.Pow(distance_y, 2) + Math.Pow(distance_z, 2));
long false_distance_xyz = (long)true_distance_xyz;
double distance_xyz_error = true_distance_xyz - false_distance_xyz;
double true_distance_xy = Math.Sqrt(Math.Pow(distance_x, 2) + Math.Pow(distance_y, 2));
long false_distance_xy = (long)true_distance_xy;
double distance_xy_error = true_distance_xy - false_distance_xy;
double horizon_coordinate_azimuth_2 = 0, horizon_coordinate_azimuth_3 = 0;
if (distance_x / true_distance_xy >= 0 && distance_y / true_distance_xy >= 0)
{
horizon_coordinate_azimuth_2 = (Math.PI / 2) - Math.Acos(distance_x / true_distance_xy);
horizon_coordinate_azimuth_3 = (Math.PI / 2) - Math.Asin(distance_y / true_distance_xy);
}
else if (distance_x / true_distance_xy >= 0 && distance_y / true_distance_xy < 0)
{
horizon_coordinate_azimuth_2 = (Math.PI / 2) + Math.Acos(distance_x / true_distance_xy);
horizon_coordinate_azimuth_3 = (Math.PI / 2) + Math.Abs(Math.Asin(distance_y / true_distance_xy));
}
else if (distance_x / true_distance_xy < 0 && distance_y / true_distance_xy < 0)
{
horizon_coordinate_azimuth_2 = (Math.PI * 3 / 2) - Math.Abs(Math.Acos(distance_x / true_distance_xy));
horizon_coordinate_azimuth_3 = (Math.PI * 3 / 2) - Math.Abs(Math.Asin(distance_y / true_distance_xy));
}
else if (distance_x / true_distance_xy < 0 && distance_y / true_distance_xy >= 0)
{
horizon_coordinate_azimuth_2 = (Math.PI * 3 / 2) + Math.Abs(Math.Acos(distance_x / true_distance_xy));
horizon_coordinate_azimuth_3 = (Math.PI * 3 / 2) + Math.Asin(distance_y / true_distance_xy);
}
double true_horizon_coordinate_azimuth = (horizon_coordinate_azimuth_2 + horizon_coordinate_azimuth_3) / 2;
double false_horizon_coordinate_azimuth = Math.Round(true_horizon_coordinate_azimuth, 5);
double horizon_azimuth_error = true_horizon_coordinate_azimuth - false_horizon_coordinate_azimuth;
double vertical_coordinate_azimuth_2 = Math.Asin(distance_z / true_distance_xyz);
double vertical_coordinate_azimuth_3 = Math.Acos(true_distance_xy / true_distance_xyz);
double true_vertical_coordinate_azimuth = (vertical_coordinate_azimuth_2 + vertical_coordinate_azimuth_3) / 2;
double false_vertical_coordinate_azimuth = Math.Round(true_vertical_coordinate_azimuth, 5);
double vertical_azimuth_error = true_vertical_coordinate_azimuth - false_vertical_coordinate_azimuth;
CoordinateAzimuthBlock.Text += "\nhorizon:" + (180 * false_horizon_coordinate_azimuth / Math.PI).ToString() + "\nvertical:" + (180 * false_vertical_coordinate_azimuth / Math.PI).ToString() + "";
DistanceBlock.Text += false_distance_xyz.ToString();
ErrorBlock.Text += "\nhorizon azimuth:" + (180 * horizon_azimuth_error / Math.PI).ToString() + "\nvertical azimuth:" + (180 * vertical_azimuth_error / Math.PI).ToString() + "\ndistance of xyz:" + distance_xyz_error.ToString() + "\ndistance of xy:" + distance_xy_error.ToString() + ".";
}
}
代码量有点大,但是分的很清楚,前面分得比较开的是计算过程,后面是运用测量学的知识去坐标反算方位角和距离,其中加入了三角函数、求平均值等额外的知识。这里不在范围内就没有注释。但是说明一点,垂直坐标方位角不是计算天顶距。在看代码的时候也要注意弧度和角度的转换。
之所以用到大量的复合运算符是因为每一步计算都要严格按照视频作者的流程,否则就会出现误差大于3个方块的情况。下一篇文章将实际开启游戏专门计算z值。