Jump to content

Jogo da string


Recommended Posts

Posted

boa tarde companheiros, estou tentando criar um jogo, onde o user passa uma string e o programa embaralha elas e o jogador tenta acertar.

mas meu problema é que não sei como embaralhar as strings

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

    int main(){
        int len = 0;
        char *str = (char *) malloc(sizeof(char) * 4096);
        if(str == NULL){
            realloc(str, sizeof(char) * 1024);
        }

        char *copy = (char *) malloc(sizeof(char) * 4096);
        if(copy == NULL){
            realloc(copy, sizeof(char) * 1024);
        }

        printf("Str: ");
        fgets(str, (sizeof(char) * 4096), stdin);

        char *token = strtok(str, ";");
        while(token != NULL){
            // junta as strings e aumenta 1
            strcat(copy, token);
            len = len +1; 

            token = strtok(NULL, ";");
        }
        // diminui 1
        len--;
        printf("string: %s\n", copy);

        free(str);
        free(copy);
        return 0;
    }

 

"Viva o hoje e aproveite o amanhã."

autor esquecido

Posted
Em 14/11/2024 às 17:39, unix disse:

boa tarde companheiros, estou tentando criar um jogo, onde o user passa uma string e o programa embaralha elas e o jogador tenta acertar.

mas meu problema é que não sei como embaralhar as strings

viva,

já programei muito em c, c++, mas há anos que não tenho oportunidades de trabalhar nisto.

do que vejo no teu código (posso estar errado):

1. fazes "malloc" de 4096, caso não seja possível, tentas fazer "realloc" de apenas 1024
>> salvo erro, tens de assignar o "str = realloc(…"

2. fazes um "fgets" com size 4096 fixo independentemente de acima teres conseguido 4096 ou apenas 1024
>> para não complicar, nesta fase, usa sempre 1024, 256, 126 em todos  (as tantas 80 seria suficiente)

3. dizes que o user passa uma string e o programa deve embaralhar… a seguir usas "strtok" para partir a string delimitada por ";"
>> o teu código está a pegar nisto str="a;b;c;d;e;f" e a transformar nisto copy="abcdef"

É isto que pretendes?
>> o user envia "uma" string com várias strings separadas por ";", tipo "não sei como;criar um jogo;boa tarde" 
>> queres separar e baralhar esta lista de strings ["não sei como", "criar um jogo", "boa tarde"] ?
>> o user deve acertar em que?

Ou apenas?
>> o user envia UMA string com VÁRIOS caracteres, sem separadores, tipo "portugal"
>> baralhas os caracteres "logtprua"
>> o user tenta acertar em "logtprua" ?

  • Vote 1
Posted

Vou partir do princípio que queres baralhar os caracteres de uma string. Caso queiras baralhar um conjunto de strings separados por ;, o que vou falar pode ser um bom princípio, mas necessitará de mais trabalho em cima.

 

A fim de baralhar a string podes usar a própria string original para ir mantendo registo dos caracteres que já usaste e de quais faltam baralhar.

Tendo uma string com N caracteres, executas um ciclo N vezes com um contador i que vai de 0 a N - 1:

  1. Obter uma posição pseudo-aleatória P no intervalo [0, N - i);
  2. Copiar para a posição i da string baralhada o caracter na posição P da string original;
  3. Trocar, na string original, os caracters das posições P e N - i - 1.

Ao executar acontece algo deste género:

Insert string: abcdef
i =   0 | pos =   4 | original = "abcdfe" | shuffled = "e"
i =   1 | pos =   1 | original = "afcdbe" | shuffled = "eb"
i =   2 | pos =   3 | original = "afcdbe" | shuffled = "ebd"
i =   3 | pos =   1 | original = "acfdbe" | shuffled = "ebdf"
i =   4 | pos =   1 | original = "acfdbe" | shuffled = "ebdfc"
i =   5 | pos =   0 | original = "acfdbe" | shuffled = "ebdfca"
original = "abcdef"
shuffled = "ebdfca"
  • Na primeira iteração (i = 0) gerei o número pseudo-aleatório 4 (intervalo [0, 6)) peguei no caracter original[4], e, coloquei em shuffled[0] e depois troquei os caracteres original[4] e original[5]. A string original ficou passou de abcdef para abcdfe e a shuffled ficou com o primeiro caracter.
  • Desta forma ficou no último caracter da original aquele que já "baralhámos", pelo que só podemos pegar numa posição pseudo-aleatória no intervalo [0, 5) na iteração seguinte. O processo repete-se, e como pegámos no caracter b, repararás que passámos de abcdfe para afcdbe.

