CS106B Assignment #4:Boggle

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) 

 

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值