Nick_is_asking Ответов: 6

Простая игра - задача с массивом (я полагаю)


Привет. Я использую C, чтобы сделать простую игру.
У меня есть такой массив, как этот:

| | | | | | ....... а между "|" я хочу запустить цикл for, чтобы мигнуть "*"

внутри "|" в случайных позициях массива ,но я получаю эту ошибку:
Segmentation fault (core dumped)

Я его еще не закончил.

Код:

Что я уже пробовал:

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


int pos_rand(char *array);


int main(void)
{
    char *array[21];
    for (int i = 0; i <= 9; i++)
    {
        printf(" ");
    }

    *(array + pos_rand(*array)) = "*";
    
    for (int i = 0; i <= 20; i++)
    {
        if(i % 2 == 0 && strcmp(*(array + i) , "*") != 0)
        {
             *(array + i) = " | ";
        }
        
        else if(strcmp(*(array + i) , "*") != 0)
        {
             *(array + i) = " ";
        }
    }
    
    for (int i = 0; i <= 20; i++)
    {
        printf("%s" , *(array + i));
    }
    
    printf("\n\nPosition:    ");

    for (int i = 1; i <= 10; i++)
    {
        printf("%d   " , i);
    }
    printf("\n\n");
}


int pos_rand(char *array)
{
    srand(time(NULL));    
    return (rand() % 10) * 2 + 1;   // recieve an odd random number between 1 to 21.
}



Я не могу понять, в чем проблема...

Спасибо за вашу помощь!!!

6 Ответов

Рейтинг:
2

Patrice T

Не вопрос, но .....
Этот код повторяет нечетное случайное число между С 1 по 19.

return (rand() % 10) * 2 + 1;   // recieve an odd random number between 1 to 21.

изменение
return (rand() % 11) * 2 + 1;

чтобы получить желаемый результат.


jeron1

Который, если он равен 21, приведет к выходу за пределы индекса массива в том виде, в каком он записан в данный момент.

Patrice T

код и комментарий противоречивы

jeron1

действительно

Luc Pattyn

Я не согласен, он хочет только 10 различных результатов от случайной функции, массив содержит 10 ячеек и 11 стенок, окружающих эти 10 ячеек.

Это его комментарий, который сбивает с толку, должен был быть

return (rand() % 10) * 2 + 1;   // return an odd random number in [1,19]

Рейтинг:
2

Rick York

Я просто обращусь к проблеме случайных чисел. Во-первых, существует (по крайней мере) два способа посева генератора случайных чисел (ГСЧ). Псевдослучайно или с фиксированным числом. Для игровых целей часто полезно использовать фиксированное число, чтобы вы могли вернуться и использовать ту же последовательность случайных значений. Вы можете назвать это игровым номером, как это часто делается в карточных играх. Псевдослучайный способ-использовать время. Если вы используете srand и rand, случайные значения будут варьироваться от 0 до RAND_MAX, что обычно составляет 32 767. Вот небольшая функция, которая будет сеять ГСЧ для вас :

typedef unsigned short USHORT;

#define PSEUDO_RANDOM_SEED 0

void SeedRNG( USHORT seedVal )
{
    USHORT seed = seedVal;
    if( seedVal == PSEUDO_RANDOM_SEED )
    {
        time_t now = time( NULL );
        seed = (USHORT)( now % RAND_MAX );
    }
    srand( seed );
}
Это позволит вам видеть ГСЧ в любом случае - псевдослучайно, передавая 0, или повторным способом, передавая ненулевое значение.

Важно засеять только ГСЧ один время.

Вот удобная функция генерации случайных чисел. Вы можете указать диапазон значений, который хотите охватить.
int GetRandomInt( int minval, int maxval )
{
    int range = maxval - minval + 1;
    int value = rand() % range;   // limit the value to the range of interest
    return range + minval;        // offset it by minimum to get it into the ROI
}
Наконец, вот как вы можете их использовать.
void Testem()
{
    const int valueCount = 20;
    int value;

    SeedRNG( PSEUDO_RANDOM_SEED );

    for( int n = 0; n < valueCount; ++n )
    {
        value = GetRandomInt( 10, 90 );
        printf( "value %2d is %2d\n", n + 1, value );
    }
}
Эта маленькая выборка должна вывести двадцать случайных величин в диапазоне от 10 до 90.


Рейтинг:
2

Nick_is_asking

Спасибо вам всем, ребята.Я использовал malloc и free, и это сработало.
Теперь я хочу "мигать" звездой "*" между "|" ,Но я хочу генерировать нечетные случайные числа, не повторяясь в последовательных позициях:
Например ,я использую цикл for,так что:
Если i = 1 ,то я генерирую нечетное случайное число в [1 , 19].
Когда i = 2 ,я хочу сгенерировать нечетное случайное число между [1 , 19],кроме предыдущего числа(i = 1).
Когда i = 3, я могу использовать число (цикл: i = 1) ,но не число в
(цикл: i = 2) и т. д...


Я подумал и попробовал что-то сделать, но ничего хорошего не вышло, и это прилипло.
Весь код:

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


int pos_rand(char *array);
void delay(int number_of_seconds);
void run(char *array);
int change_pos(char *array , int ps);


int main(void)
{
    char *array;
    for(int i = 1; i <= 10; i++)
    {
        run(array);
        system("clear");
    }
    
}


int pos_rand(char *array)
{
    srand(time(NULL));    
    return (rand() % 10) * 2 + 1;   // recieve an odd random number between 1 to 19.
}




