回 帖 发 新 帖 刷新版面

主题:[原创]我学c++Builder系列(4)

速算24游戏
作者:goal00001111

一,程序效果说明:
    速算24游戏的规则是由系统发出4张扑克牌,要求用户利用扑克牌显示的数字,通过加减乘除运算得出24(可使用括号),为了计算方便,不会出现J,Q,K和王牌。
    当启动应用程序后,程序界面如图1所示。
[img]http://www.cppblog.com/images/cppblog_com/goal00001111/7163/r_0.bmp[/img]

    点击“开始”按钮,游戏开始,系统将发出4张扑克牌。这时游戏的界面如图2所示。
[img]http://www.cppblog.com/images/cppblog_com/goal00001111/7163/r_2.bmp[/img]

    这时用户利用扑克牌显示的数字,通过加减乘除运算,以最快的速度得出24(可使用括号)。然后在文本框中写好表达式,接着点击“计算”按钮。这时系统会计算输入表达式的结果,并告诉用户答案是否正确。
    如下图所示分别是计算正确和错误的界面。

[img]http://www.cppblog.com/images/cppblog_com/goal00001111/7163/r_5.bmp[/img]

[img]http://www.cppblog.com/images/cppblog_com/goal00001111/7163/r_3.bmp[/img]

    如果错了可以再次输入新的表达式,重复上一步。直到您的表达式正确,这时系统会恭喜你算对了。
    游戏还可以计算用户花费的时间,并且能够判断用户的输入是否出现了错误和屏蔽一些不正确的输入,如字母和其他非法字符等等。
    最让我觉得有成就感的是我增加了一个让计算机提供答案的功能。当你百思不得其解的时候,你可以在文本框中输入“114”——就像生活中拨打114热线一样,呵呵——寻求答案。如果有答案的话,系统会跳出一个对话框,告诉用户一个正确的答案,并在当前目录创建一个记事本文件“answer”,把所有的正确答案记录在其中。查询答案界面如图所示。
[img]http://www.cppblog.com/images/cppblog_com/goal00001111/7163/r_4.bmp[/img]

    为了体现模块化的思想,我使用了2个独立单元文件UnitComputer和UnitAnswer,这样可以使各个模块功能更清晰。
    由于是初学,我没有使用菜单等高级技术,读者如果有兴趣,可以改进它,并与我联系。
我的E-MAIL:goal00001111@gmail.com。
    补充:游戏中所用到的扑克牌图片来自于网络,如果你想自己编写这个游戏,别忘了存储扑克牌图片到当前目录文件“扑克牌图片”中。

回复列表 (共9个回复)

沙发

二,设计初始界面:
    
[img]http://www.cppblog.com/images/cppblog_com/goal00001111/7163/r_1.bmp[/img]

        如图所示,初始界面中包括4个Image组件:Image1,Image2,Image3,Image4。其中Image1的Picture属性设置为从文件载入的一张图片,其他3个Image组件的Picture属性为空(等游戏开始后,再动态导入图片)。
    2个Button组件:Button1和Button2,Caption属性分别为“开始”和“计算”。
    1个Label组件,Caption属性初始设置为“使用时间”(等程序运行后,再动态改变Caption属性)。
    1个Edit组件,用来输入运算表达式。
    1个Timer组件,用来记录用户花费的时间。

板凳

