MATLAB實踐 - 讓計算機去玩24點

這篇文章是從我的訂閱號從copy來的。歡迎關注哈:學術學習小助手。剛開始玩訂閱號,請多指教

  • 概述

可能很多人小時候都玩過24點這個遊戲,遊戲的規則是從紙牌(除去小丑派)中抽四張,每張派只能用一次,通過+、-、x、÷最終得到24的值。

最近想到了這個問題,出現了靈感,決定把它記錄下來。

 

  • 原理

首先是24點的計算過程,取兩張牌,計算,得到一個數,接着重複兩次。最終得到一個數。。。

如果用球形表示數,用方形表示運算符,那麼我們可以這樣表示:

每次取兩個球,一個方塊,計算得到一個新的球,並放到回這個新的球。

重複這個操作三次,就能夠將四個球消去成一個球:

此時,只需要判斷最終剩下的球是不是等於24呢?如果答案是肯定的,那麼這個過程就是求解24點的過程。如果答案是否定的,則需要進行循環,包括運算符和兩個球的的選擇,需要注意,兩個球的順序是有影響的(也就是說可以把球認爲是排列)。這樣循環下去,最終如果所有情況全部遍歷完還沒有解,這時就說明真的沒有解了

這個時候我們需要估計一下,這個循環次數有多少,如果最大的循環次數過大,就不能直接解出來。這個問題不就類似於高中的排列組合問題嘛

 

所有的可能性N爲:

最多循環9216次就能夠得到24點。

 

分析到這我認爲這個問題就可以交給計算機了。

這時用任何編程語言都能夠實現上述的方法(當然,如果邏輯有問題也請各位批評指正)

 

  • 實現

我選擇使用MATLAB的函數來實現上述的方法。

邏輯和原理是一致的,只不過增加了一些判斷防止運算出錯,再次特別說明一下。

  1. 輸入必須爲正整數,如果不是,那麼會報錯。

  2. 運算過程中取出的數也都應當是非零的,如果不是,則會跳過當前循環。

  3. 如果遍歷完還沒有出現解,那麼說明無解;當最終的數與24點差距在0.01以內認爲已經求出解(由於運算過程中可能出現小數,因此需要容錯區間)。

下面分享我的代碼:

function point_24(a,b,c,d)
if a<=0||b<=0||c<=0||d<=0
    error('輸入應爲正整數')
end
xulie=[a b c d];
fuhao=['+-*/'];
temp_0=xulie;
log=[];
​
for i=1:4
    %讀取第1步序列,選擇第1個數
    temp_1_1=temp_0;
    num_1=temp_1_1(i);    
    temp_1_1(i)=[];
    for j=1:3
        %選擇第2個數
        temp_1_2=temp_1_1;
        num_2=temp_1_2(j);
        temp_1_2(j)=[];
        for k=1:4
            %選擇第1次運算,並結果保存到temp_1_C。
            if num_1<=0||num_2<=0
                continue
            end
            temp_cacu=[num2str(num_1),fuhao(k),num2str(num_2)];
            log={log;temp_cacu};
            temp_1_C=[temp_1_2,eval(temp_cacu)];
            for l=1:3
                %讀取第2步序列,選擇第三個數
                temp_2_1=temp_1_C;
                num_3=temp_2_1(l);
                temp_2_1(l)=[];
                for m=1:2
                    %選擇第四個數
                    temp_2_2=temp_2_1;
                    num_4=temp_2_2(m);
                    temp_2_2(m)=[];
                    for n=1:4
                        %選擇第二次運算,並結果保存到temp_2_C。
                        if num_3<=0||num_4<=0
                            continue
                        end
                        temp_cacu=[num2str(num_3),fuhao(n),num2str(num_4)];
                        log={log;temp_cacu};
                        temp_2_C=[temp_2_2,eval(temp_cacu)];
                        for o=1:2
                            %讀取第3步序列,選擇第五個數
                            temp_3_1=temp_2_C;
                            num_5=temp_3_1(o);
                            temp_3_1(o)=[];
                            %選擇第六個數
                            temp_3_2=temp_3_1;
                            num_6=temp_3_2;
                            temp_3_2=[];
                            for p=1:4
                                %選擇第三次運算,並結果保存到temp_3_1。
                                if num_5<=0||num_6<=0
                                    continue
                                end
                                temp_cacu=[num2str(num_5),fuhao(p),num2str(num_6)];
                                log={log;temp_cacu};
                                temp_3_C=[temp_3_2,eval(temp_cacu)];
                                
                                temp_4=temp_3_C;
                                if abs(temp_4-24)<=1e-3
                                    temp_a=[num2str(num_1),fuhao(k),num2str(num_2)];
                                    temp_b=[num2str(num_3),fuhao(n),num2str(num_4)];
                                    temp_c=[num2str(num_5),fuhao(p),num2str(num_6)];
                                    
                                    disp([temp_a,'=',num2str(eval(temp_a))]);
                                    disp([temp_b,'=',num2str(eval(temp_b))]);
                                    disp([temp_c,'=',num2str(eval(temp_c))]);
                                    return 
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end
disp('算不出來')
end

這段代碼保存爲'point_24.m' 放置在MATLAB的工作文件夾就行了。

 

  • 測試

  • 大家可以按照下面的代碼進行測試:

  • A=[4,7,2,12;9,11,5,3;9,3,4,10;8,6,7,7;13,5,8,6;1,9,5,12];
    for e=1:6
      a=A(e,1);
      b=A(e,2);
      c=A(e,3);
      d=A(e,4);
      point_24(a,b,c,d);
      disp(['↑第',num2str(e),'個答案'])
    end

    測試的結果如下:

 

轉載請註明出處

發佈了10 篇原創文章 · 獲贊 27 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章