【问题标题】:C++ Sample Project - Need help with algorithmC++ 示例项目 - 需要算法方面的帮助
【发布时间】:2011-01-16 00:14:28
【问题描述】:

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

问题:

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

我们的输入文件包含以下内容: 一个 n > 0 的数字(表示拼图中的单词数),后面跟着这么多单词。例如:

3
佛罗多
吉姆利
阿拉贡

N 不会大于 10

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

要求:
1. 两个输出文件 - 一个包含拼图单词和他拼图,一个只有解决方案,没有填充字符
2.横字要和竖字一样多
3. 1/3的单词需要倒过来
4. 拼图中至少需要有两个交叉点


建议的算法:
1. 创建两个多维数组 - 一个用于拼图,一个用于解决方案
2. 创建一个包含各种字母的一维数组
3. 用字母表中的随机字母填充拼图数组(使用伪随机 # 生成器和第 2 步中的数组)
4.开始读取输入文件
5. 读入n
6.计数器小于n时,按字读,也有垂直字和水平字的计数器
7.对于每个单词,求字符串的长度
8. 找一个随机数组位置插入单词。
9. 如果随机位置索引 + 字符串长度 = 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]

【问题讨论】:

  • 你有没有尝试过这个,也许你的“朋友”应该先考虑一下,他们会带着关于这个问题的问题回来,而不是寻求解决方案。还要标记家庭作业。
  • 如果是的话,我会把它标记为作业。我知道有很多人在这里发布作业问题,这就是为什么我要求对算法而不是代码提供反馈。顺便说一句,我已经开始对此进行编码,但后来意识到我可能没有一个有效/正确的算法。如果您对我提出的算法有一个有用的观察,也许您可​​以用一个有用的回应来回应我,而不是像上面那样聪明的评论。
  • 查看格式:复制粘贴代码时,请务必点击“101010”小按钮,以便所有代码像代码一样格式化。
  • 嗨 MatrixFrog - 对不起。以为我做到了。现在应该修复了:)
  • 算法中的某些步骤,例如“4. 开始读取输入文件”本身并不是算法的一部分,它们只是需要处理的细节。您当然需要对它们进行编码,但如果将它们从算法中删除,则更容易看到它的基本部分。

标签: c++ algorithm


【解决方案1】:

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

编辑 - 对不起,我没有讽刺,这是在 OP 发布代码之前,不清楚他们是否尝试过这个问题。

【讨论】:

  • 马丁,我实际上已经走上了那条路,但我觉得我走的路并不正确。因此提出了上述要求。
  • 我很乐意发布我编写的代码,但认为没有人愿意涉足它。
  • 贴出代码,让我们看看你目前拥有什么,毕竟阅读别人的代码总是好的做法:)。
  • @noobzilla 支持您的评论“认为没有人愿意涉足它”不是因为没有人愿意这样做,而是因为这里的一些初学者问题是“这是一个巨大的代码的数量;告诉我它是否好”,而不是一个简洁、问得好实际的问题。所以我很感激你试图不那样做。不过,既然 Erethon 愿意看一看,我想你不妨把它贴出来。
  • 在不想涉足一大段代码和想知道提问者实际上正在努力解决问题之间有一个微妙的平衡:)
【解决方案2】:

我的第一个建议是不要费心用任何东西预先填充数组 - 只需将单词插入,并在完成后随机填充空白。

【讨论】:

  • 我认为狡猾的最好用部分匹配真实单词的部分单词来填充它......
【解决方案3】:

一些想法/建议:

  1. 我认为您可以使用一个二维数组而不是两个数组来完成此操作。在我看来,这似乎更简单,当然,当您坐下来实际执行此操作时,您可能会发现我错了。
  2. 在第 9 步,与其寻找单词 可以 正向或反向匹配的位置,不如先决定它要进入的方向(可能使用随机数生成器)。然后选择一个点并检查第一个条件,然后向前或向后插入单词。请记住,这是一个二维数组,因此您需要查看所选点的 x 和 y 坐标。您还必须查看您已经放置在网格中的单词,以确保您不会覆盖已经存在的内容。
  3. 要查找交叉点,请考虑如何手动完成(如 Martin 所说)。您已经在网格中放置了几个单词,现在您想添加一个新单词。假设还没有很多交叉点,所以如果可能的话,您希望当前单词与网格中已经存在的单词之一相交。您如何知道是否可能存在交叉点,以及如何知道在何处放置单词以创建交叉点?

【讨论】:

  • 第 1 点对我来说似乎是合理的。即使你有两个数组,你也不需要填写垃圾字符直到最后。
  • 也许我在这里遗漏了一些非常明显的东西,但如果我尝试在最后插入垃圾字符,我将需要跟踪一大堆数组位置,所以我不t 覆盖数据。
  • 无论如何你都必须这样做,不是吗?否则,当您向网格中添加新单词时,您可能会覆盖已经存在的单词。您可以只用空格或问号之类的东西将空格标记为空白,然后最后用随机字母替换所有空格/问号。
【解决方案4】:

我的第一个想法是:

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

【讨论】:

  • Erethon,Jimmy 对 #1 也有类似的想法 - 请参阅我上面的回复。我认为这种方法会导致更复杂的代码(我一直认为我需要一个更简单的解决方案 - 也许我错了:) 在#2 - 这是一个有趣的方法。我可以试试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-26
  • 1970-01-01
  • 2011-08-20
  • 2011-01-02
  • 1970-01-01
  • 2010-12-30
  • 1970-01-01
相关资源
最近更新 更多