前文回顧:
致青春--python實現俄羅斯方塊
人工智慧大火的今天,如果還是自己玩俄羅斯方塊未免顯得太low,為什麼不對遊戲公升級,讓機器自己去玩俄羅斯方塊呢?有了這個想法之後利用週六週日兩天的時間去蒐集了大量的資料,在電腦宕機好多次之後終於將ai俄羅斯方塊實現了。
所謂讓機器自己去玩俄羅斯方塊,就是讓機器計算當前方塊的所有形態可放置的所有位置,然後根據統一的評價標準,計算出最優的位置進行放置。這個評價的標準簡單的來說就是:板塊放置的位置越靠下越好,方塊之間越緊密越好,自身對消除行的方塊貢獻數量越多越好,但是這裡還要注意的是不可為了追求消除行數,而去造成過多的空洞,這樣也是不合理的。
關於ai演算法主要有兩種:一種是經典的pierre dellacherie演算法,一種基於基於深度搜尋的演算法。深度搜尋需要優化的地方很多,假如計算的層數不夠、沒有高效的剪枝,一不小心容易寫**工智障,時間複雜度也不好。pierre dellacherie演算法更加清晰,複雜度更低。但是該演算法只考慮當前,不對未來的情況進行計算,注重的是「不死性」,追求方塊的「密集」,有時就算可以一次性消除 3 行,卻會使全域性方塊更加「疏」,即過多的空洞。
**由三部分組成tetris.py
,ai.py
和
utils.py
遊戲的主要邏輯由tetis控制,utils定義了方塊的樣式,ai顧名思義實現了主要的ai演算法。
只考慮當前方塊,不對未來的情況進行計算,注重的是「不死性」,演算法每次生成乙個方塊,便窮舉該方塊所有旋轉的所有落點。一種方塊最多有 4 種旋轉,並且由於遊戲介面是10*20的,所以對於每個旋轉形狀,只需要考慮10種落點。演算法的核心是乙個評估函式,對窮舉出的每一種下落情況,計算 6 個引數值,用評估函式加權求和得到乙個值,該值最大的情況便是目前方塊的最優下落位置,六個引數分別是:
1.下落高度(landing height):
當前方塊落下去之後,方塊中點距底部的方格數 事實上,不求中點也是可以的,詳見官網。2.消行數(rows eliminated)
消行層數與當前方塊貢獻出的方格數乘積3.行變換(row transitions): 4.列變換(column transitions):大意同上
列變換從一定程度上反映出一列中空洞的集中程度,空洞越集中值越小5.空洞數(number of holes)
不解釋6.井的總和(well sums):
井指兩邊皆有方塊的空列。該指標為所有井的深度連加到1再求總和 注意一列中可能有多個井,如圖:評估函式如下 (首字母簡寫):關於方塊形態相對於上次文章中的俄羅斯方塊,這裡對ai俄羅斯方塊的形態做一下特別說明,各個方塊都是根據中心點的座標來生成的,以(0,0)為中心點,在x、y軸加減1則是其他方格的座標,這個好處就是只要確定中心點座標,其他的方格位置就能隨即生成。看圖就懂↓中間一列為井,深度連加到一的和為 (2+1)+(3+2+1)=9
1# 每種塊包含的四個小方塊相對座標分布
2 self.shapes_relative_coords = [
3 [[0, 0], [0, 0], [0, 0], [0, 0]],
4 [[0, -1], [0, 0], [0, 1], [0, 2]],
5 [[0, -1], [0, 0], [0, 1], [1, 1]],
6 [[0, -1], [0, 0], [0, 1], [-1, 1]],
7 [[0, -1], [0, 0], [0, 1], [1, 0]],
8 [[0, 0], [0, -1], [1, 0], [1, -1]],
9 [[0, 0], [0, -1], [-1, 0], [1, -1]],
10 [[0, 0], [0, -1], [1, 0], [-1, -1]]
11 ]
基於深度搜尋暫時不對此方法作介紹。
【推薦閱讀】
除了畫佩奇我們還要玩點更高階的
【leetcode】貪心演算法--劃分字母區間(763)
機器學習實戰--住房月租金**(3)
俄羅斯方塊
俄羅斯方塊 tetris,俄文 是一款風靡全球的電視遊戲機 和掌上遊戲機遊戲,它由俄羅斯人阿列克謝 帕基特諾夫 發明,故得此名。俄羅斯方塊的基本規則是移動 旋轉和擺放遊戲自動輸出的各種方塊,使之排列成完整的一行或多行並且消除得分。由於上手簡單 老少皆宜,從而家喻戶曉,風靡世界。俄羅斯方塊的開發者是阿...
俄羅斯方塊
include include include include includeusing namespace std include include define mem a,b memset a,b,sizeof a const int sudu 40 const int dir 4 2 cons...
俄羅斯方塊
兩個版本 lufy版 div版 div版本的遊戲開頭和結尾沒有做處理,主要是體會用陣列為座標做遊戲的思想。以下是lufy的原始碼 loading function box box.prototype result i child return result 宣告變數 進度條顯示層,背景層,方塊繪製層...