因为项目中有个类似激活码的东东,然后就自己写了个。昨天去提问,然后结合自己的思想,最后成功了。只是优化还不是很理想,有时候会死循环,也没去调试看是哪几个值的问题。
我不知道windows啊vs啊以及SQL什么的是什么算法,我是取得每组值总和等于常量。
部分代码(全部代码):
public const int MAPKEYLEN = 16;
public const int REGISTKEYLEN = 25;
public static string[] MAPKETITEM =new string[36]{ "U", "F", "2", "I", "X", "S", "A", "V", "P", "M", "C", "9", "Q", "1", "G", "7", "K", "T", "B", "4", "W", "6", "H", "N", "E", "8", "Z", "O", "L", "3", "D", "0", "Y", "5", "J", "R"};
public class transTool
{
private static int[] mapAreas = new int[] { 48, 60, 74, 90 };
private static int[] registAreas = new int[] { 48,64,88,100,116 };
public transTool() { }
/// <summary>
/// 获取键
/// </summary>
/// <param name="keyType">1是4组4位码,2是5组5位码。可以通通过上面的值定义</param>
/// <returns></returns>
public static string getKey(int keyType)
{
string mapKey = string.Empty;
string mapKeyA = "0000";
string mapKeyB = "0000";
string mapKeyC = "0000";
string mapKeyD = "0000";
string mapKeySplit = "-";
mapKeyA = getKeys(0, keyType);
mapKeyB = getKeys(1, keyType);
mapKeyC = getKeys(2, keyType);
mapKeyD = getKeys(3, keyType);
mapKey = mapKeyA + mapKeySplit + mapKeyB + mapKeySplit + mapKeyC + mapKeySplit + mapKeyD;
if (keyType == 2)
{
string mapKeyE = "0000";
mapKeyE = getKeys(4, keyType);
mapKey += mapKeySplit + mapKeyE;
}
return mapKey;
}
private static string getKeys(int index, int keyType=1)
{
string item = string.Empty;//当前组的值
int[] areas = mapAreas; //合计域
int keyItemsLen = staticStrings.MAPKEYLEN / 4;//每组长度
if (keyType == 2)
{
areas = registAreas;
keyItemsLen = staticStrings.REGISTKEYLEN / 5;
}
if (index >= 0 && index < keyItemsLen)
{
int preItem = 0;//前一个值
int total = 0;//当前合计
for (int i = 0; i < keyItemsLen; i++)
{
int curr = getRight(areas[index], preItem, i, keyItemsLen, total);
total += curr;
if (curr >= staticStrings.MAPKETITEM.Length || curr <= 0 || (total >= areas[index] && i < keyItemsLen - 2))
{
item = getKeys(index, keyType);
}
else
{
preItem = curr;
item += staticStrings.MAPKETITEM[curr];
}
}
}
else
{
item = "0000";
}
return item;
}
/// <summary>
///
/// </summary>
/// <param name="area">总和的值</param>
/// <param name="preItem">前一个的值</param>
/// <param name="no">当前到第几个数上了</param>
/// <param name="total">当前总计</param>
/// <returns></returns>
private static int getRight(int area, int preItem, int no,int keyItemsLen, int total)
{
string keys = string.Empty;
int item = 0;
int len = staticStrings.MAPKETITEM.Length;
if (no == keyItemsLen - 1)//当获取到最后一个数时,直接总和值减去当前总和
{
item = area - total;
}
else
{
Random random = new Random();
if (len - 1 > area - total)//当还没获取到最后一个数并且剩余可用于合计的总数比取值范围还小时,去随机剩余可用范围
{
item = random.Next(1, area - total);
}
else
{
item = random.Next(1, len - 1);//随机出一个常量以内的数
}
System.Threading.Thread.Sleep(50);
}
//极端情况处理
//a!=area-keyItemsLen+1,因为第一个值取太大使得后三个值都是1,但这种情况在此题中不存在
//b!=area-total-keyItemsLen+1,因为前两个值的和值太大使得后两个值都是1,这种情况下重新取第二个数
//c!=area-total-c,虽然最后两个值不是1,但是也可能使得最后两个值相等,当知道这个值会和最后一个值相等时,抛弃此值重新取一个值
if (item == preItem || (no == 0 && item == area - keyItemsLen + no + 1) || (no == 1 && item == area - total - keyItemsLen + no+1)||(no==3&&item==area-total-item))//item<=0时重新生成所有,故不在此判断
{
item = getRight(area, preItem, no, keyItemsLen, total);
}
return item;
}
}