Minecraft钻石矿生成定位器②(版本:1.16和1.17的Java版本)

上一篇文章本人详细说明了在游戏中生成钻石矿的流程,这一篇文章将构建代码。

先来看看化简的公式的结果(参考):

\large \begin{bmatrix}x_{d}\\y_{d}\\z_{d}\end{bmatrix} =16\begin{bmatrix}g\left(\frac{x_{0}}{16}\right)\\g\left(\frac{y_{0}}{16}\right)\\0\end{bmatrix} +\begin{bmatrix} f\left(2,c_{3}+\left[16\begin{bmatrix} g\left(\frac{x_{0}}{16}\right) & g\left(\frac{y_{0}}{16}\right) \end{bmatrix}\begin{bmatrix} (f(2,s_{0})>>16<<32)+(f(3,s_{0})<<16>>32)\, | \, 1\\ (f(4,s_{0})>>16<<32)+(f(5,s_{0})<<16>>32)\, | \, 1 \end{bmatrix}\right)\wedge s_{0}\right]>>44\\ f\left(3,c_{3}+\left[16\begin{bmatrix} g\left(\frac{x_{0}}{16}\right) & g\left(\frac{y_{0}}{16}\right) \end{bmatrix}\begin{bmatrix} (f(2,s_{0})>>16<<32)+(f(3,s_{0})<<16>>32)\, | \, 1\\ (f(4,s_{0})>>16<<32)+(f(5,s_{0})<<16>>32)\, | \, 1 \end{bmatrix}\right)\wedge s_{0}\right]>>44\\10\end{bmatrix}\\ f(x,y)=\left\{\begin{aligned} y\wedge c_{1}\&c_{2},x=1\\ f(x-1,y)+11\&c_{2},x>1 \end{aligned}\right.,g(x)=\left\{\begin{aligned} [x],x\geqslant 0\\ [x]-1,x<0 \end{aligned}\right.

其中,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值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金坷垃jin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值