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

时间:2010-02-12 03:29:38

标签: c++ algorithm

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

问题:

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

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

3
FRODO
GIMLI
ARAGORN

N不会大于10

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

要求:
1.两个输出文件 - 一个包含拼图单词和拼图,一个只有解决方案,没有填充字符
2.需要有与垂直单词一样多的水平单词 3. 1/3的单词需要反转
4.谜题中至少需要有两个交叉点


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

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

我的第一个建议是不要用任何东西预先填充数组 - 只需将文字粘在一起,并在完成后随机填补空白。

答案 2 :(得分:1)

一些想法/建议:

  1. 我认为你可以用一个2D阵列代替两个。在我看来这似乎更简单,但当你坐下来实际实现这一点时,你当然可能会发现我错了。
  2. 在步骤9中,不是找到这个词适合前进或后退的地方,而是首先决定它将进入哪个方向(可能使用随机数生成器)。然后选择一个位置并检查第一个条件,然后插入单词,向前或向后。请记住,这是一个2D数组,因此您需要查看所选点的x和y坐标。您还必须查看已经放置在网格中的单词,以确保不会覆盖已存在的单词。
  3. 为了找到十字路口,想想你将如何手工完成(如马丁所说)。您已在网格中放置了几个单词,现在您想添加一个新单词。假设还没有很多交叉点,那么你想让当前的单词与已经在网格中的其中一个交叉,如果可能的话。你怎么知道交叉路口是否可能,你怎么知道在哪里放置这个词以便它创造一个交叉点?

答案 3 :(得分:0)

我的第一个想法是:

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