三,添加事件处理:
1,    窗体的构造函数:
先在UnitMain.h中增加两个私有属性int ColorData[4];和int SpendTime;分别用来存储扑克牌图片信息和用户花费的时间。
然后切换到UnitMain.cpp中,在窗体Form1的构造函数中,加入下列代码,用于初始化变量和组件:
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    ZeroMemory(ColorData, 0);
    SpendTime = 0;
}
2,“开始”按钮的OnClick事件处理
功能:点击“开始”按钮时,系统随机地发出四张纸牌,显示在四个Image组件中。并将“开始”按钮文字改变为“重新开始”。
代码:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    randomize();

    for (int i=0; i<4; i++)
    {
        ColorData[i] = random(10) + 1;  //随机给出扑克牌的点数
        String FileName = "扑克牌图片\\dw_";
        int num = random(4);   //随机给出扑克牌的花色

        if (num == 0)
            FileName += "c";
        else if (num == 1)
            FileName += "d";
        else if (num == 2)
            FileName += "h";
        else
            FileName += "s";

        FileName += IntToStr(ColorData[i]);
        FileName += ".bmp";

        if (i == 0)  //根据给定的花色和点数信息,从文件中导入对应的扑克牌图片
        {
            Image1->Picture->Bitmap->LoadFromFile(FileName);
        }
        else if (i == 1)
        {
            Image2->Picture->Bitmap->LoadFromFile(FileName);
        }
        else if (i == 2)
        {
            Image3->Picture->Bitmap->LoadFromFile(FileName);
        }
        else
        {
            Image4->Picture->Bitmap->LoadFromFile(FileName);
        }
    }

    Button1->Caption = "重新开始";  //改变Button1的Caption属性
    Edit1->Text = "";
    Edit1->SetFocus();
    SpendTime = 0;          //开始计时
    Timer1->Enabled = true;
}
3,“计算”按钮的OnClick事件处理
功能:点击“开始”按钮时,系统计算用户在Edit组件中输入的运算表达式,并通知用户答案是否正确。如果用户输入了非法数据,系统会给出提示。
代码:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    Timer1->Enabled = false;

    if (!IsInputValide())  //自定义函数,用来判断输入的数据是否合法
    {
        //MessageBox(NULL, "您输入的数据不合法", "输入错误", MB_OK);
        Edit1->SetFocus();
        return;
    }
    const int ANSWER = 24;
    int result;
    try
    {
        result = TotalCompute(Edit1->Text); //自定义函数,用来计算表达式
    }
    catch(...)
    {
        MessageBox(NULL, "您的输入有误", "输入错误", MB_OK);
        Edit1->SetFocus();
        return;
    }

    if (result == ANSWER)
    {
        ShowMessage("对了,你真行!");
    }
    else
    {
        String answer = "您输入的表达式结果为" + IntToStr(result);
        ShowMessage(answer);
    }
}
4,OnCloseQuery事件句柄
功能:当调用Close方法来关闭窗体时,OnCloseQuery事件发生。可以利用OnCloseQuery事件来询问用户是否真的希望马上关闭窗体。
代码:
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
    if (MessageDlg("确定退出应用程序?", mtConfirmation, mbOKCancel, 0) == mrOk)
        CanClose = true;
    else
        CanClose = false;
}
5,计算用户花费时间
功能:显示用户在计算时所花费的时间。每当用户按下“重新开始”按钮,则重新计时。
代码:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    SpendTime++;
    Label5->Caption = "使用时间:" + IntToStr(SpendTime) + "秒";
}
6,不响应非法字符
功能:用户有可能在编辑框中输入数字和算术符号之外的其他字符,我们不应该响应这些非法字符。
代码:
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
    if (!((Key>='0' && Key<='9') || Key=='(' || Key==')' || Key == VK_BACK
        || Key=='+' || Key=='-' || Key=='*' || Key=='/'))
    {
        Key = 0;
    }
}
7,使用回车键代替单击“计算”按钮
功能:用户在编辑框Edit1中输入表达式后,可以直接按回车键要求系统计算答案是否正确。
代码:
void __fastcall TForm1::Edit1KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
    if (Key == VK_RETURN)
    {
           if (Edit1->Text == "114")
        {
            CunShuZi(ColorData); //  由系统给出正确答案
             Edit1->SetFocus();
        }
        else
        {
            Button2Click(Sender);
        }
    }
}

3 楼

