2012-05-15 5 views
0

그래서 Boggle 시뮬레이션을 위해 재귀 호출을 구현하는 방법을 알아 내려고하고 있습니다. 인간과 컴퓨터의 두 선수가 있습니다. 인간이 간다면 보드에서 단어가 발견되고 (임의로 섞인), 재귀 호출은 유효성을 검사하기로되어 있습니다. 기본적으로 단어 입력의 인덱스 0에서 시작하여 인접한 문자를 반복해야하고, 그 방법으로 크롤링하고 매번 단어가 존재하는지 여부를 확인해야합니다. 문제는 정확히 어떻게하는지 모르겠습니다. 여기까지 제 코드가 있으며, 제 의도를 더 설명하기 위해 의사 코드를 제공했습니다. 누구든지 도와 줄 수 있습니까?Boggle - 재귀 구현

#include <iostream> 
#include <cctype> 
#include <cmath> 
#include "strlib.h" 
#include "gboggle.h" 
#include "graphics.h" 
#include "grid.h" 
#include "lexicon.h" 
#include "random.h" 
#include "simpio.h" 
#include "Board.h" 

using namespace std; 

/* Constants */ 
const int MIN_WORD_COUNT = 4; 
const int boardSize = 16; 

const int BOGGLE_WINDOW_WIDTH = 650; 
const int BOGGLE_WINDOW_HEIGHT = 350; 

const string STANDARD_CUBES[16] = { 
    "AAEEGN", "ABBJOO", "ACHOPS", "AFFKPS", 
    "AOOTTW", "CIMOTU", "DEILRX", "DELRVY", 
    "DISTTY", "EEGHNW", "EEINSU", "EHRTVW", 
    "EIOSST", "ELRTTY", "HIMNQU", "HLNNRZ" 
}; 

const string BIG_BOGGLE_CUBES[25] = { 
    "AAAFRS", "AAEEEE", "AAFIRS", "ADENNN", "AEEEEM", 
    "AEEGMU", "AEGMNN", "AFIRSY", "BJKQXZ", "CCNSTW", 
    "CEIILT", "CEILPT", "CEIPST", "DDLNOR", "DDHNOT", 
    "DHHLOR", "DHLNOR", "EIIITT", "EMOTTT", "ENSSSU", 
    "FIPRSY", "GORRVW", "HIPRRY", "NOOTUW", "OOOTTU" 
}; 

/* Function prototypes */ 

void welcome(); 
void giveInstructions(); 

void checkBoard(Vector<string>); 
void shakeCubes(int, int, Vector<string> &, Grid<char> &); 
void checkBoardLetters(Grid<char>); 
void checkHumanWords(Set<string>); 
void findHumanWordsOnBoard(Set<string> &, Grid<char>); 
bool boardContainsHumanWord(Grid<char>, string); 

void toupper(string& word); 
bool askQuestion(string question); 
void customConfiguration(int boardSize); 
void shuffleBoard(int boardSize, const string cubes[]); 
void humanTurn(Grid<char>& cubeLetters, Set<string> &alreadyUsedWords, Lexicon &dictionary); 

/* Main program */ 

int main() { 

    initGraphics(BOGGLE_WINDOW_WIDTH, BOGGLE_WINDOW_HEIGHT); 
    welcome(); 
    giveInstructions(); 

    int rows = 4; 
    int cols = 4; 
    int boardSize = rows*cols; 
    Vector<string> vec; 
    Set<string> humanWords; 
    Grid<char> cubeLetters(rows, cols); 
    Lexicon dictionary("EnglishWords.dat"); 

    // Task 1: Copy constant array into a vector vec 
    for(int i = 0; i < rows * cols; i++) 
    { 
     vec.add(STANDARD_CUBES[ i ]); 
    } 

    string instructions = "Do you need instructions?"; 
    if (askQuestion(instructions)) 
     giveInstructions(); 

    string customConfig = "Do you want a custom configuration?"; 
    drawBoard(rows, cols); 
    if (askQuestion(customConfig)){ 
     customConfiguration(boardSize); 
    } 
    else { 
     shakeCubes(rows, cols, vec, cubeLetters); 
    } 
    // Task 2 
    humanTurn(cubeLetters, humanWords, dictionary); 

    // debug 
    //checkHumanWords(humanWords); 

    // Task 3 
    findHumanWordsOnBoard(humanWords, cubeLetters); 

    // debug 
    //checkHumanWords(humanWords); 


    //else { 
     // shuffleBoard(boardSize,STANDARD_CUBES); 
    //} 
    return 0; 
} 

