暴力求解Calculator:The Game


本文詳實的記錄的我的思考過程,類似流水賬....

目前已經爛尾,我對付不了133關后面的關卡

 

這個手機游戲挺不錯的,就是有點難,所以要寫程序,暴力的通關。

游戲名字:Calculator:The Game

編程語言:python

圖標長這個樣子

 

 游戲界面這個樣子

灰色按鈕表示對數字的操作

游戲很簡單,在步數限制內,將數字變成“目標數字”

目前看上去,很容易,for循環+eval函數就可以解決問題

就算后來出現了乘除 eval函數 也能應付

s = [ "+2" ,"+3"]
begin = 0
end = 8
for i_0 in s:
    for i_1 in s:
        for i_2 in s:
            num = begin
            num =eval( str(num) +i_0 )
            num =eval( str(num) +i_1 )
            num =eval( str(num) +i_2 )
            if num == end:
                print(i_0,end = ",")
                print(i_1,end = ",")
                print(i_2)

后來果然出現了乘除

而且步數限制變成了4,也就是加個for循環的事

后來解鎖了一個新的鍵 它可以刪掉數字的最后一位,例如 4321-->432-->43-->4

其實,它並不算新運算,它就是“//10”

>>> s = ["+8","*5","//10"]
>>> begin = 0
>>> end = 4
>>> game_3(s,begin,end)
+8,*5,//10

ps:我已經悄悄的包裝成函數啦

后來限制步數變成了5 我不想再添for了

現在開始思考

>>> s = ["+2","+3"]
>>> con = s
#定義變量con表示所有可能的解法
#當步數為1時,con就等於s
>>> con = [ (x,y) for x in con for y in s]
>>> con
[('+2', '+2'), ('+2', '+3'), ('+3', '+2'), ('+3', '+3')]
#當步數為2時,兩層遍歷就可以啦
#但是,再遍歷一次可不是步數為3的情況
>>> con_3 = [ (x,y) for x in con for y in s]
>>> con_3
[(('+2', '+2'), '+2'), (('+2', '+2'), '+3'), (('+2', '+3'), '+2'), (('+2', '+3'), '+3'), (('+3', '+2'), '+2'), (('+3', '+2'), '+3'), (('+3', '+3'), '+2'), (('+3', '+3'), '+3')]
#仔細觀察(('+2', '+2'), '+2')可不是想要的格式
#('+2', '+2', '+2')才是
#所以遍歷的時候,需要對x解構
>>> con = [ (*x,y) for x in con for y in s]
>>> con
[('+2', '+2', '+2'), ('+2', '+2', '+3'), ('+2', '+3', '+2'), ('+2', '+3', '+3'), ('+3', '+2', '+2'), ('+3', '+2', '+3'), ('+3', '+3', '+2'), ('+3', '+3', '+3')]
#這才是正確的做法

完整的代碼

    s = tuple(s)
    con = s
    con = ( (x,y) for x in con for y in s)
    for i in range(step-2):
        con = ( (*x,y) for x in con for y in s)

#列表生成式 改成 生成器
#為了避免的不必要的麻煩,list改成tuple

PS:因為這個游戲的特性,步數不可能是1,2(那樣就太簡單了)

然后對con遍歷,尋找正確的解

然后整體加上必要的input(),實際使用中發現,輸入按鈕類型時,輸入大量的引號,對此做點優化

def game():
    begin = int(input("初始數字:"))
    end = int(input("目標數字:"))
    step = int(input("限制步數:"))
    s = []
    n = int(input("按鈕數量:"))
    for i in range(n):
        s.append(input("第%d個:"%(i+1)))
    s = tuple(s)
    con = s
    con = ( (x,y) for x in con for y in s)
    for i in range(step-2):
        con = ( (*x,y) for x in con for y in s)
    for i in con :
        num = begin
        for j in i:
            num = eval(str(num) + j)
        if num == end:
            print(i)

