您的位置:首页 > 移动开发 > IOS开发

24点游戏7节课--第3节-格式化结果表达式

2010-06-06 22:59 302 查看
 这是前两节课:

 
24点游戏7节课--第1节-游戏介绍与基本算法
24点游戏7节课--第2节-24点计算处理
 
-----------------------------------------------------------
 
 格式化?是printf吗?
 
不是啦,上一节已经能够计算出给定的4个数,如何计算出24点,只是在答案输出上,有点不爽,比如:5,10,2 ,6四个数,上节课我们输出的答案是:5+10*2-6。 仔细 一算,这答案5+20-6,就是19嘛。这一节课的任务很简单,就是让它能够正确地输出为:(5+10)*2-6.
 
问题关键显然是在加括号上,怎么实现?从运算符号下手,上例中,第一个运算符是+号,第二个则是*,后面的运算符优先级大于前面的,而按照上一节提到“连贯式”的意义,我们要的是前面的运算先处理,所以必须给前面的计算加括号。
 
 
新加exp_getter.h 和 exp_getter.cpp 到项目中。
 
exp_getter.h 

Code:

#ifndef EXP_GETTER_H_INCLUDED    

#define EXP_GETTER_H_INCLUDED    

    

#include <string>    

    

#include "common_def.h"    

    

//组装连续运算形式的表达式:    

std::string get_consecutive_exp(int opds[4], operator_index oprs[3]);    

    

//组装分割运算形式的表达式:    

std::string get_separate_exp(int opds[4], operator_index oprs[3]);    

    

#endif // EXP_GETTER_H_INCLUDED    

 
 
代码文件没有什么好废话的。头文件中就是声明了两个函数,一个函数用来为“连贯式”计算的结果格式化,一个为“分割式”计算的结果格式化——等等,我们还没有讲为“分割式”结果格式化的思路呢?这个太简单了,留给大家先自行看代码再说吧。
 
 
exp_getter.cpp,片段一

Code:

#include <sstream> //for stringstream    

    

#include "exp_getter.h"    

    

using namespace std;    

    

void add_parenthesis(stringstream& ss)    

{    

    ss.str("(" + ss.str() + ")");    

    ss.seekp(0, ios_base::end);        

}  

 
这是给一个字符串加上一对括号的。为了其它一些地方的操作方便,我用的是 stringstream流。如果你不熟悉,那是时候熟悉这家伙了,它是C++ 标准库中一个最常用的家伙。
 
一定要注意哦,这个流将被我们“又读又写”,此时就是“写”,为了保证后续还有的写操作写入位置正确,我们在改变它的内容(这是写入操作)之后,将写的位置,强置到流最后面。
 
 
 
exp_getter.cpp,片段二
继续前面的代码,这是实现格式“连贯式”计算的函数。
 

Code:

string get_consecutive_exp(int n[4], operator_index o[3])    

{    

    stringstream ss;    

        

    //12*2-12*2 ==> (12 * 2 - 12) * 2    

    //2+1*4*2 ==> (2+1)*4*2    

    //2*2+8*2 ==> (2*2+8)*2    

        

    ss << n[0] << operator_char_def[o[0]] << n[1];     

        

    if(o[0] < 2 && o[1] >= 2)     

        add_parenthesis(ss);    

    

    ss << operator_char_def[o[1]] << n[2];    

        

    if (o[1] < 2 && o[2] >= 2)    

        add_parenthesis(ss);    

        

    ss << operator_char_def[o[2]] << n[3];    

        

    return ss.str();    

}    

 
 
n[4]是4张牌的牌面值(再自我检讨一下,入参中的4,不过是用来好看的,根本不起作用,而函数中的代码也没有检查任何数组戴的问题)。 operator_index[3] 则是结果表达式中的那三个操作符(再再自我检讨一下,入参中的3……)。
 
由于我们是用 0,1,2,3,分别表示“+”,"-","*","/"。所以下面的这个if语句:
 
 if (o[1] < 2 && o[2] >= 2)  
 
它在判断什么呢? 其实就是:如果 第1个运算符是加或减,并且第二个运算符是乘或除,则需要进行加括号处理,比如答案是:
 
1 + 3  * 5 +  4  ,则——
 
上述代码第14行,通过流操作,得到:1+3。
 
然后第17行,得到 (1+3)
 
再往后的判断逻辑一样。本例中由于*比+优先级高,所以后面判断结果不需要再添加括号,最终结果就是(1+3)*5+4。
 
会不会忘记 operator_char_def 数组是什么东西?直接说下,免得非要查前面的课程: operator_index 存的是0,1,2,3,用来表示加减乘除,而operator_char_def 才是真正存着 “+,-,*,/”四个字符。
 
 
exp_getter.cpp,片段三
继续前面代码,这是实现“分割式”计算结果的格式化函数:
 

Code:

string get_separate_exp(int n[4], operator_index o[3])    

{    

    stringstream ss;    

            

    //3*4+4*3 ==> (3*4) + (4*3)    

        

    ss << '(' << n[0] << operator_char_def[o[0]] << n[1] << ')'    

        << operator_char_def[o[1]]     

        << '(' << n[2] << operator_char_def[o[2]] << n[3] << ')';    

            

    return ss.str();    

}    

 
 
它简单多了,因为我们是强制加括号,正如代码那行注释,理论是不需要括号的,但我们为了简化处理,就强制添加了。
 
 
有了以上两个函数,回到 calc_24.cpp文件,开始处增加一行:
 
#include "exp_getter.h"
 
然后在 bool calc_24(int num[4])  函数,找到合适的位置,替换原来输出的那两个处代码,编译通过就完成了。现在,我们的输出漂亮极了。下面是实例:
 
 
输入: 12  9  9 3, 输出:(12-9)*9-3。
 
输入:4 5 6 7 ,输出: (5+7-6)*4。
 
-------------------------------------------------------------------------------
 
如果您想与我交流,请点击如下链接成为我的好友:
 
http://student.csdn.net/invite.php?u=112600&c=f635b3cf130f350c
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  游戏 getter 算法 任务 ios c