/* 
* Function: shakeCubes 
* Usage: shakeCubes(int, int, Vector<string> &); 
* ----------------- 
* Randomize cubes and their sides. 
*/ 

void shakeCubes(int rows, int cols, Vector<string> &vec, Grid<char> &cubeLetters) 
{ 
    // Shuffle cubes 
    srand (time(NULL)); 
    random_shuffle(vec.begin(), vec.end()); 

    char c; 
    int i = 0, j = 0; 

    // Shuffle cube sides 
    foreach(string s in vec) 
    { 
     c = s[ rand() % 6 ]; 
     labelCube(i, j, c); 
     cubeLetters[ i ][ j ] = c; 

     if(j == 3) 
     { 
      i++; 
      j = 0; 
     } 
     else 
      j++; 
    } 
} 


void humanTurn(Grid<char>& cubeLetters, Set<string> &alreadyUsedWords, Lexicon &dictionary) { 
    cout << endl << "Find all the words you can." 
    << endl << "Signal that you're finished by entering an empty line." << endl << endl; 
    do { 
     cout << "Enter a word: "; 
     string word = getLine(); 

     if(word.empty()) 
      break; // the only way out of the do-while loop 

     toupper(word); 

     if(word.length() < MIN_WORD_COUNT) // word < min word length 
     { 
      cout << "I'm sorry, but we have our standards." << endl 
      << "That word doesn't meet the minimum word length." << endl; 
     } 
     else if(alreadyUsedWords.contains(word)) // word has already been entered 
     { 
      cout << "You've already found that word!" << endl; 
     } 
     else if(dictionary.contains(word)) // word not in lexicon 
     { 
      alreadyUsedWords.add(word); 
      recordWordForPlayer(word, HUMAN); 
     } 
     else 
     { 
      cout << "You can't make that word!" << endl; 
     } 
    } while(true); 
} 


/* 
* Function: checkBoard 
* Usage: checkBoard(Vector<string>); 
* ----------------- 
* Print out current state of Boggle board. 
*/ 

void checkBoard(Vector<string> vec) 
{ 
    cout << endl; 

    foreach(string s in vec) 
    { 
     cout << s << endl; 
    } 
} 

void checkBoardLetters(Grid<char> cubeLetters) 
{ 
    cout << endl; 
    for(int i = 0; i < 4; i ++) 
    { 
     for(int j = 0; j < 4; j++) 
     { 
      cout << cubeLetters[i][j] << endl; 
     } 
    } 
} 

void checkHumanWords(Set<string> humanWords) 
{ 
    cout << endl; 
    foreach(string s in humanWords) 
    { 
     cout << s << endl; 
    } 

    if(humanWords.isEmpty()) 
     cout << "human word set is empty" << endl; 
} 

// Does board contain word? RECURSIVE 
bool boardContainsWord(Grid<char> cubeLetters, string word) 
{ 

    foreach(char c in cubeLetters) 
    for(int i = 0; i < cubeLetters.numRows(); i++) 
    { 
     for(int j = 0; j < cubeLetters.numCols(); j++) 
     { 
      if(cubeLetters[i][j] == word[0]) 
      { 
       if(word.length() == 1) 
        return true; 
       else 
        return boardContainsWord(cubeLetters, word.substr(1)); 
      } 
     } 
    } 

    return false; 
} 
/* 
bool boardContainsLetter(Grid<char> cubeLetters, char letter) 
{ 
    return false; 
} 

// Task 3: Reduce set of HumanWords to those that exist on board 
void findHumanWordsOnBoard(Set<string> &humanWords, Grid<char> cubeLetters) 
{ 
    foreach(string word in humanWords) 
    { 
     if(!boardContainsWord(cubeLetters, word)) 
      humanWords.remove(word); 
    } 
} 
*/ 

/* *** Brainstorming and Under Construction *** 
I need to save (x,y) coordinates and store in a Set collection class to describe path. 

I need a recursive, boolean function that takes in string word, Grid board, and Set path to check valid words. 
This recursion will check each adjacent letter (and can start from top left [row-1][col-1], and move around the chosen letter); 
It also has to check whether it's inBounds before proceeding. 


/* 
* Function: welcome 
* Usage: welcome(); 
* ----------------- 
* Print out a cheery welcome message. 
*/ 