實際的使用情況

>>> game()
初始數字:0
目標數字:404
限制步數:5
按鈕數量:3
第1個:+8
第2個:*10
第3個:/2
('+8', '*10', '*10', '+8', '/2')
>>> game()
初始數字:171
目標數字:23
限制步數:4
按鈕數量:3
第1個:*2
第2個:-9
第3個://10
('-9', '*2', '//10', '-9')
('-9', '//10', '*2', '-9')

 出現里新按鈕 它可以在數字最后面加一個數字 

那也沒問題這個按鈕可以理解為“*10+1”   當然,直接一個1也是可以的

>>> a = 23
>>> b = eval(str(a)+'5')
>>> b
235
初始數字:0
目標數字:56
限制步數:3
按鈕數量:2
第1個:1
第2個:+5
Traceback (most recent call last):
  File "F:\py\測試IDEL\5-3.py", line 48, in <module>
    game()
  File "F:\py\測試IDEL\5-3.py", line 44, in game
    num = eval(str(num) + j)
  File "<string>", line 1
    01
     ^
SyntaxError: invalid token

遭遇了一個錯誤↑↑↑

還是老老實實的寫成*10+1吧

26級左右出現了新按鈕,其實也沒啥, *100+10 就可以啦

我本以為,我可以靠這點代碼打通關的,結果我錯了

好吧對代碼進行微調

    for i in con :
        num = begin
        for j in i:
            if "-/" not in j:
                num = eval(str(num) + j)
            else:
                num = int(str(num).replace( j[0], j[3]))
        if num == end:
            print(i)

使用情況

初始數字:0
目標數字:93
限制步數:4
按鈕數量:3
第1個:+6
第2個:*7
第3個:6-/9
('+6', '6-/9', '*7', '6-/9')

完美  φ(>ω<*) 

32關遭遇bug

初始數字:11
目標數字:29
限制步數:5
按鈕數量:4
第1個:/2
第2個:+3
第3個:1-/2
第4個:2-/9
Traceback (most recent call last):
  File "F:\py\測試IDEL\5-3.py", line 52, in games
    game()
  File "F:\py\測試IDEL\5-3.py", line 47, in game
    num = int(str(num).replace( j[0], j[3]))
ValueError: invalid literal for int() with base 10: '0.6875'

解決方法 : int改為float

當初偷得懶,遲早要還的   T^T

    for i in con :
        num = begin
        for j in i:
            if "-/" not in j:
                num = eval(str(num) + j)
            else:
                k = j.split('-/')
                num = float(str(num).replace( *k ))
        if num == end:
            print(i)

后來出現了負數....-1 *10+5 = -5 對負數而言 應該是*10-5才對

好吧,再改改

    for i in con :
        num = begin
        for j in i:
            if "-/"  in j:
                k = j.split('-/')
                num = float(str(num).replace( *k ))
            elif "++" in j:
                k =int( j.split('++')[-1] )
                num = num*10 + k if num >=0 else num*10 - k
            else:
                num = eval(str(num) + j)  
        if num == end:
            print(i)

Q:k =int( j.split('++')[-1] )中的[-1]是什么意思

A:split產生的是列表,而且++前面的空白也被切出來了..所以不是[0]

>>> '++5'.split('++')
['', '5']

使用情況

初始數字:0
目標數字:-85
限制步數:4
按鈕數量:3
第1個:+6
第2個:++5
第3個:-7
('+6', '-7', '-7', '++5')
('-7', '+6', '-7', '++5')
('-7', '-7', '+6', '++5')

PS:再也不用打*10+5啦,格式改成++5

39左右出現新按鈕

        for j in i:
            if "-/"  in j:
                k = j.split('-/')
                num = float(str(num).replace( *k ))
            elif "++" in j:
                k =int( j.split('++')[-1] )
                num = num*10 + k if num >=0 else num*10 - k
            elif "+-" in j :
                num = -num
            else:
                num = eval(str(num) + j)  
        if num == end:
            print(i)