8,计算表达式结果
算法思路:此游戏的难点是如何将一个字符串形式的表达式解析成计算机能计算的算术表达式。我们的想法是按照数学四则运算法则,先去掉括号,然后按照先乘除后加减的顺序计算。
按照这种思路,我们必须解决如何寻找匹配的符号,如何寻找算术符号两边的数字,如何定位第一个算术符号的位置等问题。
    新建一个Unit文件“UnitComputer”,打开UnitComputer.h,加入如下代码:
//---------------------------------------------------------------------------

#ifndef UnitComputerH
#define UnitComputerH
#include <vcl.h>


//定位第一个算术符号的位置,如果没有算术符号,则返回0
int AnyFirstPos(String str);

//定位最后一个算术符号的位置,如果没有算术符号,则返回0
int AnyLastPos(String str);

//返回最先出现的算术符号
char AnyFirstF(String str);

//计算不带()号的四则运算,先乘除,后加减
int SubCompute(String str);

//计算带()号的四则运算表达式
int TotalCompute(String str);
//---------------------------------------------------------------------------
#endif
    然后切换到UnitComputer.cpp,实现上述自定义函数。
//---------------------------------------------------------------------------

#pragma hdrstop

#include "UnitComputer.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

//---------------------------------------------------------------------------
//定位第一个算术符号的位置,如果没有算术符号,则返回0
int AnyFirstPos(String str)
{
    const int IMPOSSIBLE = 2000;
    int pos = IMPOSSIBLE; //将pos设置成一个不可能值
    int subPos = str.Pos("-");
    int plusPos = str.Pos("+");
    int mulPos = str.Pos("*");
    int divPos = str.Pos("/");

    //返回第一个算术符号的位置
    if (subPos != 0 && pos > subPos)
        pos = subPos;
    if (plusPos != 0 && pos > plusPos)
        pos = plusPos;
    if (mulPos != 0 && pos > mulPos)
        pos = mulPos;
    if (divPos != 0 && pos > divPos)
        pos = divPos;

    if (pos == IMPOSSIBLE)  //如果没有算术符号,则返回0
        pos = 0;

    return pos;
}
//---------------------------------------------------------------------------
//定位最后一个算术符号的位置,如果没有算术符号,则返回0
int AnyLastPos(String str)
{
    int subPos = str.LastDelimiter("-");
    int plusPos = str.LastDelimiter("+");
    int mulPos = str.LastDelimiter("*");
    int divPos = str.LastDelimiter("/");
    int pos = subPos;

    if (pos < plusPos)
        pos = plusPos;
    if (pos < mulPos)
        pos = mulPos;
    if (pos < divPos)
        pos = divPos;

    return pos;
}
//---------------------------------------------------------------------------
//返回最先出现的算术符号
char AnyFirstF(String str)
{
    //定位第一个算术符号的位置
    int pos = AnyFirstPos(str);
    if (pos == 0)
        return '\0';

    return str[pos];
}
//---------------------------------------------------------------------------
//计算不带()号的四则运算,先乘除,后加减
int SubCompute(String str)
{
    const int IMPOSSIBLE = 2000;
    String midStr = ""; //中间结果
    String leftStr = "";   //左边子串
    String rightStr = "";  //右边子串
    String factor1 = "";   //参与运算的因数1
    String factor2 = "";   //参与运算的因数2

    //定位第一个"*"或"/"的位置
    int mulPos = str.Pos("*");
    int divPos = str.Pos("/");
    int first = 0;

    if (mulPos != 0 && divPos != 0)
    {
        first = (mulPos < divPos) ? mulPos : divPos;
    }
    else if (mulPos == 0 && divPos != 0)
    {
        first = divPos;
        mulPos = IMPOSSIBLE;  //用IMPOSSIBLE替代返回值0,表示没有出现该运算符
    }
    else if (mulPos != 0 && divPos == 0)
    {
        first = mulPos;
        divPos = IMPOSSIBLE;
    }

    while (first)    //循环进行乘除运算
    {
        //获取左子串
        String tempStr = str.SubString(1, first-1);
        int temp = AnyLastPos(tempStr);
        leftStr = str.SubString(1, temp);
        factor1 = str.SubString(temp+1, first-temp-1);
        //获取右子串
        tempStr = str.SubString(first+1, str.Length()-first);
        temp = AnyFirstPos(tempStr);
        if (temp == 0)//右子串中无运算符
        {
            factor2 = tempStr;
            rightStr = "";
        }
        else
        {
            factor2 = tempStr.SubString(1, temp-1);
            rightStr = tempStr.SubString(temp, tempStr.Length()-temp+1);
        }
        //进行乘除运算,得到中间结果
        if (mulPos > divPos)
            midStr = IntToStr(StrToInt(factor1) / StrToInt(factor2));
        else
            midStr = IntToStr(StrToInt(factor1) * StrToInt(factor2));
        //组合新的字符串表达式
        str = leftStr + midStr + rightStr;

        //查找乘除运算符,循环进行乘除运算
        //定位第一个"*"或"/"的位置
        mulPos = str.Pos("*");
        divPos = str.Pos("/");
        first = 0;

        if (mulPos != 0 && divPos != 0)
        {
            first = (mulPos < divPos) ? mulPos : divPos;
        }
        else if (mulPos == 0 && divPos != 0)
        {
            first = divPos;
            mulPos = IMPOSSIBLE;
        }
        else if (mulPos != 0 && divPos == 0)
        {
            first = mulPos;
            divPos = IMPOSSIBLE;
        }
    }

    //定位第一个"+"或"-"的位置
    char fuHao = AnyFirstF(str);
    first = AnyFirstPos(str);

    while (first)//循环进行加减运算
    {
        String tempStr = str.SubString(1, first-1);
        int temp = AnyLastPos(tempStr);
        leftStr = str.SubString(1, temp);
        factor1 = str.SubString(temp+1, first-temp-1);
        //获取右子串
        tempStr = str.SubString(first+1, str.Length()-first);
        temp = AnyFirstPos(tempStr);
        if (temp == 0)//右子串中无运算符
        {
            factor2 = tempStr;
            rightStr = "";
        }
        else
        {
            factor2 = tempStr.SubString(1, temp-1);
            rightStr = tempStr.SubString(temp, tempStr.Length()-temp+1);
        }
        //进行加减运算,得到中间结果
        if (fuHao == '+')
            midStr = IntToStr(StrToInt(factor1) + StrToInt(factor2));
        else
            midStr = IntToStr(StrToInt(factor1) - StrToInt(factor2));
        //组合新的字符串表达式
        str = leftStr + midStr + rightStr;

        //查找加减运算符,循环进行加减运算
        fuHao = AnyFirstF(str);
        first = AnyFirstPos(str);
    }

    return StrToInt(str);
}
//-----------------------------------------------------------------------------
//计算带()号的四则运算表达式
int TotalCompute(String str)
{
    int first = str.LastDelimiter("(");//定位最后一个"("的位置

    while (first)
    {
        String subStr = str.SubString(first+1, str.Length()-first);
        int last = subStr.Pos(")") + first;  //定位与最后一个"("对应的")"的位置
        String leftStrStr = str.SubString(1, first-1);//"("左边的子串
        String midStr = str.SubString(first+1, last-first-1);//"("与")"之间的子串
        String rightStrStr = str.SubString(last+1, str.Length()-last);//")"右边的子串

        midStr = IntToStr(SubCompute(midStr));//计算括号内的算术表达式

        str = leftStrStr + midStr + rightStrStr;
        first = str.LastDelimiter("(");//定位最后一个"("的位置
    }

    return SubCompute(str);//返回运算结果
}