Desta forma garantimos sempre que os caracteres baralhados já não serão reutilizados, usando sempre o mesmo espaço de memória.

Em código:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define MAXLEN 256

// Comenta se não quiseres mostrar o progresso no ciclo "for"
#define DEBUG

/* Aloca uma string de tamanho "len", colocando todos os bytes a "zero" */
static inline char *make_str(size_t len) {
    return (char*)calloc(len, sizeof(char));
}

/* Aloca memória com uma cópia da string de origem */
char *make_copy(const char *src, size_t len) {
    char *copy = make_str(len);
    if (copy)
        strncpy(copy, src, len);
    return copy;
}

/* Obtém string do utilizador e remove "new line" se estiver presente no final */
size_t get_string(const char *prompt, char *str, const size_t maxlen) {
    printf("%s", prompt);
    fgets(str, maxlen, stdin);
    size_t len = strlen(str);
    if (str[len - 1] == '\n')
        str[--len] = '\0';
    return len;
}

/* Obtém um número pseudo-aleatório no intervalo [min, max) (i.e. exclusive "max") */
static inline int get_rand_int(int min, int max) {
    return min + rand() % (max - min);
}

int main(void) {
    // Aloca memória para string original e obtém o input do utilizador
    char *original = make_str(MAXLEN);
    if (!original)
        return 1;
    size_t len = get_string("Insert string: ", original, MAXLEN);

    // Cópia da original, apenas porque vou mostrar a string original no final mas vou precisar de a modificar
    char *copy_original = make_copy(original, len + 1);
    if (!copy_original) {
        free(original);
        return 2;
    }

    // Aloca memória para a string baralhada
    char *shuffled = make_str(len + 1);
    if (!shuffled) {
        free(original);
        free(copy_original);
        return 3;
    }

    // Inicializa variáveis temporárias e "randomizador"
    int  pos  = 0;
    char temp = '\0';
    srand(time(NULL));

    // Vamos baralhar!
    for (size_t i = 0; i < len; ++i) {
        pos                   = get_rand_int(0, len - i);
        shuffled[i]           = temp = original[pos];
        original[pos]         = original[len - i - 1];
        original[len - i - 1] = temp;
#ifdef DEBUG
        printf("i = %3lu | pos = %3d | original = \"%s\" | shuffled = \"%s\"\n", i, pos, original, shuffled);
#endif
    }

    printf("original = \"%s\"\nshuffled = \"%s\"\n", copy_original, shuffled);

    free(original);
    free(copy_original);
    free(shuffled);

    return 0;
}

O output de exemplo supra-citado foi gerado com uma execução deste código.

 

Cumprimentos.

Knowledge is free!

  • 2 weeks later...
Posted

@unix : percebo que quando uma pessoa tem uma dúvida, seja difícil a explanar. pois se não fosse dúvida, as coisas eram simples. peço só para tentar ser um pouco mais claro na próxima vez, eu acredito que consigas porque já vi perguntas bem mais difíceis de compreender aqui.

@thoga31 eu gosto de código um pouco mais simples 😄

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAXLEN 256

int main() {
    size_t len = MAXLEN;
    char *original = NULL, *shuffled = NULL;

    // aloca memória para string original
    if ((original = (char*) calloc(len, sizeof(char))) == NULL)
        return 1;

    // pedir a string ao utilizador
    do {
        len = 0;
        printf("Insert string: ");
        if (fgets(original, MAXLEN, stdin) != NULL) {
            len = strlen(original);
            if (original[len - 1] == '\n')
                original[--len] = '\0';
        }
    } while (len == 0);

    // criar o resultado com base na original
    if ((shuffled = (char*) malloc(len + 1)) == NULL) {
        free(original);
        return 1;
    }
    strncpy(shuffled, original, len + 1);

    // baralhar a string gerada
    for (size_t i = 0; i < len; i++) {
        size_t pos = i + rand() % (len - i);
        if (pos != i) {
            char aux = shuffled[i];
            shuffled[i] = shuffled[pos];
            shuffled[pos] = aux;
        }
    }

    // apresentar as strings
    printf("%s|%s\n", original, shuffled);

    // libertar a memória alocada
    free(original);
    free(shuffled);

    return 0;
}

 

IRC : sim, é algo que ainda existe >> #p@p

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.