2015-11-23 3 views
-1

В этой функции программа получает четыре случайных слова, сгенерированных ранее из списка, и случайным образом помещает их в матрицу 10x10.Слова, перекрывающиеся в игре поиска слов

Проблема в том, что иногда слова горизонтального/вертикального/наклонного перекрывают друг друга (однако слова из той же категории нет). Я не хочу, чтобы они перекрывались таким образом

void outputMatrix() { 
char matrix[10][10]; 
for (int i = 0; i<10; i++) { 
    for (int j = 0; j<10; j++) { 
     matrix[i][j] = '-';   
    } 
} 
getRandomWord(); 
srand(time(NULL)); 
int randPosY = (rand() % 9); 
int randPosX = (rand() % 9); 
int incr = 0; 
bool amend; 
char r; 
for (int x = 0; x < 4; x++) { 
    char randCase = (rand() % 3) + 65; 

    switch (randCase) { 
    case 'A': //to input words horizontally   
     if (incr == 1) { 
      r1 = r2; 
     } 
     if (incr == 2) { 
      r1 = r3; 
     } 
     if (incr == 3) { 
      r1 = r4; 
     } 

    reCheck: 
     amend = false; 
     if ((randPosX + strlen(dictionary[r1]) > 10)) { 
      randPosX--; 
      goto reCheck; 
     } 

     for (int i = 0; i < strlen(dictionary[r1]); i++) { 
      matrix[randPosY][randPosX + i] = dictionary[r1][i]; 
     } 

     for (int i = 0; i < strlen(dictionary[r1]); i++) { 
      reRand: 
       if (matrix[randPosY][randPosX + i] != '-') { 
        randPosY = (rand() % 9); 
        randPosX = (rand() % 9);       
        goto reRand; 
        amend = true; 

       }if ((i == (strlen(dictionary[r1]) - 1)) && (amend == true)) goto reCheck; 
      }   
     break; 

    case 'B': //to input words vertically   
     if (incr == 1) { 
      r1 = r2; 
     } 
     if (incr == 2) { 
      r1 = r3; 
     } 
     if (incr == 3) { 
      r1 = r4; 
     }  
    reCheck2: 
     amend = false; 
     if ((randPosY + strlen(dictionary[r1]) > 10)) { 
      randPosY--; 
      goto reCheck2; 
     }   
     for (int i = 0; i < strlen(dictionary[r1]); i++) { 
      matrix[randPosY + i][randPosX] = dictionary[r1][i]; 
     } 
     for (int i = 0; i < strlen(dictionary[r1]); i++) { 
     reRand2: 
      if (matrix[randPosY + i][randPosX] != '-') { 
       randPosY = (rand() % 9); 
       randPosX = (rand() % 9); 
       goto reRand2; 
       amend = true; 
      }if ((i == (strlen(dictionary[r1]) - 1)) && (amend == true)) goto reCheck2; 
     } 
      break; 

    case 'C': //to input words slanting   
     if (incr == 1) { 
      r1 = r2; 
     } 
     if (incr == 2) { 
      r1 = r3; 
     } 
     if (incr == 3) { 
      r1 = r4; 
     } 

    reCheck3: 
     amend = false; 
     if ((randPosY + strlen(dictionary[r1]) > 10)) { 
      randPosY--; 
      goto reCheck3; 
     } 
    reCheck4: 
     if ((randPosX + strlen(dictionary[r1]) > 10)) { 
      randPosX--; 
      goto reCheck4; 
     } 
     for (int i = 0; i < strlen(dictionary[r1]); i++) { 
      matrix[randPosY + i][randPosX + i] = dictionary[r1][i]; 
     } 
     for (int i = 0; i < strlen(dictionary[r1]); i++) { 
     reRand3: 
      if (matrix[randPosY + i][randPosX + i] != '-') { 
       randPosY = (rand() % 9); 
       randPosX = (rand() % 9); 
       amend == true; 
       goto reRand3; 
      }if ((i == (strlen(dictionary[r1]) - 1)) && (amend == true)) goto reCheck3; 
     }   
     break; 
     } incr++;   
    } 

//for (int i = 0; i<10; i++) { 
    //for (int j = 0; j < 10; j++) { 
     //if (matrix[i][j] == '-') { 
      //r = (rand() % 26) + 65; 
      //matrix[i][j] = r; 
     //} 

    //} 
//} 
printf("\n\t  A B C D E F G H I J\n\n\n\t"); 
for (int a = 0; a <10; a++) { 
    printf("%d", a); 
    printf(" "); 
    for (int b = 0; b < 10; b++) { 
     printf("%c ", matrix[a][b]); 
    }  
    printf("\n\n\t"); 
} 
} 
+0