4 楼

9,判断输入的数据是否合法
功能:虽然我们前面已经屏蔽了用户输入的一些非法数据,但是我们仍然不能判断用户输入的数据是否有效,如第一个符号是否合法(只能以数字或"("开头),左右括号是否成对出现,运算表达式中的数字是否与牌面的数字吻合等。
代码:
bool TForm1::IsInputValide() //判断输入的数据是否合法
{
    String tempStr = Edit1->Text;

    //判断第一个符号是否合法(只能以数字或"("开头)
    if ((tempStr.c_str()[0]<'0' || tempStr.c_str()[0]>'9') && tempStr.c_str()[0]!='(')
    {
        ShowMessage("第一个符号不合法");
        return false;
    }

    //判断左右括号是否成对出现
    if (!RightBracket(tempStr))
        return false;

    //去掉括号
    int pos = tempStr.Pos("(");
    while (pos)
    {
        tempStr.Delete(pos, 1);
        pos = tempStr.Pos("(");
    }
    pos = tempStr.Pos(")");
    while (pos)
    {
        tempStr.Delete(pos, 1);
        pos = tempStr.Pos(")");
    }

    //获取输入的数字
    const int MAX = 4; //最多4张牌,结合图片的数量,可以更改MAX的值
    int inputData[MAX];
    int n = 0;

    pos = AnyFirstPos(tempStr);
    while (pos)
    {
        inputData[n++] = StrToInt(tempStr.SubString(1, pos-1));
        tempStr = tempStr.SubString(pos+1, tempStr.Length()-pos);
        pos = AnyFirstPos(tempStr);
    }
    inputData[n] = StrToInt(tempStr);
    if (n != MAX-1) //输入的数不是MAX个
    {
        String s = "输入的数不是";
        s += IntToStr(MAX);
        s += "个";
        ShowMessage(s);
        return false;
    }

    //利用循环判断当前字符是不是属于4张牌中的任何一个
    for (int i=0; i<MAX; i++)
    {
        bool flag = false;
        for (int j=0; j<MAX; j++)
        {
             if (inputData[i] == ColorData[j])
             {
                 flag = true;
                 break;
             }
        }
        if (flag == false) //不属于任何一张牌的数值
        {
            String s = "数据 ";
            s += IntToStr(inputData[i]);
            s += "不属于任何一张牌";
            ShowMessage(s);
            return false;
        }
    }

    //利用循环判断是否所有的牌都出现在运算表达式中
    for (int i=0; i<MAX; i++)
    {
        bool flag = false;
        for (int j=0; j<MAX; j++)
        {
             if (inputData[j] == ColorData[i])
             {
                 flag = true;
                 break;
             }
        }
        if (flag == false) //此张牌没有出现在运算表达式中
        {
            String s = "牌 ";
            s += IntToStr(ColorData[i]);
            s += "没有出现在运算表达式中";
            ShowMessage(s);
            return false;
        }
    }
    return true;
}
//---------------------------------------------------------------------------