void welcome() { 
    cout << "Welcome! You're about to play an intense game "; 
    cout << "of mind-numbing Boggle. The good news is that "; 
    cout << "you might improve your vocabulary a bit. The "; 
    cout << "bad news is that you're probably going to lose "; 
    cout << "miserably to this little dictionary-toting hunk "; 
    cout << "of silicon. If only YOU had a gig of RAM..." << endl << endl; 
} 

/* 
* Function: giveInstructions 
* Usage: giveInstructions(); 
* -------------------------- 
* Print out the instructions for the user. 
*/ 

void giveInstructions() { 
    cout << endl; 
    cout << endl << "The boggle board is a grid onto which I will randomly distribute" << endl 
     << "dice. These 6-sided dice have letters rather than numbers on the faces, " << endl 
     << "creating a grid of letters on which you try to form words. You go first, " << endl 
     << "entering the words you find that are formed by tracing adjoining " << endl 
     << "letters. Two letters adjoin if they are next to each other horizontally, " << endl 
     << "vertically, or diagonally. A letter can only be used once in the word. Words" << endl 
     << "must be at least 4 letters long and can only be counted once. You score points" << endl 
     << "based on word length, a 4-letter word is worth one, 5-letters two, etc. After your " << endl 
     << "tiny brain is exhausted, I, the brilliant computer, will find all the remaining " << endl 
     << "words in the puzzle and double or triple your paltry score." << endl << endl; 
    cout << "Hit return when you're ready..."; 
    getLine(); 
} 

//Function call to capitalize every letter in a string 
void toupper(string& word) { 
    for(int i = 0; i < word.size(); i++) { 
     word[i] = toupper(word[i]); 
    } 
} 

// A do-while loop to keep asking for a YES/NO answer to a given question 
bool askQuestion(string question) { 
    do { 
     cout << question << " "; 
     string answer = getLine(); 
     if(toupper(answer[0]) == 'N') return false; 
     else if(toupper(answer[0]) == 'Y') return true; 
    } while (cout << "Please answer yes or no." << endl); 

    return 1; 
} 


// Requests user for a board configuration input for the given size board 
// and labels the cubes with the corresponding input string 
void customConfiguration(int boardSize) { 
    cout << endl << "Enter a " << boardSize 
     << "-character string to identify which letters you want on the cubes." 
     << endl << "The first " << sqrt(double(boardSize)) 
     << " letters are the cubes on the top row from left to right " 
     << endl << "next " << sqrt(double(boardSize)) 
     << " letters are the second row, etc." 
     << endl << "Enter the string: "; 
    string answer; 
    do { 
     answer = getLine(); 
     if(answer.size() >= double(boardSize)) break; 
    } while (cout << "String must include " << boardSize 
     << " characters! Try again: "); 
    toupper(answer); 
    int strIndex = 0; 
    for (int row = 0; row < sqrt(double(boardSize)); row++){ 
     for (int col = 0; col < sqrt(double(boardSize)); col++){ 
      char answerSubStr = answer[strIndex]; 
      labelCube(row, col, answerSubStr); 
      strIndex++; 
     } 
    } 
} 

답변

1

(예 : 숙제의 경우) 재귀를 사용하지 않는 한.

대신 단어 목록을 정렬 된 문자로 등가로 사전 처리하십시오. 정렬 된 문자에서 문자 그룹으로 표현할 수있는 단어로 멀티 맵을 작성하십시오.

플레이어가 제안한 작품을 골라 내면 글자를 가져 와서 정렬하고지도에서 찾은 다음 결과 중 하나가 입력 한 것과 일치하는지 확인하십시오. 이것은 기본적으로 항상 적은 수의 항목 일 뿐이므로 각각에 대해 간단한 문자열 비교를 수행 할 수 있습니다.

또 다른 가능성은 단어 목록을 트라이로 만드는 것입니다. 이것은 분명히 더 많은 일이 될 것입니다. 그것은 거의 확실하게 메모리를 절약 할 것이고 아마도 좀 더 빠르게 검색을 수행 할 것입니다. 그러나 컴퓨터가 수천명의 사람들과 동시에 재생 될 수 있도록 boggle 웹 사이트를 실행하지 않으면 문제가 발생하지 않을 것입니다.

+0

감사합니다. :) 실제로 재귀 적으로해야했습니다. 해결책은 흥미 롭습니다. 나는 bool 플래그 그리드를 사용하여 컴퓨터 재귀를 도와야했다. –