Добро пожаловать в StackOverflow! Вы просите нас улучшить вашу программу? что ты уже испробовал? – Ilya

+0

Вы забыли задать вопрос. Вы должны задать нам конкретный вопрос, на который мы можем ответить. –

+0

Когда вы определяете новые координаты для следующего слова, вы делаете это для последнего слова и для последней ориентации. Логика проверки сама по себе неверна. Вам нужен цикл для проверки всех ячеек, но если вы обнаружите столкновение, вы должны начать все заново. (Кстати, стиль 'goto' ужасен.Код вроде' start: if (x) {y(); goto start;} 'может отображаться более естественно как'while (x) y();'.) –

ответ

0

Ваша логика поместить слово должно быть:

  • выбрать слово
  • выбрать случайные координаты и ориентацию, пока слово не может быть помещен в этих координатах и ​​с этой ориентацией.
  • место слово

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

Ваш код имеет другие проблемы:

  • Использование goto с делает код почти нечитаемым. Вы можете заменить все goto с общими конструкциями управления. Например,

    reCheck4: 
        if ((randPosX + strlen(dictionary[r1]) > 10)) { 
         randPosX--; 
         goto reCheck4; 
        } 
    

    можно записать в виде

    while (randPosX + strlen(dictionary[r1]) > 10) randPosX--; 
    

    Некоторые goto s сделать stetements недостижим, например:

    goto reRand2; 
    amend = true; 
    

    Здесь amend = true никогда не будет выполнена. (Странно, что вы используете Fortran77-иш последовательно открывает повсюду, но одно место, где они мощь было понятнее, можно использовать переменную в Pascal-иш правда.)

  • Ваш цикл по четыре слова использует x, но вы никогда не используете эту переменную. Вместо этого вы сохраняете другую переменную incr, значение которой совпадает с значением x. Заменить

    int incr = 0; 
    
    for (int x = 0; x < 4; x++) { 
        // Do stuff with incr, but not with x 
        incr++; 
    } 
    

    с:

    for (int incr = 0; incr < 4; incr++) { 
        // Do stuff with incr, but not with x 
    } 
    
  • У вас есть четыре индекса слова, r1 через r4.Код, как

    if (incr == 1) { 
        r1 = r2; 
    } 
    if (incr == 2) { 
        r1 = r3; 
    } 
    if (incr == 3) { 
        r1 = r4; 
    } 
    

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

    r1 = index[incr]; 
    
  • вызов srand только один раз, в начале main. Неоднократный вызов srand с семенами с низкой степенью детализации, такими как время в секундах, сделает вашу программу менее случайной.

  • - функция, которая определяет длину строки каждый раз, когда вы вызываете ее, пересекая строку, пока не найдет нулевой ограничитель. Вы всегда смотрите одну и ту же строку в цикле, чтобы сохранить длину строки в переменной. (Yourstrings короткое, а накладные расходы незначительно, но все же.)

Вы можете исправить свой код, ptting тестов фронта. Это будет означать нулевой тест для первого слова, но, по крайней мере, логика понятна.

