227 lines
4.1 KiB
C++
Vendored
227 lines
4.1 KiB
C++
Vendored
// Demo1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
|
|
//
|
|
|
|
#include <iostream>
|
|
#include <unordered_set>
|
|
#include <unordered_map>
|
|
#include <string>
|
|
#include <variant>
|
|
|
|
#include <cstdint>
|
|
#include <stacktrace>
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
void print(int x, int y, std::string str) {
|
|
COORD p = { x, y };
|
|
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), p);
|
|
std::cout << str;
|
|
}
|
|
|
|
// 2D环形遍历
|
|
// 中心点是数学坐标(0, 0), 每环从右下(N, -N)开始逆时针遍历
|
|
void RingSearch_Next(int& nX, int& nY)
|
|
{
|
|
// 开始
|
|
if (nX == 0 && nY == 0)
|
|
{
|
|
nX = 1;
|
|
nY = -1;
|
|
return;
|
|
}
|
|
|
|
// 下1环(右下)
|
|
if (nY<0 && nX+nY== -1)
|
|
{
|
|
++nX; // 到右下
|
|
|
|
// 下1环
|
|
++nX;
|
|
--nY;
|
|
return;
|
|
}
|
|
|
|
// 右边线(向上)
|
|
if (nY+nX>=0 && nY-nX<0)
|
|
{
|
|
++nY;
|
|
return;
|
|
}
|
|
|
|
// 上边线(向左)
|
|
if (nY - nX >= 0 && nY + nX > 0)
|
|
{
|
|
--nX;
|
|
return;
|
|
}
|
|
|
|
// 左边线(向下)
|
|
if (nY + nX <= 0 && nY - nX > 0)
|
|
{
|
|
--nY;
|
|
return;
|
|
}
|
|
|
|
// 下边线(向右)
|
|
if (nY-nX<=0 && nY+nX<0)
|
|
{
|
|
++nX;
|
|
return;
|
|
}
|
|
|
|
// 无法到这里
|
|
int x = 0;
|
|
x++;
|
|
}
|
|
|
|
|
|
// 2D环形遍历
|
|
// 中心点是数学坐标(0, 0), 每环从右下(N, -N)开始逆时针遍历
|
|
// 根据序号直接计算点坐标
|
|
void RingSearch_Index(int nIndex, int& nX, int& nY)
|
|
{
|
|
// (0, 0) 做为第0环, 且 nIndex=0
|
|
if (nIndex <= 0)
|
|
{
|
|
nX = 0;
|
|
nY = 0;
|
|
return;
|
|
}
|
|
|
|
// 次外层第K环, 共有 (2K+1)*(2K+1)个点
|
|
|
|
// 最外层
|
|
int k = (sqrt(nIndex) + 1) / 2;
|
|
|
|
// 第k环点的序号
|
|
int nIdx = nIndex - (2*k-1)*(2*k-1);
|
|
|
|
// 第k环每条边的点数
|
|
int nL = 2 * k; // 只能包含一个端点
|
|
|
|
// 第几条边的第几个点
|
|
int nD = nIdx / nL;
|
|
int nIdx2 = nIdx % nL;
|
|
|
|
// (下面边的序号对应的边可以随意修改: 代表了不同的遍历方法)
|
|
switch (nD)
|
|
{
|
|
case 0:
|
|
// 第一条边(右)
|
|
nX = k;
|
|
nY = -k;
|
|
|
|
nY += nIdx2;
|
|
break;
|
|
case 1:
|
|
// 第二条边(上)
|
|
nX = k;
|
|
nY = k;
|
|
|
|
nX -= nIdx2;
|
|
break;
|
|
case 2:
|
|
// 第三条边(左)
|
|
nX = -k;
|
|
nY = k;
|
|
|
|
nY -= nIdx2;
|
|
break;
|
|
case 3:
|
|
// 第四条边(下)
|
|
nX = -k;
|
|
nY = -k;
|
|
|
|
nX += nIdx2;
|
|
break;
|
|
default:
|
|
// 出错
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 2D环形遍历
|
|
// 中心点是数学坐标(0, 0), 每环从右下(N, -N)开始逆时针遍历
|
|
// 根据点坐标计算序号(从0开始)
|
|
int GetRingIndex(int nX, int nY)
|
|
{
|
|
if (nX == 0 && nY == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int k = max(abs(nX), abs(nY));
|
|
|
|
// 环内的数量
|
|
int nN = (2 * k - 1) * (2 * k - 1);
|
|
|
|
// 边长
|
|
int nL = 2 * k;
|
|
|
|
if (nX == k && nY != k)
|
|
{
|
|
// 第一边(右)
|
|
nN += (k + nY);
|
|
}
|
|
else if (nY == k && nX != -k)
|
|
{
|
|
// 第二边(上)
|
|
nN += 2*k;
|
|
nN += (k - nX);
|
|
}
|
|
else if (nX == -k && nY != -k)
|
|
{
|
|
// 第三边(左)
|
|
nN += 4 * k;
|
|
nN += (k-nY);
|
|
}
|
|
else if(nY == -k && nX != k)
|
|
{
|
|
// 第四边(下)
|
|
nN += 6 * k;
|
|
nN += (k + nX);
|
|
}
|
|
else
|
|
{
|
|
// 不会到这里
|
|
}
|
|
|
|
return nN;
|
|
}
|
|
|
|
|
|
int main()
|
|
{
|
|
int nX = 0, nY = 0;
|
|
//std::cout << "0 : (" << nX << ", " << nY << ")" << std::endl;
|
|
|
|
int K = 5;
|
|
for (int i = 1; i < (2*K+1)*(2*K+1); i++)
|
|
{
|
|
// 第一种算法
|
|
RingSearch_Next(nX, nY);
|
|
|
|
// 第二种算法
|
|
int nX2, nY2;
|
|
RingSearch_Index(i, nX2, nY2);
|
|
if (nX != nX2 || nY != nY2)
|
|
{
|
|
std::cout << "Error" << std::endl;
|
|
}
|
|
|
|
// 反向计算序号
|
|
int iii = GetRingIndex(nX, nY);
|
|
if (i != iii)
|
|
{
|
|
std::cout << "Error" << std::endl;
|
|
}
|
|
|
|
print((nX2 + 10) * 3, (nY2 + 10) * 3, std::to_string(i));
|
|
//std::cout <<i << " : (" << nX << ", " << nY << ")" << std::endl;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|