Best way to make sure this number isn't the same as any others?
#1

pawn Код:
for(new i = 0; i < MAX_FURNI; i++)
        {
            if(FurniCode[i] == furnic)
            {
             
            }
I'm not very familiar with while loops and I realise that a for one is not adequate, but that for loop kind of explains what I need.

Basically.

Furnicode is 6 random digits, I need to make sure that when a new code is allocated it doesn't match any other code in the server.
I need it to keep repeating until that becomes the case

What is the best way to do this?
Reply
#2

If it is supposed to be a unique identifier, why is it random? What is it used for?
Reply
#3

pawn Код:
for(new i = 0; i < MAX_FURNI; i++)
{
    if(FurniCode[i] == furnic)
    {
        furnic = rand // generate the number again and loop again
        continue;
    }
}
Just generate a new number if it matches and continue to see if it still matches. Or you can keep a variable that increments each time a furniture object is created and save and load it when the server closes / starts.
Reply
#4

There is nothing wrong with doing so if you know that "numbers in use" (or the maximum of numbers in use = MAX_FURNI) is very small compared to 10^6 (all possible numbers)
Because than the chance to hit a used number is very low

Otherwise you should use a another method without possible infinite loops
Reply
#5

Thanks very much guys, Vince, it would take a while to explain, but basically I'm using it to uniquely identify furniture with a roleplay reason. i.e a barcode.
Reply
#6

This should work for what you want to do:
pawn Код:
// [ DEVELOPMENT GAMEMODE ]

// RULES:

#pragma dynamic 1000000

// INCLUDES:

#include <a_samp>
#include <sscanf2>
#include <zcmd>

// DEFINES:

#define MAX_NUMBERS 899999
#define OFFSET 100000

// VARIABLES:

new bool:gNumbers[MAX_NUMBERS] = false;

// MAIN:

main()
{
    print("Development Mode: random_not_taken.amx");
}

// CALLBACKS:

public OnGameModeInit()
{
    return 1;
}

public OnGameModeExit()
{
    return 1;
}

// COMMANDS:

CMD:add(playerid, params[])
{
    new index;
    if(sscanf(params, "i", index)) return SendClientMessage(playerid, -1, "Usage: /add (index).");
    if(gNumbers[index]) return SendClientMessage(playerid, -1, "Index is already in use.");
    if(index < 0 || index >= MAX_NUMBERS) return SendClientMessage(playerid, -1, "You have entered an invalid index.");

    gNumbers[index] = true;

    new string[128];
    format(string, sizeof(string), "%d has been marked as taken.", index + OFFSET);
    SendClientMessage(playerid, -1, string);
    return 1;
}

CMD:remove(playerid, params[])
{
    new index;
    if(sscanf(params, "i", index)) return SendClientMessage(playerid, -1, "Usage: /remove (index).");
    if(!gNumbers[index]) return SendClientMessage(playerid, -1, "Index is not in use.");
    if(index < 0 || index >= MAX_NUMBERS) return SendClientMessage(playerid, -1, "You have entered an invalid number.");

    gNumbers[index] = false;

    new string[128];
    format(string, sizeof(string), "%d has been marked as available.", index + OFFSET);
    SendClientMessage(playerid, -1, string);
    return 1;
}

CMD:random(playerid, params[])
{
    new string[128], tick[2], number;
    tick[0] = GetTickCount();
    number = RandomNotTaken();
    tick[1] = GetTickCount();

    format(string, sizeof(string), "Number %d is a free non-taken number (%d ms).", number, tick[1] - tick[0]);
    SendClientMessage(playerid, -1, string);
    return 1;
}

// FUNCTIONS:

stock RandomNotTaken()
{
    new free_numbers[MAX_NUMBERS], count;
    for(new i = 0; i < MAX_NUMBERS; i ++)
    {
        if(!gNumbers[i])
        {
            free_numbers[count] = i;
            count ++;
        }
    }

    new selected = free_numbers[random(count)] + OFFSET;
    return selected;
}


Test with 5 numbers:
pawn Код:
// [ DEVELOPMENT GAMEMODE ]

// INCLUDES:

#include <a_samp>
#include <sscanf2>
#include <zcmd>

// DEFINES:

#define MAX_NUMBERS 5

// VARIABLES:

new bool:gNumbers[MAX_NUMBERS] = false;

// MAIN:

main()
{
    print("Development Mode: random_not_taken.amx");
}

// CALLBACKS:

public OnGameModeInit()
{
    return 1;
}

public OnGameModeExit()
{
    return 1;
}

// COMMANDS:

CMD:add(playerid, params[])
{
    new index;
    if(sscanf(params, "i", index)) return SendClientMessage(playerid, -1, "Usage: /add (index).");
    if(gNumbers[index]) return SendClientMessage(playerid, -1, "Index is already in use.");
    if(index < 0 || index >= MAX_NUMBERS) return SendClientMessage(playerid, -1, "You have entered an invalid index.");

    gNumbers[index] = true;

    new string[128];
    format(string, sizeof(string), "%d has been marked as taken.", index);
    SendClientMessage(playerid, -1, string);
    return 1;
}

CMD:remove(playerid, params[])
{
    new index;
    if(sscanf(params, "i", index)) return SendClientMessage(playerid, -1, "Usage: /remove (index).");
    if(!gNumbers[index]) return SendClientMessage(playerid, -1, "Index is not in use.");
    if(index < 0 || index >= MAX_NUMBERS) return SendClientMessage(playerid, -1, "You have entered an invalid number.");

    gNumbers[index] = false;

    new string[128];
    format(string, sizeof(string), "%d has been marked as available.", index);
    SendClientMessage(playerid, -1, string);
    return 1;
}

CMD:random(playerid, params[])
{
    new string[128];
    format(string, sizeof(string), "Number %d is a free non-taken number.", RandomNotTaken());
    SendClientMessage(playerid, -1, string);
    return 1;
}

// FUNCTIONS:

stock RandomNotTaken()
{
    new free_numbers[MAX_NUMBERS], count;
    for(new i = 0; i < MAX_NUMBERS; i ++)
    {
        if(!gNumbers[i])
        {
            free_numbers[count] = i;
            count ++;
        }
    }

    new selected = free_numbers[random(count)];
    return selected;
}




Reply
#7

A lot easier and faster way than creating another array:

pawn Код:
randomin(min, max) return random(max - min) + min;

bool:NumberInUse(number)
{
        for (new i; i < MAX_FURNI; i++) if (FurniCode[i] == number) return false;
        return true;
}

FreeNumber()
{
    new number = randomin(100000, 1000000);
    while (NumberInUse(number)) number = randomin(100000, 1000000);
    return number;
}
Reply
#8

Quote:
Originally Posted by kvann
Посмотреть сообщение
A lot easier and faster way than creating another array:

pawn Код:
randomin(min, max) return random(max - min) + min;

bool:NumberInUse(number)
{
        for (new i; i < MAX_FURNI; i++) if (FurniCode[i] == number) return false;
        return true;
}

FreeNumber()
{
    new number = randomin(100000, 1000000);
    while (NumberInUse(number)) number = randomin(100000, 1000000);
    return number;
}
Let's see your and my version in action. Mine being 'Version 1' and yours being 'Version 2'.



As you can see yours is not faster and it is vastly unstable to even consider using it.

Code for anyone that wants to test them both:
pawn Код:
// [ DEVELOPMENT GAMEMODE ]

// RULES:

#pragma dynamic 1000000

// INCLUDES:

#include <a_samp>
#include <sscanf2>
#include <zcmd>

// DEFINES:

#define MAX_NUMBERS 899999
#define OFFSET 100000

// VARIABLES:

new bool:gNumbers[MAX_NUMBERS] = false;

// MAIN:

main()
{
    print("Development Mode: random_identifier_benchmark.amx");
}

// CALLBACKS:

public OnGameModeInit()
{
    for(new i = 0; i < MAX_NUMBERS; i ++)
    {
        if(i == 529428) continue;
        gNumbers[i] = true;
    }
    return 1;
}

public OnGameModeExit()
{
    return 1;
}

// COMMANDS:

CMD:random_1(playerid, params[])
{
    new string[128], tick[2], number;
    tick[0] = GetTickCount();
    number = RandomNotTaken_1();
    tick[1] = GetTickCount();

    format(string, sizeof(string), "Number %d is a free non-taken number (%d ms). Version 1.", number, tick[1] - tick[0]);
    SendClientMessage(playerid, -1, string);
    return 1;
}

CMD:random_2(playerid, params[])
{
    new string[128], tick[2], number;
    tick[0] = GetTickCount();
    number = RandomNotTaken_2();
    tick[1] = GetTickCount();

    format(string, sizeof(string), "Number %d is a free non-taken number (%d ms). Version 2.", number, tick[1] - tick[0]);
    SendClientMessage(playerid, -1, string);
    return 1;
}

// FUNCTIONS:

stock RandomNotTaken_1()
{
    new free_numbers[MAX_NUMBERS], count;
    for(new i = 0; i < MAX_NUMBERS; i ++)
    {
        if(!gNumbers[i])
        {
            free_numbers[count] = i;
            count ++;
        }
    }

    new selected = free_numbers[random(count)] + OFFSET;
    return selected;
}

stock RandomNotTaken_2()
{
    new number, free_number;
    for(new i = 0; i < 2; i ++)
    {
        number = RandomBetween(100000, 899999) - OFFSET;
        if(gNumbers[number])
        {
            i = 0;
        }
        else
        {
            free_number = number + OFFSET;
            break;
        }
    }
    return free_number;
}

stock RandomBetween(minimum, maximum)
{
    new selected = random(maximum - minimum) + minimum;
    return selected;
}
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)