Вы можете улучшить свой код несколькими способами:

  • попытаться устранить дублирование кода. На данный момент ваши три случая почти одинаковы. Найдите общие части и объедините их в общую функцию. Например, ориентации действительно просто означают другие «векторы движения» через сетку, а именно (0,1) для орионталя, (0,1) для вертикальной и (1,1) для диагонали.

  • После этого вы можете определить допустимые диапазоны для позиции вверх. Нет необходимости корректировать координаты.

  • Не стесняйтесь использовать функции. Разделение задач на функции означает, что вы должны передавать некоторые данные, но это также означает, что вы можете выпрыгнуть из функции с возвращаемым значением сразу, если вам нужно. Это сэкономит вам немало goto с переменными истинности и является способом управления потоком C.

    Проверка того, можно ли разместить слово, является хорошим кандидатом на функцию. Размещение слова тоже.

  • Тим Б перегрузил сброс. Это хорошая идея, потому что вы можете заглянуть в угол здесь, если ваши слова будут длинными.

Вот пересмотренный (или переписаны, а) версию кода, который не выбирает слова на место случайно, однако:

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

int isvalid(char matrix[10][10], int x, int y, int dx, int dy, int len) 
{ 
    for (int i = 0; i < len; i++) { 
     if (matrix[y][x] != '-') return 0; 
     x += dx; 
     y += dy; 
    } 

    return 1; 
} 

void matrix_fill(char matrix[10][10], const char *words[4]) 
{ 
    int dx[3] = {1, 0, 1};  // horizontal strides 
    int dy[3] = {0, 1, 1};  // vertical strides 

    startover: 

    for (int i = 0; i < 10; i++) { 
     for (int j = 0; j < 10; j++) { 
      matrix[j][i] = '-'; 
     } 
    } 

    for (int i = 0; i < 4; i++) { 
     const char *word = words[i]; 
     int len = strlen(word); 

     int orient, x, y; 
     int tries = 0; 
     int valid; 

     if (len > 8) break;  // just to be sure 

     do { 
      orient = rand() % 3; 
      x = rand() % (10 - dx[orient] * len); 
      y = rand() % (10 - dy[orient] * len); 

      valid = isvalid(matrix, x, y, 
          dx[orient], dy[orient], len);    
      tries++; 
     } while (!valid && tries < 100); 

     if (!valid) goto startover; 

     for (int i = 0; i < len; i++) { 
      matrix[y][x] = word[i]; 
      x += dx[orient]; 
      y += dy[orient]; 
     } 
    } 

} 

void matrix_print(char matrix[10][10]) 
{ 
    printf("%4s ", ""); 
    for (int i = 0; i < 10; i++) { 
     printf("%4c", 'A' + i); 
    } 
    printf("\n\n"); 

    for (int j = 0; j < 10; j++) { 
     printf("%4d ", j); 

     for (int i = 0; i < 10; i++) { 
      printf("%4c", matrix[j][i]); 
     } 
     printf("\n\n"); 
    } 
} 

int main() 
{ 
    const char *dictionary[4] = {"apple", "pear", "cherry", "lemon"}; 
    char matrix[10][10]; 

    srand(time(NULL)); 

    matrix_fill(matrix, dictionary); 
    matrix_print(matrix); 

    return 0; 
} 
+0

Большое спасибо! Да, ты прав. Гото, это не хорошая практика, я заменил их на некоторое время ... Я также добавил функции и организовал логику, как вы заявили вначале. Там возникла еще одна проблема, что булевы не работают в C++! Вместо этого я использовал целое ... Программа отлично работает! Благодаря :) – Simon

1

Когда вы решили поместить слово в месте, то первое сканирование везде вы размещаете слово и посмотреть, если есть другое слово. Если после этого произойдет прерывание и попробуйте новое место.

Возможно, вы захотите иметь какой-либо вариант «перезагрузки», если он слишком часто терпит неудачу, если нет действительного места.

+0

Не делает ли эта форма, в которой используется логическое значение? Может быть, вместо повторения дела я повторяю весь метод? Я попробую, когда я буду дома. – Simon

Смежные вопросы