使用情況

>>>game()
初始數字:0
目標數字:-13
限制步數:4
按鈕數量:3
第1個:+3
第2個:-7
第3個:+-
('+3', '+3', '+-', '-7')

 

看來得加入新東西啦

            if "-/"  in j:
                k = j.split('-/')
                num = float(str(num).replace( *k ))
            elif "++" in j:
                k =int( j.split('++')[-1] )
                num = num*10 + k if num >=0 else num*10 - k
            elif "+-" in j :
                num = -num
            elif "00" in j:
                num = int(str(num)[::-1])
            else:
                num = eval(str(num) + j)  

另外,大量使用中發現,基礎的數據需要手動錄入那沒有辦法,那只能減少其它不必要的按鍵

#原來的
    begin = int(input("初始數字:"))
    end = int(input("目標數字:"))
    step = int(input("限制步數:"))
    s = []
    n = int(input("按鈕數量:"))
    for i in range(n):
        s.append(input("第%d個:"%(i+1)))

#改后
    begin ,end, step = map(int,input("始-終-步:").split(" "))
    s = input("按鈕們:").split(" ")

使用效果

 

遭遇bug

>>>game()
始-終-步:0 58 4
按鈕們:+4 *4 -3 00
('+4', '*4', '00', '-3')
Traceback (most recent call last):
  File "F:\py\測試IDEL\5-3.py", line 65, in games
    game()
  File "F:\py\測試IDEL\5-3.py", line 57, in game
    num = int(str(num)[::-1])
ValueError: invalid literal for int() with base 10: '2-'

負數的問題..

微調下(游戲里面應該不會有“翻轉”負數的情況)

            elif "00" in j:
                if num >= 0:
                    num = int(str(num)[::-1])
                else:
                    break

 

第2個bug

>>>game()
始-終-步:6 4 3
按鈕們:++1 /4 00
Traceback (most recent call last):
  File "F:\py\測試IDEL\5-3.py", line 68, in games
    game()
  File "F:\py\測試IDEL\5-3.py", line 58, in game
    num = int(str(num)[::-1])
ValueError: invalid literal for int() with base 10: '52.51'

看來小數也不行

            elif "00" in j:
                if num >= 0 and num%1 == 0 :
                    num = int(str(num)[::-1])
                else:
                    break

 

又一個bug

>>>game()
始-終-步:6 4 3
按鈕們:++1 /4 00
('++1', '00', '/4')
('/4', '++1', '/4')
Traceback (most recent call last):
  File "F:\py\測試IDEL\5-3.py", line 68, in games
    game()
  File "F:\py\測試IDEL\5-3.py", line 58, in game
    num = int(str(num)[::-1])
ValueError: invalid literal for int() with base 10: '0.61'

浮點數也不行...

            elif "00" in j:
                if num >= 0 :
                    num = int(str(int(num))[::-1])
                else:
                    break

這下應該沒問題啦

62級處,出現無解的情況..

>>>game()
始-終-步:0 102 4
按鈕們:++10 *4 +5 00

原因也找到了,原有的代碼,為了兼容負數,結果兼容不了“添加兩個數字”啦

#原有的
            elif "++" in j:
                k =int( j.split('++')[-1] )
                num = num*10 + k if num >=0 else num*10 - k
#更改后
            elif "++" in j:
                k =  j.split('++')[-1]
                num = int(str(num)+k)

PS,必須用int 不能用eval,下面感受下它們的不同

>>> a = int("010")
>>> a
10
>>> b = eval("010")
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    b = eval("010")
  File "<string>", line 1
    010
      ^
SyntaxError: invalid token

OK bug修復

>>>game()
始-終-步:0 102 4
按鈕們:++10 *4 +5 00
('+5', '*4', '++10', '00')

打臉了,

