The game of Boggle
任务地址:https://see.stanford.edu/materials/icspacs106b/H22-Assign4Boggle.pdf
一个人机比赛的拼字游戏
It's time for a CS106 classic, the venerable word game Boggle!
核心部分还是递归,写多了真感觉大同小异;
比较难的是九宫格移动时的条件设计,采用双重循环省去类很多重复代码。
还有新的递归结构 :递归结构:if(递归条件) { 标记; 递归; 解除标记;}
和迷宫回溯一样的理念,标记递归过的地方,递归结束时再解除标记,以前为采用的是set类存储递归过的地方
代码:
#include <iostream>
#include "strutils.h"
#include "random.h"
#include "lexicon.h"
#include "simpio.h"
#include "grid.h"
#include "vector.h"
#include "set.h"
#include <string>
using namespace std;
const int Bordsize = 4;
//stanford定义的字符串
string StandardCubes[16] =
{"AAEEGN", "ABBJOO", "ACHOPS", "AFFKPS", "AOOTTW", "CIMOTU", "DEILRX", "DELRVY",
"DISTTY", "EEGHNW", "EEINSU", "EHRTVW", "EIOSST", "ELRTTY", "HIMNQU", "HLNNRZ"};
//board二维数组的建立部分//
Vector<string> StringArrayToVector(string arr[], int boardSize)
{
Vector<string> vec;
int size = boardSize * boardSize;
for (int i = 0; i < size; i++)
{
vec.add(arr[i]);
}
return vec;
}
void FillBoard(Grid<string> &board, Vector<string> &letters)
{
int count = 0;
for (int row = 0; row < board.numRows(); row++)
{
for (int col = 0; col < board.numCols(); col++)
{
board.setAt(row,col,letters[count]);
count++;
}
}
}
void ShuffleBoardCubes(Grid<string> &board)
{
for (int row = 0; row < board.numRows(); row++)
{
for (int col = 0; col < board.numCols(); col++)
{
int randomRow = RandomInteger(row, board.numRows()-1);
int randomCol = RandomInteger(col, board.numCols()-1);
string tmp = board.getAt(row,col);
board.setAt(row,col,board.getAt(randomRow,randomCol));
board.setAt(randomRow,randomCol,tmp);
}
}
}
void ShuffleCubeLetters(Grid<string> &board)
{
for (int row = 0; row < board.numRows(); row++)
{
for (int col = 0; col < board.numCols(); col++)
{
string cubeString = board.getAt(row,col);
int randomChar = RandomInteger(0,cubeString.size()-1);
string letter = cubeString.substr(randomChar, 1);
board.setAt(row,col,letter);
}
}
}
Grid<string> BoardSetup(){
int boardSize = Bordsize; //设定board大小
Grid<string> board(boardSize, boardSize);
Vector<string> cube;
cube = StringArrayToVector(StandardCubes, boardSize);//获取填充用的vector
FillBoard(board, cube);//将cube填入board中, 得到二维数组, 内容为6字符的字符串
ShuffleBoardCubes(board); //打乱次序
ShuffleCubeLetters(board); //从字符串中随机选择一个字符填入
return board;
}
/核心找答案部分/
//递归函数
void FindCompWords(Grid<string> &board, Lexicon &lex, int row, int col,
string soFar, Set<string> & allsoultions)
{
string letter = board.getAt(row,col); // 取出单词
string current = soFar + letter.substr(0,1); // 加入current
// 如果找到单词结束递归
if (current.length() >= 4 && lex.containsWord(current))
{
if(!(allsoultions.contains(current))){
string temp = ConvertToLowerCase(current);
allsoultions.add(temp);
}
return;
}
// 如果不含前缀结束递归
if (!lex.containsPrefix(soFar))
{
return;
}
// 递归结构:条件{ 标记; 递归; 解除标记;}
for (int vert = -1; vert <= 1; vert++)
{
for (int horiz = -1; horiz <= 1; horiz++)
{
// 递归条件:不超过边界 && 没被标记 && 不同时为0(本身)
if (row + vert >= 0 && row + vert < board.numRows() &&
col + horiz >= 0 && col + horiz < board.numCols() &&
board.getAt(row + vert, col + horiz) != "~" &&
!(horiz == 0 && vert == 0))
{
board.setAt(row,col,"~"); // 标记
FindCompWords(board,lex,row+vert,col+horiz,current,allsoultions);//递归
board.setAt(row,col,letter); // 递归结束后取消标记
}
}
}
}
//递归主函数
Set<string> getallsolution(Grid<string> board, Lexicon lex){
int boardSize = board.numRows();
Set<string> allsolutions;
//设定递归传入参量:首字母的行列,初始量soFar, 判别量allsolution
for (int row = 0; row < boardSize; row++)
{
for (int col = 0; col < boardSize; col++)
{
string soFar = "";
FindCompWords(board,lex,row,col,soFar,allsolutions);
}
}
return allsolutions;
}
用户输入部分//
void ParseGuess(string word, Set<string> &guesses,Set<string> & allsolutions )
{
if (guesses.contains(word))//判断是否录过该单词
{
cout << "You've already guessed that word!" << endl;
return;
}
if (word.length() < 4)
{
cout << "Not a valid word!" << endl;
return;
}
// 找到单词
bool haveword = false;
if(allsolutions.contains(word)){
guesses.add(word);
allsolutions.remove(word);
haveword = true;
}
if(!haveword)
cout << "Couldn't find word on board." << endl;
}
//返回用户输入的得到的正确单词组
Set<string> PlayerTurn(Set<string> & allsolutions){
Set<string> guesses;
string word;
while(true)
{
cout << endl << "Enter a word: ";
word = GetLine();
word = ConvertToLowerCase(word);
if (word == "") break;
ParseGuess(word, guesses, allsolutions);
}
return guesses;
}
///画图打印部分/
//把board画出
void DrawBoard(Grid<string> board){
system("clear");
for (int i = 0; i < Bordsize; i++) {
cout << "+---";
}
cout << "+" << endl;
for (int i = 0; i < Bordsize; i++) {
for (int j = 0; j < Bordsize; j++) {
cout << "| " << board[i][j] << " ";
}
cout << "|" << endl;
for (int k = 0; k < Bordsize; k++) {
cout << "+---";
}
cout << "+" << endl;
}
}
//打印成绩和单词
void printset(Set<string> set){
int score =0;
int i = 0;
Set<string>::Iterator It = set.iterator();
while(It.hasNext()){
string temp = It.next();
score += temp.size();
cout << temp <<" ";
if((++i)%10 == 0)
cout <<" "<<endl;
}
cout <<endl;
cout <<"\nthe scores are : "<<score<<endl;
cout << "---------------------------------------------------------"<<endl;
}
//游戏结构部分//
//欢迎
void Welcome() {
cout << "Welcome to my Game ! "<< endl;
cout << "Hit return when you're ready...";
GetLine();
cout << endl;
}
//游戏开始
void StartGame(Lexicon &lex){
Grid<string> board = BoardSetup(); //得到board
DrawBoard(board);
Set<string> allsolutions = getallsolution(board, lex);//找出所有可能的单词
Set<string> playersoltuion = PlayerTurn(allsolutions);
cout << "-- Your sollution is :\n"<<endl;
printset(playersoltuion);
Set<string> computersolution = allsolutions;
cout << "-- The computer's sollution is :\n"<<endl;
printset(computersolution);
}
//设定是否继续
bool PlayAgain()
{
bool rerun = false;
while(true)
{
cout << endl << "Play again? (Y/N) ";
string answer = GetLine();
answer = ConvertToUpperCase(answer);
if (answer == "Y" || answer == "YES")
{
rerun = true;
break;
}
else if (answer == "N" || answer == "NO")
{
rerun = false;
break;
}
}
return rerun;
}
///
int main()
{
Randomize();
Welcome();
Lexicon lex("/Users/elwg/ClionProjects/myboggle/lexicon.dat");
StartGame(lex);
while(true)
{
if(PlayAgain())
{
cout << endl;
StartGame(lex);
}
else
break;
}
return 0;
}
结果展示:
Welcome to my Game !
Hit return when you're ready...
+---+---+---+---+
| I | H | E | A |
+---+---+---+---+
| O | N | T | R |
+---+---+---+---+
| D | G | C | R |
+---+---+---+---+
| O | R | M | N |
+---+---+---+---+
Enter a word: neat
Enter a word:
-- Your sollution is :
neat
the scores are : 4
---------------------------------------------------------
-- The computer's sollution is :
crate doing done dong dorm earth eath ethion gone hear
heat hent hind hint hone hong inearth inert inter near
odor ohing ordo rate rath rend rent tare tear tend
then thin thio thong trend
the scores are : 153
---------------------------------------------------------
Play again? (Y/N)