单词游戏
给出一个4乘4的方格。一个字母只能向相邻的方格延伸
算法思路:主要涉及设计了四个函数
fillboard1:无返回值,人为输入字母,该函数比较简单
fillboard2:无返回值,自动生成字母,使用rand函数随机生成A到Z的大写字母(此处使用了ASCII码),使用srand函数保证rand每次生成的数字是不同的
check:返回值为bool类型,用以判断输入的单词是否满足要求,每次对首字母在邻近的八个方向进行查找,判断是否存在下一个字母,如果存在,则把首字母去掉后进入下一层递归,并以下一层递归的结果判断该路径是否可行,如果不存在则返回false,当字符串的大小为0时,说明该单词符合要求,返回true
computerturn:无返回值,用以查找出所有剩余的单词,从每一个位置开始向相邻的八个方向延伸,当english中无相同前缀的时候,直接返回false以降低时间复杂度,当有相同前缀并且将单词传入check函数返回true时,加上延伸的字母进入下一层递归,直到单词无法再延伸为止
暂时还没有想到好的办法降低时间复杂度
/*
* File: Boggle.cpp
* -----------------------
* Name: [TODO: enter name here]
* This file is the starter code for the Boggle Game problem
* from Assignment #4.
* [TODO: extend the documentation]
*/
#include <cctype>
#include <fstream>
#include <iostream>
#include "gboggle.h"
#include "grid.h"
#include "gwindow.h"
#include "lexicon.h"
#include "random.h"
#include "simpio.h"
#include "sound.h"
#include "console.h"
#include <grid.h>
#include <ctime>
using namespace std;
const int BOGGLE_WINDOW_WIDTH = 650;
const int BOGGLE_WINDOW_HEIGHT = 350;
const string STANDARD_CUBES_FIlE = "cubes16.txt";
const string BIG_BOGGLE_CUBES_FILE = "cubes25.txt";
/* Function prototypes */
void welcome();
void giveInstructions();
void playBoggle();
void fillboard1(Grid<char> & board);
void fillboard2(Grid<char> & board);
bool check(Grid<char> & board, string & word, int & i, int & j, Grid<bool> & path, bool & flag);
void computerturn(Grid<char> & board, int & i, int & j, string & computer, Grid<bool> & path);
/* Main program */
// You need to design specific data structures and functions
// to complete this assignment.
int main() {
welcome();
if (getYesOrNo("Do you need instructions? ")) {
giveInstructions();
}
playBoggle();
return 0;
}
/*
* 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 << "The boggle board is a grid onto which I ";
cout << "I will randomly distribute cubes. These ";
cout << "6-sided cubes have letters rather than ";
cout << "numbers on the faces, creating a grid of ";
cout << "letters on which you try to form words. ";
cout << "You go first, entering all the words you can ";
cout << "find that are formed by tracing adjoining ";
cout << "letters. Two letters adjoin if they are next ";
cout << "to each other horizontally, vertically, or ";
cout << "diagonally. A letter can only be used once ";
cout << "in each word. Words must be at least four ";
cout << "letters long and can be counted only once. ";
cout << "You score points based on word length: a ";
cout << "4-letter word is worth 1 point, 5-letters ";
cout << "earn 2 points, and so on. After your puny ";
cout << "brain is exhausted, I, the supercomputer, ";
cout << "will find all the remaining words and double ";
cout << "or triple your paltry score." << endl << endl;
cout << "Hit return when you're ready...";
getLine();
}
void fillboard1(Grid<char> & board)
{
string tmp;
cin >> tmp;
string tmp2 = toUpperCase(tmp);
if(tmp.length() == 16)
{
int n = 0;
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
board[i][j] = tmp[n];
labelCube(i, j, tmp2[n]);
n++;
}
}
}
else
{
cout << "String must include 16 characters! Try again: ";
fillboard1(board);
}
}
void fillboard2(Grid<char> & board)
{
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
labelCube(i, j, board[i][j]);
}
}
}
bool check(Grid<char> & board, string & word, int & i, int & j, Grid<bool> & path, bool & flag)
{
if(word.length() == 0) return true;
else
{
string tmp;
tmp = word.substr(1, word.length() - 1);
int m, n;
Grid<bool> copy;
if(i == 0 && j == 0)
{
for(int k = i; k <= i+1; k++)
{
for(int l = j; l <= j+1; l++)
{
if(board[k][l] == word[0] && !path[k][l])
{
copy = path;
copy[k][l] = true;
m = k;
n = l;
if(check(board, tmp, m, n, copy, flag))
{
if(flag)
{
highlightCube(m, n, flag);
highlightCube(m, n, false);
}
return true;
}
}
}
}
}
if(i == 0 && j != 0 && j != 3)
{
for(int k = i; k <= i+1; k++)
{
for(int l = j-1; l <= j+1; l++)
{
if(board[k][l] == word[0] && !path[k][l])
{
copy = path;
copy[k][l] = true;
m = k;
n = l;
if(check(board, tmp, m, n, copy, flag))
{
if(flag)
{
highlightCube(m, n, flag);
highlightCube(m, n, false);
}
return true;
}
}
}
}
}
if(i == 0 && j == 3)
{
for(int k = i; k <= i+1; k++)
{
for(int l = j-1; l <= j; l++)
{
if(board[k][l] == word[0] && !path[k][l])
{
copy = path;
copy[k][l] = true;
m = k;
n = l;
if(check(board, tmp, m, n, copy, flag))
{
if(flag)
{
highlightCube(m, n, flag);
highlightCube(m, n, false);
}
return true;
}
}
}
}
}
if(j == 0 && i > 0 && i < 3)
{
for(int k = i-1; k <= i+1; k++)
{
for(int l = j; l <= j+1; l++)
{
if(board[k][l] == word[0] && !path[k][l])
{
copy = path;
copy[k][l] = true;
m = k;
n = l;
if(check(board, tmp, m, n, copy, flag))
{
if(flag)
{
highlightCube(m, n, flag);
highlightCube(m, n, false);
}
return true;
}
}
}
}
}
if(j == 0 && i == 3)
{
for(int k = i-1; k <= i; k++)
{
for(int l = j; l <= j+1; l++)
{
if(board[k][l] == word[0] && !path[k][l])
{
copy = path;
copy[k][l] = true;
m = k;
n = l;
if(check(board, tmp, m, n, copy, flag))
{
if(flag)
{
highlightCube(m, n, flag);
highlightCube(m, n, false);
}
return true;
}
}
}
}
}
if(i == 3 && j > 0 && j < 3)
{
for(int k = i-1; k <= i; k++)
{
for(int l = j-1; l <= j+1; l++)
{
if(board[k][l] == word[0] && !path[k][l])
{
copy = path;
copy[k][l] = true;
m = k;
n = l;
if(check(board, tmp, m, n, copy, flag))
{
if(flag)
{
highlightCube(m, n, flag);
highlightCube(m, n, false);
}
return true;
}
}
}
}
}
if(i == 3 && j == 3)
{
for(int k = i-1; k <= i; k++)
{
for(int l = j-1; l <= j; l++)
{
if(board[k][l] == word[0] && !path[k][l])
{
copy = path;
copy[k][l] = true;
m = k;
n = l;
if(check(board, tmp, m, n, copy, flag))
{
if(flag)
{
highlightCube(m, n, flag);
highlightCube(m, n, false);
}
return true;
}
}
}
}
}
if(j == 3 && i > 0 && i < 3)
{
for(int k = i-1; k <= i+1; k++)
{
for(int l = j-1; l <= j; l++)
{
if(board[k][l] == word[0] && !path[k][l])
{
copy = path;
copy[k][l] = true;
m = k;
n = l;
if(check(board, tmp, m, n, copy, flag))
{
if(flag)
{
highlightCube(m, n, flag);
highlightCube(m, n, false);
}
return true;
}
}
}
}
}
if(j > 0 && j < 3 && i > 0 && i < 3)
{
for(int k = i-1; k <= i+1; k++)
{
for(int l = j-1; l <= j+1; l++)
{
if(board[k][l] == word[0] && !path[k][l])
{
copy = path;
copy[k][l] = true;
m = k;
n = l;
if(check(board, tmp, m, n, copy, flag))
{
if(flag)
{
highlightCube(m, n, flag);
highlightCube(m, n, false);
}
return true;
}
}
}
}
}
}
return false;
}
void computerturn(Grid<char> & board, int & i, int & j, string & computer, Lexicon & used, Lexicon & english, Grid<bool> & path)
{
bool flag = false;
Grid<bool> path2(4, 4, false);
Grid<bool> copy2;
int m, n;
string copy;
string tmp1, tmp2;
bool flag2 = false;
for(string tmp : english)
{
tmp1 = tmp.substr(0, computer.size());
tmp2 = toUpperCase(tmp1);
if(tmp2 == computer)
{
flag2 = true;
break;
}
}
if(flag2)
{
if(i == 0 && j == 0)
{
for(int x = i; x <= i+1; x++)
{
for(int y = j; y <= j+1; y++)
{
copy = computer;
m = x;
n = y;
if(!path[m][n])
{
copy += board[m][n];
copy2 = path;
copy2[m][n] = true;
computerturn(board, m, n, copy, used, english, copy2);
}
}
}
}
if(i == 0 && j != 0 && j != 3)
{
for(int x = i; x <= i+1; x++)
{
for(int y = j-1; y <= j+1; y++)
{
copy = computer;
m = x;
n = y;
if(!path[m][n])
{
copy += board[m][n];
copy2 = path;
copy2[m][n] = true;
computerturn(board, m, n, copy, used, english, copy2);
}
}
}
}
if(i == 0 && j == 3)
{
for(int x = i; x <= i+1; x++)
{
for(int y = j-1; y <= j; y++)
{
copy = computer;
m = x;
n = y;
if(!path[m][n])
{
copy += board[m][n];
copy2 = path;
copy2[m][n] = true;
computerturn(board, m, n, copy, used, english, copy2);
}
}
}
}
if(j == 0 && i > 0 && i < 3)
{
for(int x = i-1; x <= i+1; x++)
{
for(int y = j; y <= j+1; y++)
{
copy = computer;
m = x;
n = y;
if(!path[m][n])
{
copy += board[m][n];
copy2 = path;
copy2[m][n] = true;
computerturn(board, m, n, copy, used, english, copy2);
}
}
}
}
if(j == 0 && i == 3)
{
for(int x = i-1; x <= i; x++)
{
for(int y = j; y <= j+1; y++)
{
copy = computer;
m = x;
n = y;
if(!path[m][n])
{
copy += board[m][n];
copy2 = path;
copy2[m][n] = true;
computerturn(board, m, n, copy, used, english, copy2);
}
}
}
}
if(i == 3 && j > 0 && j < 3)
{
for(int x = i-1; x <= i; x++)
{
for(int y = j-1; y <= j+1; y++)
{
copy = computer;
m = x;
n = y;
if(!path[m][n])
{
copy += board[m][n];
copy2 = path;
copy2[m][n] = true;
computerturn(board, m, n, copy, used, english, copy2);
}
}
}
}
if(i == 3 && j == 3)
{
for(int x = i-1; x <= i; x++)
{
for(int y = j-1; y <= j; y++)
{
copy = computer;
m = x;
n = y;
if(!path[m][n])
{
copy += board[m][n];
copy2 = path;
copy2[m][n] = true;
computerturn(board, m, n, copy, used, english, copy2);
}
}
}
}
if(j == 3 && i > 0 && i < 3)
{
for(int x = i-1; x <= i+1; x++)
{
for(int y = j-1; y <= j; y++)
{
copy = computer;
m = x;
n = y;
if(!path[m][n])
{
copy += board[m][n];
copy2 = path;
copy2[m][n] = true;
computerturn(board, m, n, copy, used, english, copy2);
}
}
}
}
if(j > 0 && j < 3 && i > 0 && i < 3)
{
for(int x = i-1; x <= i+1; x++)
{
for(int y = j-1; y <= j+1; y++)
{
copy = computer;
m = x;
n = y;
if(!path[m][n])
{
copy += board[m][n];
copy2 = path;
copy2[m][n] = true;
computerturn(board, m, n, copy, used, english, copy2);
}
}
}
}
if(computer.length() >= 4)
{
if(used.contains(computer)) return;
if(!english.contains(computer)) return;
else
{
for(int k = 0; k < 4; k++)
{
for(int l = 0; l < 4; l++)
{
if(board[k][l] == computer[0])
{
string tmp = computer.substr(1, computer.length() - 1);
if(check(board, tmp, k, l, path2, flag))
{
recordWordForPlayer(computer, COMPUTER);
used.add(computer);
break;
}
}
}
}
}
computerturn(board, i, j, computer, used, english, path);
}
}
else return;
}
void playBoggle() {
// [TODO: Fill and extend code here]
GWindow gw(BOGGLE_WINDOW_WIDTH, BOGGLE_WINDOW_HEIGHT);
gw.setLocation(50,50);
initGBoggle(gw);
Grid<char> board(4, 4);
Lexicon used;
Lexicon english("EnglishWords.txt");
srand((int)time(0));
while (true) {
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
char tmp = (char)(65 + rand()%26);
board[i][j] = tmp;
}
}
drawBoard(4, 4);
cout << endl;
if(getYesOrNo("I'll give you a chance to set up the board to your specification, which makes it easier to confirm your boggle program is working.Do you want to force the board configuration? "))
{
cout << "Enter a 16-character string to identify which letters you want on the cubes." << endl;
cout << "The first 4 letters are the cubes on the top row from left to right, the next 4 letters are the second row, and so on." << endl;
cout << "Enter the string: ";
fillboard1(board);
}
else
{
fillboard2(board);
}
cout << endl;
cout << "Ok, take all the time you want and find all the words you can! Signal that you're finished by entering an empty line." << endl;
cout << endl;
string tmp;
while(true)
{
cout << "Enter a word: ";
getline(cin , tmp);
if(tmp.length() == 0) break;
else
{
string word = toUpperCase(tmp);
if(word.length() >= 4)
{
if(used.contains(word))
{
cout << "You've already guessed that!" << endl;
continue;
}
if(!english.contains(word))
{
cout << "That's not a word!" << endl;
continue;
}
else
{
bool flag = false;
bool flag2 = true;
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
if(board[i][j] == word[0])
{
string tmp = word.substr(1, word.length() - 1);
Grid<bool> path(4, 4, false);
path[i][j] = true;
if(check(board, tmp, i, j, path, flag2))
{
highlightCube(i, j, true);
highlightCube(i, j, false);
recordWordForPlayer(word, HUMAN);
used.add(word);
flag = true;
break;
}
}
}
}
if(!flag) cout << "You can't make that word!" << endl;
}
}
else
{
cout << "I'm sorry, but we have our standards." << endl;
cout << "That word doesn't meet the minimum word length." << endl;
}
word.clear();
}
}
string computer;
bool flag2 = false;
string tmp1, tmp2;
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
computer = board[i][j];
for(string tmp : english)
{
tmp1 = tmp.substr(0, computer.size());
tmp2 = toUpperCase(tmp1);
if(tmp2 == computer)
{
flag2 = true;
break;
}
}
if(flag2)
{
Grid<bool> path(4, 4, false);
path[i][j] = true;
computerturn(board, i, j, computer, used, english, path);
}
}
}
if (!getYesOrNo("Would you like to play again? ")) break;
}
exitGraphics();
}