>>>game()
始-終-步:0 7 4
按鈕們:++2 +1 /3 00
Traceback (most recent call last):
  File "F:\py\測試IDEL\5-3.py", line 71, in games
    game()
  File "F:\py\測試IDEL\5-3.py", line 53, in game
    num = int(str(num)+k)
ValueError: invalid literal for int() with base 10: '7.3333333333333332'

補個int吧

            elif "++" in j:
                k =  j.split('++')[-1]
                num = int(str(int(num))+k)

解決了

>>>game()
始-終-步:0 7 4
按鈕們:++2 +1 /3 00
('++2', '++2', '/3', '00')
('+1', '++2', '00', '/3')

按第一個解法,結果...

我發現這個游戲里顯示不了小數..

按第一個解法

('++2', '++2', '/3', '00')

0 --> 2 --> 22 --> 7.1 --> 7

            else:
                num = eval(str(num) + j)
            if num%1 != 0:
                break
        if num == end:
            print(i)

加上些代碼,由於監測num是否變成小數,一旦變了,直接終止

第71級 無解bug

>>>game()
始-終-步:0 -43 5
按鈕們:-5 +7 -9 00

最終原因,游戲里面實驗了下,負數可以翻轉...-18翻轉成-81..

而我的代碼否定了負數的翻轉...

#之前的
            elif "00" in j:
                if num >= 0 :
                    num = int(str(int(num))[::-1])
                else:
                    break
#改正后
            elif "00" in j:
                if num >= 0 :
                    num = int(str(num)[::-1])
                else:
                    num = int(str(num)[1:][::-1])*-1

PS,由於,num不可能是小數,內層的int就去掉了

>>>game()
始-終-步:0 -43 5
按鈕們:-5 +7 -9 00
('-5', '-9', '00', '+7', '-9')
('-5', '-9', '00', '+7', '00')
('-5', '-9', '00', '-9', '+7')
('-9', '-5', '00', '+7', '-9')
('-9', '-5', '00', '+7', '00')
('-9', '-5', '00', '-9', '+7')

 

......不知道該說些什么...

>>>game()
始-終-步:88 41 4
按鈕們:/4 -4 00
Traceback (most recent call last):
  File "F:\py\測試IDEL\5-3.py", line 73, in games
    game()
  File "F:\py\測試IDEL\5-3.py", line 61, in game
    num = int(str(num)[::-1])
ValueError: invalid literal for int() with base 10: '0.41'
#之前
            if num%1 != 0:
                break
        if num == end:
            print(i)
#之后
            if num%1 != 0:
                break
            else:
                num = int(num)
        if num == end:
            print(i)

 

bug:算出的解,游戲里面沒法用

>>>game()
始-終-步:50 101 5
按鈕們:1-/10 +50 00 5-/1

...

('5-/1', '5-/1', '00', '+50', '+50')

游戲:  如果沒法轉換,按了按鈕,也不算步數...

我的代碼:  如果沒法轉換,按了按鈕,算步數...

結果出現了一些偏差.......

        for j in i:
            if "-/"  in j:
                k = j.split('-/')
                num = float(str(num).replace( *k ))
#改為
        for j in i:
            if "-/"  in j:
                num_0 = num
                k = j.split('-/')
                num = float(str(num).replace( *k ))
                if num_0 == num:
                    break

89級處出現新按鈕

使用+*+表示吧,PS:盡量使用小鍵盤

            elif "+*+" in j:
                num = sum(map(int,str(num)))

103級

>>>game()
始-終-步:9 30 4
按鈕們:-5 *-6 +- +*+
Traceback (most recent call last):
  File "F:\py\測試IDEL\5-3.py", line 80, in games
    game()
  File "F:\py\測試IDEL\5-3.py", line 68, in game
    num = sum(map(int,str(num)))
ValueError: invalid literal for int() with base 10: '-'

