代码之家  ›  专栏  ›  技术社区  ›  noobzilla

C++示例项目-需要帮助的算法

  •  2
  • noobzilla  · 技术社区  · 15 年前

    我有一个朋友给我发送了这个编程任务,这样我就可以复习一下我的C++技巧。下面是程序描述和我提出的算法。请有人提供一些反馈/替代解决方案:

    问题:

    这个程序创建单词搜索谜题——单词在矩形网格中的随机位置打印。单词可以是水平的,也可以是垂直的,可以是向前的(从左到右或从上到下),也可以是反向的(从右到左或从下到上)。未使用的方格用随机字母填充。该程序应将一组单词列表作为输入,并生成两个文件作为输出。第一个列表是每个拼图中的单词列表,然后是拼图本身。第二个应该显示单词在每个拼图中的位置,没有随机的填充字母

    我们的输入文件包含以下内容: 数字n>0(代表拼图中的#个单词)后跟那么多单词。例如:

    3.
    佛罗多
    金利
    阿拉贡

    N将不大于10

    我们需要使用大小为12 x 12的多维数组来创建拼图

    要求:
    1.两个输出文件——一个包含拼图单词和he拼图,一个只包含答案,没有填充字符
    2.水平词的数量应与垂直词的数量相同
    3.三分之一的单词需要颠倒
    4.拼图中至少需要有两个交点


    提议的算法:
    1.创建两个多维数组——一个用于拼图,另一个用于解决方案
    2.创建包含字母表中各种字母的一维数组
    3.用字母表中的随机字母填充拼图数组(使用伪随机生成器和步骤2中的数组)
    4.开始读取输入文件
    5.阅读
    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 回复  |  直到 15 年前
        1
  •  3
  •   Martin Beckett    15 年前

    先在纸上试试
    然后让它工作(在代码中)
    然后让它快速/高效/优雅

    编辑 -抱歉,我不是在讽刺,这是在OP发布代码之前,不清楚他们是否试图解决这个问题。

        2
  •  2
  •   Anon.    15 年前

    我的第一个建议是,不要在数组中预先填充任何内容——只需插入单词,完成后随机填充空白即可。

        3
  •  1
  •   Tyler    15 年前

    一些想法/建议:

    1. 我想你可以用一个2D数组而不是两个。在我看来,这似乎更简单,不过当你坐下来实际实施这一点时,你当然会发现我错了。
    2. 在第9步,不是找到一个单词 能够 无论是正向拟合还是反向拟合,首先确定它将以哪种方式进行(可能使用随机数生成器)。然后选择一个点,检查第一个条件,然后插入单词,向前或向后。记住这是一个2D数组,所以你需要查看你选择的点的x和y坐标。你还必须查看你已经放在网格中的单词,以确保不会覆盖已经存在的内容。
    3. 对于寻找交叉点,想想你会如何用手(就像马丁说的)。您已经在网格中放置了一些单词,现在您想添加一个新单词。假设还没有很多交叉点,所以如果可能的话,你希望当前单词与网格中已经存在的单词相交。你如何知道交叉点是否可能,以及如何知道将单词放置在何处,从而创建交叉点?
        4
  •  0
  •   Erethon    15 年前

    我的第一个想法是:

    1. 先放置单词,然后随机填充空白。我认为这样做对你来说更容易想象,也更容易检查单词的位置是否正确。
    2. 放置第一个单词后,我会将该单词保存到一个数组中。在检查第二个单词是否足够小以适合这个谜题后,我会让程序找到单词1和2的常用字母。如果它们有一个共同的字母,请放置第二个单词,使两个单词相交(当然,您必须首先检查您尝试放置单词2的方式是否合法,也就是说,如果它与您尝试放置它的方式相符)。单词3的用法相同,只是在单词1和2之间寻找可能的交叉点。如果没有可能的交叉点,尝试下一个单词。如果在放置所有单词后不能有两个或更多交叉点,请清空数组并将第一个单词替换到不同的随机位置。在以至少存在两个交叉点的方式放置单词后,可以继续并放置其余单词。