void delay(int number_of_seconds) 
{ 
    // Converting time into milli_seconds 
    int milli_seconds = 1000 * number_of_seconds; 
  
    // Storing start time 
    clock_t start_time = clock(); 
  
    // looping till required time is not achieved 
    while (clock() < start_time + milli_seconds); 
} 


void run(char *array)
{
    printf("Array:");
    for (int i = 0; i <= 7; i++)
    {
        printf(" ");
    }

    array = malloc(sizeof(char) * 21);
    if(!array)
    {
        printf("ERROR\n");
        exit(0);
    }

    for(int i = 0; i <= 9; i++)
    {
        array[ change_pos(array , i) ] = '*';
    }
    
    
    
    for (int i = 0; i <= 20; i++)
    {

        if(i % 2 == 0 && array[i] != '*')
        {
            array[i] = '|';
        }
        
        else if(array[i] != '*')
        {
            array[i] = ' ';
        }
    }
    
    for (int i = 0; i <= 20; i++)
    {
        printf("%c" , array[i]);
    }
    
    printf("\n\nPosition:      ");

    for (int i = 1; i <= 10; i++)
    {
        printf("%d " , i);
    }
    delay(300);
    printf("\n");
    for (int i = 0; i <= 20; i++)
    {
        array[i] = ' ';
    }

    printf("\n");
    free(array);
}



int change_pos(char *array , int ps)
{
    int *arr_pos;
    int previous;
    
    arr_pos = malloc(sizeof(int) * 10);
    do
    {
        previous = pos_rand(array);
        arr_pos[ps] = previous;
    }
    while(arr_pos[previous] == arr_pos[previous + 1]);
    free(arr_pos);
    return previous;
}


Рейтинг:
1

Luc Pattyn

Проблема в вашем коде - это строка

char *array[21];
определяет массив указателей char (или строк), однако эти указатели не инициализируются, и за ними нет памяти. Чтобы исправить это, вам, возможно, придется сделать что-то вроде цикла с malloc для каждого элемента массива.


ИМХО было бы проще держать логику и отображение игры отдельно.

В логике у вас есть массив ячеек, каждый из которых имеет только несколько возможных состояний; вы можете смоделировать это с массивом целых чисел.

При отображении вам придется повторить этот массив и построить строку из таких подстрок, как " | " и "*".

И если вы используете (а) некоторые константы/определения и (Б) доступ к массиву в скобках, все становится гораздо более читабельным. как и в этом случае:

#define EMPTY 0
#define STAR 1
#define BAR 2
#define CELLCOUNT 10

int array[2*CELLCOUNT+1];
char mystring[4*CELLCOUNT];

for(int i=0; i<=CELLCOUNT ; i++) array[2*i]=BAR;
for(int i=0; i<CELLCOUNT ; i++) array[2*i+1]=EMPTY;
array[rand_pos()]=STAR;

mystring[0]=0;
for(int i=0; i<2*CELLCOUNT+1; i++) {
    switch(array[i]) {
        case BAR:
            strcat(mystring, " | ");
            break;
        case STAR:
            strcat(mystring, "*");
            break;
        case EMPTY:
            strcat(mystring, " ");
            break;
    }
}


Рейтинг:
0

k5054

Здесь так много всего, что трудно понять, с чего начать, но давайте начнем здесь:

int pos_rand(char *array)
{
    srand(time(NULL));    
    return (rand() % 10) * 2 + 1;   // recieve an odd random number between 1 to 21.
}

Во-первых, кажется, что в этом споре нет никакого смысла char *array как array нигде в массиве не используется.
Во-вторых, srand() используется только для заполнения генератора случайных чисел и обычно используется только для заполнения генератора случайных чисел. однажды за программу. Рассмотрим следующую программу:
#include <stdlib.h>
#include <time.h>

int getrand()
{
    srand(time(NULL));
    return rand();
}


int main()
{
    for(int i = 0; i < 10; ++i)
        printf("%d\n", getrand());

    return 0;
}
Выходные данные для этой программы могут выглядеть следующим образом:
$ ./example
1824823912
1824823912
1824823912
1824823912
1824823912
1824823912
1824823912
1824823912
1824823912
$
То, что происходит здесь заключается в том, что rand() получает свою начальную точку сброса каждый раз, так что до тех пор, пока вызов getrand() находится в пределах одной и той же секунды на часах, он вернет то же значение.

Тогда есть такое использование: *(array + i). Если вы не работаете над запутанной программой на языке Си, то обычно вы не получаете доступ к i-му элементу массива. Нормальный способ сделать это таков array[i]

Затем убедитесь, что вы скомпилировали свою программу с опцией-g (добавляет информацию для отладчика), например gcc -Wall -Wextra -g myprog.c -o myprog
Затем используйте gdb, чтобы взять изучить, что происходит
Возможно, вы захотите посмотреть документацию gdb и узнать, как запустить программу, получить обратную трассировку, изменить фреймы и распечатать значения переменных.


Рейтинг:
0

Patrice T

К новому вопросу:

Цитата:
Теперь я хочу "мигать" звездой "*" между "|" ,Но я хочу генерировать нечетные случайные числа, не повторяясь в последовательных позициях:

Случайные числа без повтора не случайны!
Подумайте о колоде карт, вы тасуете всю колоду сразу, затем вы рисуете карты 1 на 1. когда все карты рисуют, тасуйте снова.
Перетасовка - Википедия[^]
Фишер–Йейтс шаффл - Википедия[^]