bool TForm1::RightBracket(const String & str)//判断左右括号排列是否正确
{
    String tempStr = str;
    const int MAXSIZE = 100;
    char stack[MAXSIZE];
    int top = 0;
    int pos1 = tempStr.Pos("(");
    int pos2 = tempStr.Pos(")");

    while (pos2)
    {
        if (pos1 > 0 && pos1 < pos2)
        {
            stack[top++] = '(';
            tempStr = tempStr.SubString(pos1+1, tempStr.Length()-pos1);
        }
        else if (top > 0 && stack[top-1] == '(')
        {
            top--;
            tempStr = tempStr.SubString(pos2+1, tempStr.Length()-pos2);
        }
        else
        {
            ShowMessage("左右括号排列不正确");
            return false;
        }

        pos1 = tempStr.Pos("(");
        pos2 = tempStr.Pos(")");
    }
    if (top > 0 || tempStr.Pos("(") > 0)//有多余的"("或")"
    {
        ShowMessage("有多余的括号");
        return false;
    }

    return true;
}

5 楼

10,由系统给出正确答案
算法思路:当你希望获取更多的解或者更快的得到答案的话,就可以使用这个功能。我采用穷举的方法,让计算机列出参与运算的数字和符号的各种排列方式,并按照基本运算原则进行计算,最后详细分析了出现括号的各种情况,并以规定的格式进行输出。
新建一个Unit文件“UnitAnswer”,打开UnitAnswer.h,加入如下代码:
//---------------------------------------------------------------------------
#ifndef UnitAnswerH
#define UnitAnswerH

#include <vcl.h>

//穷举法列出参与运算的数字的各种排列方式
void CunShuZi(int num[]);

//回溯法输出各个可能的正确答案
void CunFuHao(int xuhao);

//根据序号返回对应的运算符
char FuHao(int i);

//计算当前四则运算表达式,并返回计算结果
int JiSuan(void);

//记录正确答案到文本文件中
void Print(int n);
//---------------------------------------------------------------------------
#endif
    然后切换到UnitAnswer.cpp,实现上述自定义函数。
//---------------------------------------------------------------------------
#pragma hdrstop

#include "UnitAnswer.h"
//---------------------------------------------------------------------------

#pragma package(smart_init)

const int MAX = 4; //参与运算的数字和符号的数量
int shuZi[MAX];    //存储参与运算的数字
char suanFu[MAX];  //存储可能的运算符,共4个:+,-,*,/
int iFile;          //文件句柄
String str("");    //用来存储各个正确答案

//---------------------------------------------------------------------------
//穷举法列出参与运算的数字的各种排列方式
void CunShuZi(int num[])
{
    DeleteFile("answer.txt");  //销毁原来的文本文件,以便记录本题的正确答案
    iFile = FileOpen("answer.txt", fmOpenReadWrite);
    if (iFile == -1)        //新建文件
        iFile = FileCreate("answer.txt", fmOpenReadWrite);

    int i, j, k;
       for (i=0; i<MAX; i++)//穷举法列出参与运算数字的各种排列方式
       {
        shuZi[0] = num[i];
          for (j=0; j<MAX; j++)
        {
              if (i != j)
             {
                   shuZi[1] = num[j];
                 for (k=0; k<MAX; k++)
                 {
                    if (i != k && j != k)
                        {
                        shuZi[2] = num[k];
                              shuZi[3] = num[6-i-j-k];
                         CunFuHao(0);//存储运算符
                    }
                }
            }
        }
    }
    //输出最后一个答案到对话框,若无解则对话框的内容为空白
    MessageBox(NULL, str.c_str(), "答案", MB_OK);
    //MessageBox(NULL, "无解", "答案", MB_OK);
    FileClose(iFile);
}
//---------------------------------------------------------------------------
//回溯法输出各个可能的正确答案
void CunFuHao(int xuhao)
{
    int i;
   
       for (i=0; i<=3; i++)
       {
          suanFu[xuhao] = FuHao(i);
          if (xuhao < 2)
          {
            CunFuHao(xuhao+1);
        }
         else
         {
              Print(JiSuan()); //记录当前正确答案
        }
       }
}
//---------------------------------------------------------------------------
//根据序号返回对应的运算符
char FuHao(int i)
{
       switch(i)
       {
          case 0: return '+';
          case 1: return '-';
          case 2: return '*';
          case 3: return '/';
       }
}
//---------------------------------------------------------------------------
//计算当前四则运算表达式,并返回计算结果
int JiSuan(void)
{
       int i;
       int result, sum1, sum2;
       int flag0, flag1, flag2;

    //判断第一,二,三个运算符是否为乘除运算符
       flag0 = (suanFu[0] == '*' || suanFu[0] == '/');
       flag1 = (suanFu[1] == '*' || suanFu[1] == '/');
       flag2 = (suanFu[2] == '*' || suanFu[2] == '/');

       if (!flag0 && flag1 && !flag2)//型如(a+b)*(c+d)
      {
         if (suanFu[0] == '+')
              sum1 = shuZi[0] + shuZi[1];
          else
              sum1 = shuZi[0] - shuZi[1];
          
        if (suanFu[2] == '+')
              sum2 = shuZi[2] + shuZi[3];
          else
              sum2 = shuZi[2] - shuZi[3];
          
        if (suanFu[1] == '*')
              result = sum1 * sum2;
          else if (sum2 != 0 && sum1%sum2 == 0 )
                 result = sum1 / sum2; /*前后两个数必须能整除,且分母不为0*/
           else                       /*否则返回值12345(表示无效)*/
               result = 12345;
       }
       if (result == 24) //得到型如(a+b)*(c+d)的答案
          return 1;
    
    if (suanFu[0] == '*' && suanFu[1] == '/' && !flag2)//型如a*b/(c+d)
      {
        result = shuZi[0] * shuZi[1];
        
         if (suanFu[2] == '+')
              sum1 = shuZi[2] + shuZi[3];
          else
              sum1 = shuZi[2] - shuZi[3];
          
        if (sum1 != 0 && result%sum1 == 0 )
                 result /= sum1; /*前后两个数必须能整除,且分母不为0*/
        else                       /*否则返回值12345(表示无效)*/
               result = 12345;
       }
       if (result == 24)//得到型如a*b/(c+d)的答案
          return 2;
          
       if (suanFu[0] == '/' && !flag1 && !flag2)//型如a/(b+c)+d
      {
         if (suanFu[1] == '+')
              sum1 = shuZi[1] + shuZi[2];
          else
              sum1 = shuZi[1] - shuZi[2];
          
        if (sum1 != 0 && shuZi[0]%sum1 == 0 )
                 result = shuZi[0] / sum1; /*前后两个数必须能整除,且分母不为0*/
        else                    
               goto A;

       if (suanFu[2] == '+')
          result += shuZi[3];
       else if (suanFu[2] == '-')
          result -= shuZi[3];
       }
A:
       if (result == 24) //得到型如a/(b+c)+d的答案
          return 3;
          
    if (flag0 && !flag1 && flag2)//型如a*b+c*d
      {
        if (suanFu[0] == '*')
              sum1 = shuZi[0] * shuZi[1];
          else if (shuZi[1] != 0 && shuZi[0]%shuZi[1] == 0 )
                 sum1 = shuZi[0] / shuZi[1]; /*前后两个数必须能整除,且分母不为0*/
           else
               goto B;

        if (suanFu[2] == '*')
              sum2 = shuZi[2] * shuZi[3];
          else if (shuZi[3] != 0 && shuZi[2]%shuZi[3] == 0 )
                 sum2 = shuZi[2] / shuZi[3]; /*前后两个数必须能整除,且分母不为0*/
           else
               goto B;
               
          if (suanFu[1] == '+')
              result = sum1 + sum2;
           else
               result = sum1 - sum2;
       }
B:
    if (result == 24) //得到型如a*b+c*d的答案
          return 4;   

       result = shuZi[0];
       for (i=0; i<=2; i++)//其他形式
       {
           switch(suanFu[i])
           {
                case '+':  result += shuZi[i+1]; break;
                case '-':  result -= shuZi[i+1]; break;
                case '*':  result *= shuZi[i+1]; break;
                case '/':  if (shuZi[i+1] != 0 && result%shuZi[i+1] == 0 )
                                        result /= shuZi[i+1]; /*前后两个数必须能整除,且分母不为0*/
                           else                       /*否则返回值12345(表示无效)*/
                                       result = 12345;
                           break;
        }
    }
       if (result == 24) //得到其他形式的答案
          return 5;
   
   return 0;   //无解
}
//---------------------------------------------------------------------------
//记录正确答案到文本文件中
void Print(int n)
{
    if (n == 0)  //无解则不记录,直接返回到CunFuHao函数
       return;
       
    str = "     ";
       int flag0, flag1, flag2;

    //判断第一,二,三个运算符是否为乘除运算符
       flag0 = (suanFu[0] == '*' || suanFu[0] == '/');
       flag1 = (suanFu[1] == '*' || suanFu[1] == '/');
       flag2 = (suanFu[2] == '*' || suanFu[2] == '/');
   
       if    (n == 1)     //型如(a+b)*(c+d)
       {
        str += "(";
        str += shuZi[0];
        str += suanFu[0];
        str += shuZi[1];
        str += ")";
        str += suanFu[1];
        str += "(";
        str += shuZi[2];
        str += suanFu[2];
        str += shuZi[3];
        str += ")";
       }
       else if    (n == 2)    //型如a*b/(c+d)
       {
        str += shuZi[0];
        str += "*";
        str += shuZi[1];
        str += "/";
        str += "(";
        str += shuZi[2];
        str += suanFu[2];
        str += shuZi[3];
        str += ")";
       }
       else if    (n == 3)      //型如a/(b+c)+d
       {
        str += shuZi[0];
        str += "/";
        str += "(";
        str += shuZi[1];
        str += suanFu[1];
        str += shuZi[2];
        str += ")";
        str += suanFu[2];
        str += shuZi[3];
        
       }
       else if (n==5 && !flag0 && flag1) //型如(a+b)*c+d
       {
          str += "(";
        str += shuZi[0];
        str += suanFu[0];
        str += shuZi[1];
        str += ")";
        str += suanFu[1];
        str += shuZi[2];
        str += suanFu[2];
        str += shuZi[3];
       }
       else if (n==5 && !flag1 && flag2)//型如(a+b+c)*d
       {
          str += "(";
        str += shuZi[0];
        str += suanFu[0];
        str += shuZi[1];
        str += suanFu[1];
        str += shuZi[2];
        str += ")";
        str += suanFu[2];
        str += shuZi[3];
       }
    else  //不带括号的情况
       {
        for (int i=0; i<=2; i++)
         {
            str += shuZi[i];
            str += suanFu[i];
          }
        str += shuZi[3];
       }
    FileWrite(iFile, str.c_str(), str.Length());//记录正确答案
    //MessageBox(NULL, str.c_str(), "答案", MB_OK);
}

6 楼

结语:
    至此,实现了我想要的功能。
    为了让您更好的参看这个程序,我给出UnitMain.h的内容。
//---------------------------------------------------------------------------
#ifndef UnitMainH
#define UnitMainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <jpeg.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
    TButton *Button1;
    TButton *Button2;
    TEdit *Edit1;
    TImage *Image1;
    TImage *Image2;
    TImage *Image3;
    TImage *Image4;
    TLabel *Label5;
    TTimer *Timer1;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall Button2Click(TObject *Sender);
    void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose);
    void __fastcall Timer1Timer(TObject *Sender);
    void __fastcall Edit1KeyPress(TObject *Sender, char &Key);
    void __fastcall Edit1KeyDown(TObject *Sender, WORD &Key,
          TShiftState Shift);
private:    // User declarations
    int ColorData[4];
    int SpendTime;
    bool IsInputValide();
    bool RightBracket(const String & str);
public:        // User declarations
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
        
                                                        goal00001111于2008-05-25
(全文完)

7 楼

不错啊....

8 楼

很人问过这个问题…苍白…有用么。法师基本是一个要和对方保持距离,让对方一下都打不中自己的职业,攻击在于一堆九级魔法。苍白让你推迟得到九级魔法,得到的是2点你一定不会用的攻击值,6点有等于没有的防守值,三个普通法师可以学的魔法,一个你永远都打不中高手的特别攻击,一堆没用的绝缘。除了角色扮演,我想不到要用苍白的任何理由。

9 楼

中通网社区免责声明1、本贴由flyferrari原创或转载,其依照《资料版权问题以及免责声明》享有相关权利;2、本帖如有侵犯到贵站或个人版权问题,请通过《要求移除诉求》申请处理;3、本站管理员和版主有权不事先通知发帖者而删除本文。

我来回复

您尚未登录,请登录后再回复。点此登录或注册