我來幫你計算24點

背景

24點是一個非常有意思的紙牌遊戲,我在大學的時候經常和那幾個關係非常好的朋友同學一起去三三玩24點遊戲,只是那美好的時光一去不復返。遊戲規則是這樣的:

將4張撲克正面放在桌面上,玩家使用簡單的四則運算對四張牌進行計算,使得計算結果等於24,每張牌只能使用一次

那時候真的玩的不亦樂乎,cyy平時雖然傻里傻氣的,但是玩24點真的一點都不含糊,總是很快就能得出答案。然後,爲了能與之一戰,我用C語言寫了一個計算24點的程序。本來就不是計算機專業出身,所以當時寫的代碼雖然能夠實現功能,但是代碼風格太差,不忍卒睹。現在感慨往昔的日子,所以又用C++的代碼重新寫了一個。

24點計算原理

計算24點的原理並不複雜,因爲是4個數字,3個運算符,所以總共要做3步運算。
第一步: 從 a,b,c,d 四個數字中選出a,b(任意兩個)進行計算,得到e
第二步: 從c,d,e三個數字中選出c,d(任意兩個)進行計算,得到f
第三步: e,f 進行計算,判斷結果是否等於24

代碼實現原理

因爲只有4個數字,本來計算量就不大,所以我採用窮舉遞歸的方式來實現,詳情見實際代碼

代碼

#include <iostream>
#include <cmath>
#include <vector>

std::vector<double> calcNums;
std::vector<char>   calcOps;

bool calc(std::vector<double> lst);

void printSolution()
{
    std::cout << "=======================================" << std::endl;
    for(int expr = 2; expr >= 0; --expr)
    {
        std::cout << "Step" << 3 - expr << ": " ;
        std::cout << calcNums[expr * 3] << calcOps[expr] << calcNums[expr * 3 + 1] << "=" << calcNums[expr * 3 + 2] << std::endl;
    }
    std::cout << "=======================================" << std::endl;
    //calcNums.clear();
    //calcOps.clear();
}
void record(double num1, double num2, double num3, char op)
{
    calcNums.push_back(num1);
    calcNums.push_back(num2);
    calcNums.push_back(num3);
    calcOps.push_back(op);
}
bool try_add(std::vector<double> &lst,double &num1, double &num2)
{
    lst.push_back(num1 + num2);
    if(calc(lst)) 
    {
        record(num1,num2,num1+num2,'+');
        return true;
    }
    else
    {
        lst.pop_back();
        return false;
    }
}
bool try_minus(std::vector<double> &lst,double &num1, double &num2)
{
    lst.push_back(fabs(num1 - num2));
    if(calc(lst)) 
    {
        if(num1 > num2) record(num1,num2,num1-num2,'-');
        else    record(num2,num1,num2-num1,'-');
        return true;
    }
    else
    {
        lst.pop_back();
        return false;
    }
}
bool try_times(std::vector<double> &lst,double &num1, double &num2)
{
    lst.push_back(num1 * num2);
    if(calc(lst)) 
    {
        record(num1,num2,num1*num2,'*');
        return true;
    }
    else
    {
        lst.pop_back();
        return false;
    }
}
bool try_divide(std::vector<double> &lst,double &num1, double &num2)
{
    lst.push_back(num1 / num2);
    if(calc(lst)) 
    {
        record(num1,num2,num1 / num2,'/');
        return true;
    }
    else lst.pop_back();
    lst.push_back(num2 / num1);
    if(calc(lst)) 
    {
        record(num2,num1,num2 / num1,'/');
        return true;
    }
    else 
    {
        lst.pop_back();
        return false;
    }
}
bool calc(std::vector<double> lst)
{
    if(lst.size() > 1)
    {
        for(int i = 0; i < lst.size() - 1; ++i)
        {
            for(int j = i+1; j < lst.size(); ++j)
            {
                std::vector<double> newLst;
                for(int k = 0; k < lst.size(); ++k)
                {
                    if(k != i && k != j)
                    {
                        newLst.push_back(lst[k]);
                    }
                }
                if(try_add(newLst,lst[i],lst[j])   || 
                   try_minus(newLst,lst[i],lst[j]) || 
                   try_divide(newLst,lst[i],lst[j])|| 
                   try_times(newLst,lst[i],lst[j]))
                {
                    return true;
                }
            }
        }
        return false;
    }
    else
    {
        return (fabs(lst[0] - 24) <= 0.0001);
    }
}
int main(int argc, char** argv)
{
    double nums[4] = {0};
    std::cout << "Input 4 integers: ";
    std::cin >> nums[0] >> nums[1] >> nums[2] >> nums[3];
    std::vector<double> numbers;
    for(int idx = 0; idx < 4; ++idx)
    {
        numbers.push_back(nums[idx]);
    }
    if(calc(numbers))
    {
        printSolution();
    }
    else
    {
        std::cout << "These 4 numbers CANNOT calculate to 24!" << std::endl;
    }
}

運行結果

這裏寫圖片描述

最後

時光一逝永不回,往事只能回味

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章