Пример проекта C ++ - Нужна помощь с алгоритмом - PullRequest
2 голосов
/ 12 февраля 2010

Один из моих друзей прислал мне это задание по программированию, чтобы я мог освежить в себе некоторые свои навыки C ++. Ниже приведено описание программы и предложенный мной алгоритм. Может ли кто-нибудь предоставить какие-либо отзывы / альтернативные решения:

Проблема:

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

Наш входной файл содержит следующее: Число n> 0 (представляющее количество слов в загадке), за которым следует такое количество слов. Например:

3
Фродо
ГИМЛИ
Арагорн

N не будет больше 10

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

Требования:
1. Два выходных файла - один, содержащий слова головоломки и головоломки, один только с решениями и без символов-заполнителей
2. Горизонтальных слов должно быть столько, сколько вертикальных слов
3. 1/3 слова необходимо поменять местами
4. В головоломке должно быть как минимум два пересечения


Предлагаемый алгоритм:
1. Создайте два многомерных массива - один для головоломки и один для решений
2. Создайте одномерный массив, содержащий различные буквы алфавита
3. Заполните массив пазлов случайными буквами алфавита (используя генератор псевдослучайных чисел # и массив из шага 2)
4. Начните читать входной файл
5. Читайте в n
6. Хотя счетчик меньше n, читайте словами, также есть счетчик для вертикальных и горизонтальных слов
7. Для каждого слова найдите длину строки
8. Найдите случайное расположение массива для вставки слова.
9. Если индекс случайного местоположения + длина строки <= 12 или если индекс случайного местоположения - длина строки>> 0 (чтобы гарантировать, что слово будет соответствовать вперед или назад), введите слово
10. Также вставьте слово в массив решений
12. Повторно используйте массивы для вставки всех слов во входной файл (аналогичным образом)

Я до сих пор не уверен в том, как я могу обеспечить наличие хотя бы двух пересечений.

Я также обеспокоен тем, что предложенный мной алгоритм излишне запутан.

Ваш отзыв очень важен!


Хорошо, вот, насколько я попал в процесс кодирования, прежде чем я решил вернуться и вернуться к алгоритму:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <ctime>
using namespace std;

//Error Codes
const int INPUT_FAIL = 1;
const int PUZZLES_OUTPUT_FAIL = 2;
const int SOLUTIONS_OUTPUT_FAIL = 3;

//Function Declarations/Prototypes
void OpenFiles(ifstream& input, ofstream& puzzles, ofstream& solutions);
//PRE:  The filestream objects exist and their address locations are passed in
//POST: The filestreams are opened. If they cannot be opened, an error message is printed to screen
//      and the program is terminated.

void FillArray(char puzzle[][12], char alphabet[]);
//PRE:  The address of the array is passed in
//POST: The array is filled with a random set of 

void CreatePuzzle(char puzzle[][12], ifstream& input, ofstream& puzzles, ofstream& solutions);
//PRE:  The address of the puzzle array,the address of the ifstream object and the addresses of the
//      ofstream objects are passed in.
//POST: The data in the input file is read and the words are input into the puzzle AND the puzzle
//      and solutions are printed to file.

void PrintPuzzle(char puzzle[][12], ofstream& output);
//PRE:  The address of the puzzle array and the ofstream object is passed in
//POST: The puzzle is output to the file

int main()
{
    //Seed the pseudo random generator
    srand(time(NULL));



    //Declare the filestream objects
    ifstream input;
    ofstream puzzles, solutions;

    //Declare the 2D array
    char puzzle[12][12];
    char solution[12][12];

    //Declare an alphabet array
    char alphabet[27] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
    /*char alphabet[27] = {'A','B','C','D','E','F','G','H','I','J','K','L',
    'M','N','O','P','Q','R','S','T','U','V','W',
    'X','Y','Z'};*/

    //Attempt to open files
    OpenFiles(input, puzzles, solutions);

    //Fill puzzle array with random letters of the alphabet
    FillArray(puzzle, alphabet);

    //Print puzzle
    PrintPuzzle(puzzle, puzzles);

    //Read in data to create puzzle
    input >> numwords;

    return 0;
}



//Function definitions
void OpenFiles(ifstream& input, ofstream& puzzles, ofstream& solutions)
{

    //Attempt to open files
    input.open("input.txt");
    puzzles.open("puzzles2.txt");
    solutions.open("solutions2.txt");

    //Ensure they opened correctly
    if (input.fail())
    {
        cout << "Input file failed to open!" << endl;
        exit(INPUT_FAIL);
    }

    if (puzzles.fail())
    {
        cout << "Output file - puzzles.txt failed to open!" << endl;
        exit(PUZZLES_OUTPUT_FAIL);
    }

    if (solutions.fail())
    {
        cout << "Output file - solutions.txt failed to open" << endl;
        exit(SOLUTIONS_OUTPUT_FAIL);
    }

}


void FillArray(char puzzle[][12], char alphabet[])
{
    int tmp;
    for(int i = 0; i < 12; i++)
    {
        for(int j = 0; j < 12; j++)
        {
            tmp = rand()%26;
            puzzle[i][j] = alphabet[tmp];
        }
    }
}


void PrintPuzzle(char puzzle[][12], ofstream& output)
{
    for(int i = 0; i < 12; i++)
    {
        for(int j = 0; j < 12; j++)
        {
            output <<   puzzle[i][j] << " ";
        }
        output << endl;
    }
}



void CreatePuzzle(char puzzle[][12], ifstream& input, ofstream& puzzles, ofstream& solutions)
{
    string pword; //#the puzzle word being read
    int numwords; //# of words in a given puzzle
    char tmparray[13];
    int wordlength = 0;
    int startloc;

    //Read the number of words to be used in the puzzle
    input >> numwords;

    int vwords = numwords/2; //#of vertical words
    int rwords = numwords/3; //# of reversed words
    int hwords = (numwords - (numwords/2)); //# of horizontal words

    for(int i = 0; i < numwords; i++)
    {
        //Read the word into our tmparray
        input >> pword;
        tmparray[] = pword;
        wordlength = pword.length();

        //Find a random array location to begin inserting the words
        startloc = rand()%12;
    int tmpcount = 0; //a temporary counter to ensure that 
        for(tmpcount; tmpcount <= 1; tmpcount ++)startloc + wordlength < 12)
        {
            for(int j = 0; j <= wordlength; j++)
            {
                puzzle[startloc][startloc]

Ответы [ 4 ]

3 голосов
/ 12 февраля 2010

Сначала попробуйте на бумаге
Тогда заставь это работать (в коде)
Тогда сделай это быстро / эффективно / элегантно

edit - Извините, я не был саркастичен, это было до того, как OP опубликовал код, и не было ясно, что они пытались решить проблему.

2 голосов
/ 12 февраля 2010

Моим первым предложением было бы не беспокоиться о предварительном заполнении массива чем-либо - просто вставьте слова и случайным образом заполните пробелы, как только вы закончите.

1 голос
/ 12 февраля 2010

Несколько мыслей / предложений:

  1. Я думаю, вы могли бы сделать это с одним 2D-массивом вместо двух. Мне кажется, это проще, хотя, конечно, вы можете обнаружить, что я неправ, когда вы садитесь за это.
  2. На шаге 9 вместо того, чтобы найти точку, в которой слово может соответствовать либо прямому, либо обратному, сначала решите, в каком направлении оно будет идти (возможно, с помощью генератора случайных чисел). Затем выберите место и проверьте первое условие и просто вставьте слово, вперед или назад. Помните, что это двумерный массив, поэтому вам нужно посмотреть координаты x и y выбранной точки. Вам также придется посмотреть на слова, которые вы уже поместили в сетку, чтобы убедиться, что вы не перезаписали то, что уже есть.
  3. Чтобы найти перекрестки, подумайте, как бы вы сделали это вручную (как сказал Мартин). Вы уже поместили несколько слов в сетку, и теперь вы хотите добавить новое. Предположим, что пересечений пока не так много, поэтому вы хотите, чтобы текущее слово пересекало одно из тех, которые уже есть в сетке, если это возможно. Как вы узнаете, возможно ли пересечение, и как вы знаете, где разместить слово, чтобы оно создавало пересечение?
0 голосов
/ 12 февраля 2010

Мои первые мысли:

  1. Сначала поместите слова, а затем случайным образом заполните пробелы. Я думаю, что вам будет намного проще визуализировать это таким образом, а также будет легче проверить, правильно ли размещено слово.
  2. После размещения первого слова я бы сохранил слово в массив. После проверки того, достаточно ли второго слова достаточно мало, чтобы соответствовать загадке, я бы попросил программу найти общие буквы слов 1 и 2. Если они имеют общую букву, поместите второе слово так, чтобы два слова пересекались (конечно, сначала проверьте, является ли способ, которым вы пытаетесь разместить слово 2, законным, то есть соответствует ли он головоломке так, как вы пытаетесь ее разместить). Слово 3 аналогично, за исключением поиска возможных пересечений между словами 1 и 2. Если нет возможных пересечений, попробуйте следующее слово. Если после размещения всех слов не может быть 2 или более пересечений, очистите массив и замените первое слово в другой случайной позиции. Разместив слова таким образом, чтобы существовало как минимум два пересечения, вы можете продолжить и разместить остальные слова.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...