經驗證 sum可以對負數求和 -54 --> -9 就是去掉符號再求和

            elif "+*+" in j:
                if num>=0:
                    num = sum(map(int,str(num)))
                else:
                    num = -num
                    num = sum(map(int,str(num)))
                    num = -num
            else:

 

舉個例子1234-->2341-->3412-->4123(這是向左的,還會有向右的)

           elif "/**" in j :
                num = str(num)
                num = int(num[1:]+num[0])
            elif "**/" in j:
                num = str(num)
                num = int(num[-1]+num[:-1])

/*   向左, */  向右

示例

>>>game()
始-終-步:101 121 3
按鈕們:/** **/ +2
('*/', '+2', '/*')
>>>game()
始-終-步:120 210 5
按鈕們:+1 /** +-
Traceback (most recent call last):
  File "F:\py\測試IDEL\5-3.py", line 91, in games
    game()
  File "F:\py\測試IDEL\5-3.py", line 76, in game
    num = int(num[1:]+num[0])
ValueError: invalid literal for int() with base 10: '123-'

負數..負數是去掉符號再移動

            elif "/*" in j :
                fh = 1 if num>=0 else -1
                num = str(abs(num))
                num = int(num[1:]+num[0])
                num = num*fh
            elif "*/" in j:
                fh = 1 if num>=0 else -1
                num = str(abs(num))
                num = int(num[-1]+num[:-1])
                num = num*fh

 

新按鈕,作用 23---> 2332

            elif "---" in j:
                num = str(num)
                num = int(num+num[::-1])

使用

>>>game()
始-終-步:91 19 6
按鈕們:+5 --- +*+
('+5', '+5', '+5', '---', '+5', '+*+')
('+5', '+5', '+5', '---', '+*+', '+5')

...........

經驗證,游戲里面對負數也可以鏡像,老套路,忽略符號....

            elif "---" in j:
                fh = 1 if num>=0 else -1
                num = str(abs(num))
                num = int(num+num[::-1])
                num = num*fh

 

發現新特性,游戲中不能6位以上的數字

            if num%1 != 0 :
                break
            else:
                num = int(num)
#改為
            if num%1 != 0 or num >=10**6 :
                break
            else:
                num = int(num)

 最終代碼

def game():
    begin ,end, step = map(int,input("始-終-步:").split(" "))
    s = input("按鈕們:").split(" ")

    s = tuple(s)
    con = s
    con = ( (x,y) for x in con for y in s)
    for i in range(step-2):
        con = ( (*x,y) for x in con for y in s)
    for i in con :
        num = begin
        for j in i:
            if "-/"  in j:
                num_0 = num
                k = j.split('-/')
                num = float(str(num).replace( *k ))
                if num_0 == num:
                    break
            elif "++" in j:
                k =  j.split('++')[-1]
                num = int(str(num)+k)
            elif "+-" in j :
                num = -num
            elif "00" in j:
                if num >= 0 :
                    num = int(str(num)[::-1])
                else:
                    num = int(str(num)[1:][::-1])*-1
            elif "+*+" in j:
                if num>=0:
                    num = sum(map(int,str(num)))
                else:
                    num = -num
                    num = sum(map(int,str(num)))
                    num = -num
            elif "/**" in j :
                fh = 1 if num>=0 else -1
                num = str(abs(num))
                num = int(num[1:]+num[0])
                num = num*fh
            elif "**/" in j:
                fh = 1 if num>=0 else -1
                num = str(abs(num))
                num = int(num[-1]+num[:-1])
                num = num*fh
            elif "---" in j:
                fh = 1 if num>=0 else -1
                num = str(abs(num))
                num = int(num+num[::-1])
                num = num*fh
            else:
                num = eval(str(num) + j)
            if num%1 != 0 or num >=10**6 :
                break
            else:
                num = int(num)
        if num == end:
            print(i)

爛尾啦

133級遇到了新按鈕,我短時間內找不到解決方法

#

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM