patterncppMinor
Boggle board solver in C++
Viewed 0 times
solverboggleboard
Problem
This C++ Boggle board solver is intended to take in many boards one after another and score them.
I would like comments on code style, whether there are C++ standard library features that I could use to streamline the code, appropriate division between public and private, etc.
Download code
Download dictionary file
Boggle
Boggle is a board game with a 4x4 board of squares, each of which has a letter, in which you score points by finding words on the board. This is an example Boggle board:
This board contains the words 'cat', 'act', 'tact', etc. The words must be made up of neighboring squares (left, right, up, down, and diagonal), and you can't use the same square twice in a word. Words don't need to be in a straight line.
Code
Boggle class
The Boggle class stores the board.
...
```
#include
#include
#include
#include
// Map word lengths to points
std::map POINTS = {{3, 1}, {5, 2}, {6, 3}, {7, 5}, {8, 11}};
// Boggle board class
class Boggle {
private:
struct square {
std::string value;
int row;
int col;
std::vector neighbors;
square(int row, int col);
};
int size;
std::vector board;
Dictionary dict;
std::map points;
std::unordered_set found_words;
void Words(int position, std::string str = "", std::unordered_set visited = std::unordered_set());
public:
Boggle(Dictionary dict, int size = 4, std::map points = POINTS);
~Boggle();
void Load(std::string letters);
void Print();
int Score();
};
// Boggle board constructor
Bogg
I would like comments on code style, whether there are C++ standard library features that I could use to streamline the code, appropriate division between public and private, etc.
Download code
Download dictionary file
Boggle
Boggle is a board game with a 4x4 board of squares, each of which has a letter, in which you score points by finding words on the board. This is an example Boggle board:
c a t c
a t c a
t c a t
c a t cThis board contains the words 'cat', 'act', 'tact', etc. The words must be made up of neighboring squares (left, right, up, down, and diagonal), and you can't use the same square twice in a word. Words don't need to be in a straight line.
Code
Boggle class
The Boggle class stores the board.
boardstores the letters in a vector of structs, each of which stores a letter, the row and column, and a vector of indices for neighboring squares.
Loadloads a string into the board.
Printprints the board.
Scorefinds all words on the board and calculates how much they're worth.
Words(private member function) finds all words starting at a given square on the board.
...
```
#include
#include
#include
#include
// Map word lengths to points
std::map POINTS = {{3, 1}, {5, 2}, {6, 3}, {7, 5}, {8, 11}};
// Boggle board class
class Boggle {
private:
struct square {
std::string value;
int row;
int col;
std::vector neighbors;
square(int row, int col);
};
int size;
std::vector board;
Dictionary dict;
std::map points;
std::unordered_set found_words;
void Words(int position, std::string str = "", std::unordered_set visited = std::unordered_set());
public:
Boggle(Dictionary dict, int size = 4, std::map points = POINTS);
~Boggle();
void Load(std::string letters);
void Print();
int Score();
};
// Boggle board constructor
Bogg
Solution
About the constructor of Boggle
From a stylistic point of view, instead of assigning member fields inside the constructor in java style, the C++ way is rather to use an initializer list.
That is to say, instead of:
You can write:
One big advantage of using an initializer list over assignments inside the constructor's body, is that you can now declare these variables as
Performance
Your code is likely to be much slower than it could be. One source of slowness is the
The first idea is to use a reference instead of a copy. That is to say, use
Another more important idea is that, instead of using a
Yet another performance idea: using a prefix-tree data structure might be a lot faster: https://en.wikipedia.org/wiki/Trie . But there is not such container in standard C++.
From a stylistic point of view, instead of assigning member fields inside the constructor in java style, the C++ way is rather to use an initializer list.
That is to say, instead of:
Boggle::Boggle(Dictionary dict, int size, std::map points) {
this->dict = dict;
this->size = size;
this->points = points;You can write:
Boggle::Boggle(Dictionary dict, int size, std::map points):
dict(dict),
size(size),
points(point)
{One big advantage of using an initializer list over assignments inside the constructor's body, is that you can now declare these variables as
const, or even use a reference instead, which avoids the copy. Using references will save a lot of work, but you have to make sure that the referred-to object is not deleted before the end of the Boggle instance.Performance
Your code is likely to be much slower than it could be. One source of slowness is the
std::unordered_set visited. Each call to the recursive Word function makes a copy of the set. There are two ideas that could improve this a lot.The first idea is to use a reference instead of a copy. That is to say, use
std::unordered_set &visited. With a reference, you also have to make sure that the set is restored to its initial state before quitting the function: add visited.erase(position); before returning.Another more important idea is that, instead of using a
std::set, you could simply use an array of flags that indicate, for each possible position, whether it was visited or not. insert and erase operations on such a representation of a set will be considerably more efficient: it simply consists in setting an array element to true or false.Yet another performance idea: using a prefix-tree data structure might be a lot faster: https://en.wikipedia.org/wiki/Trie . But there is not such container in standard C++.
Code Snippets
Boggle::Boggle(Dictionary dict, int size, std::map<int, int> points) {
this->dict = dict;
this->size = size;
this->points = points;Boggle::Boggle(Dictionary dict, int size, std::map<int, int> points):
dict(dict),
size(size),
points(point)
{Context
StackExchange Code Review Q#146877, answer score: 2
Revisions (0)
No revisions yet.