編程語言:python(3.6.4)python
主要應用的模塊:pygame編程
(下面有源碼,可是拒絕分享完整的源碼,下面的代碼整合起來就是完整的源碼)數組
首先列出個人核心思路:app
1,圖像由「核心變量」徹底控制,圖像變化的本質是 變量的改變 2,自上而下式的思考,圖像變化的問題將一步步轉爲 一系列具體的變量修改 3,「核心變量」在思考過程當中並不是不可變動,爲了寫函數方便,能夠適當讓步
正文開始:dom
首先當作品圖預覽圖編程語言
從上圖和遊戲玩法能夠得出如下兩點:函數
1,方塊位置十分有規律學習
2,兩類方塊(上面移動的,下方固定的 都比較有特色)3d
方塊的大小都是固定的,只須要操心位置的問題,下面建座標系code
下一步,座標的儲存方式
###歡迎加羣:725479218,完整源碼,以及pygame的學習方法,都有
記錄方式有兩種:
1,橫縱座標作一個二元元組,再用一個列表裝着一堆二元元組
例如:[(20,1),(20,2),(20,3),(20,4)]表明第20行的1~4列的四個方塊
2,二維數組,一行是一個列表,用兩個索引表明橫縱座標,值爲1就表明有方塊,0就是沒有方塊
例如:block[20][1] 值爲1就表示20行第1列有方塊,block[20][5] 爲0表示20行第5列有沒有方塊
講道理,兩種記錄方式沒什麼大區別,並且第一種彷佛更好用
但後面會有這樣的問題
怎麼判斷一行是否被填滿,填滿後怎麼消除,消除後怎麼使上方的方塊下落。
兩種記錄方式對應的解法:
1,假如判斷第2行 只要依次判斷(2, 0), (2, 1)···· (2, 8), (2, 9) 是否都存在於列表就能夠,消除、下落就有點麻煩,以第2行爲例 遍歷列表 2行如下的不修改,2行的所有清除,2行以上的 行數-1
2,被填滿 等價於 全是1 等價於 沒有0 ,一個not in 就能夠啦,pop就能夠清除一行,並且後面列表的索引會向前補(實現下落),而後在最後補充一個空列表就完事啦(防止被刪光)
因此
充當背景的方塊 就使用2號記錄方式
下一步 對接pygame繪製函數
核心變量的聲明
background = [[0 for i in range(10)]for j in range(21)] active = []
繪製函數
# 初版 def new_draw(): screen.fill(white) for i in range(1, 21): for j in range(10): bolck = background[i][j] if bolck: pygame.draw.rect(screen, blue, (j * 25 + 1, 500 - i * 25 + 1, 23, 23)) for i, j in active: pygame.draw.rect(screen, blue, (j * 25+1, 500 - i * 25 + 1, 23, 23)) pygame.display.update()
補充:座標轉換
鍵盤到圖像(本質:鍵盤到核心變量)
下面簡略列出須要的函數
首先,方塊移動的難點在「旋轉」上
Q:爲何不先考慮左右移動 A:旋轉的問題的有些複雜,須要變動「核心變量」 核心變量一但變動 其它相關函數都得改寫 因此爲了省心,優先考慮可能涉及「核心變量」的事情
解決思路:
1,爲每一個形狀創建一個「狀態庫」,手寫出每一個姿態,旋轉時再讀取
2,旋轉先後存在明確的數學關係
選那個沒有懸念
追加一個變量,記錄旋轉中心座標
旋轉時依照方程轉換座標
公式很簡單吧
若是旋轉在原點,將會更簡單
PS:注意座標系,公式不能直接抄
因此,從記錄「絕對座標」變動爲「中心座標+相對座標」
PS:繪製函數須要作相應的調整
旋轉過程 ( x , y ) --> (-y , x)
重要的細節:移動是有限制的
方塊在邊界處,就得限制向外的移動,若是移動後與已有的方塊重疊,也得限制移動
####代碼時間 左右移動
def move_LR(n): """n=-1表明向左,n=1表明向右""" x, y = centre y += n for i, j in active: i += x j += y if j < 0 or j > 9 or background[i][j]: break else: centre.clear() centre.extend([x, y])
PS:centre是列表
Q:clear + extend 是什麼騷操做?不能夠直接賦值嗎? A:函數內部能夠讀取 但不能修改全局變量 可是能夠調用全局變量的方法 因此clear+extend修改centra 這樣就不用將centra傳入傳出啦 (危險操做,謹慎使用)
旋轉的
def rotate(): x, y = centre l = [(-j, i) for i, j in active] for i, j in l: i += x j += y if j < 0 or j > 9 or background[i][j]: break else: active.clear() active.extend(l)
PS:由於旋轉的機制很簡陋,會有田字形方塊的也能旋轉的奇怪現象發生。
講道理下落並不難,關鍵是下落結束後會有不少後事要處理
1,檢查是否落到底部,是:繼續,否:跳出
2,active的信息轉到background,
3,檢查background是否有「行」被填滿 是:繼續,否:跳至5
4,清掉滿行,補上空行,計分
5,生成新的active,檢查其位置是否被佔(被佔<=>方塊被堆至頂部<=>game over)
那就開始擼代碼
def move_down(): x, y = centre x -= 1 for i, j in active: i += x j += y if background[i][j]: break else: centre.clear() centre.extend([x, y]) return # 若是新位置未被佔用 經過return結束 # 若是新位置被佔用則繼續向下執行 x, y = centre for i, j in active: background[x + i][y + j] = 1 l = [] for i in range(1, 20): if 0 not in background[i]: l.append(i) # l裝 行號,鑑於刪去後,部分索引變化,對其降序排列,倒着刪除 l.sort(reverse=True) for i in l: background.pop(i) background.append([0 for j in range(10)]) # 隨刪隨補 score[0] += len(l) pygame.display.set_caption("分數:%d" % (score[0])) active.clear() active.extend(list(random.choice(all_block))) # all_block保存7種形狀的信息,手打出來的 centre.clear() centre.extend([20, 4]) x, y = centre for i, j in active: i += x j += y if background[i][j]: break else: return alive.append(1)
控制結構 下一步組裝
由於核心變量發生變化,new_draw重寫
def new_draw(): screen.fill(white) for i in range(1, 21): for j in range(10): bolck = background[i][j] if bolck: pygame.draw.rect(screen, blue, (j * 25 + 1, 500 - i * 25 + 1, 23, 23)) x, y = centre for i, j in active: i += x j += y pygame.draw.rect(screen, blue, (j * 25 + 1, 500 - i * 25 + 1, 23, 23)) pygame.display.update()
核心變量定義
all_block = (((0, 0), (0, -1), (0, 1), (0, 2)), ((0, 0), (0, 1), (-1, 0), (-1, 1)), ((0, 0), (0, -1), (-1, 0), (-1, 1)), ((0, 0), (0, 1), (-1, -1), (-1, 0)), ((0, 0), (0, 1), (1, 0), (0, -1)), ((0, 0), (1, 0), (-1, 0), (1, -1)), ((0, 0), (1, 0), (-1, 0), (1, 1))) background = [[0 for i in range(10)] for j in range(24)] background[0] = [1 for i in range(10)] active = list(random.choice(all_block)) centre = [20, 4] score = [0]
for i in range(1, 20): if 0 not in background[i]: l.append(i)
這個部分是從第1行纔開始檢查的(~ ̄▽ ̄)~
pygame固定結構,控制結構,控制變量,龍套變量
pygame.init() screen = pygame.display.set_mode((250, 500)) pygame.display.set_caption("俄羅斯方塊") fclock = pygame.time.Clock() black = 0, 0, 0 white = 255, 255, 255 blue = 0, 0, 255 times = 0 alive = [] press = False while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: move_LR(-1) elif event.key == pygame.K_RIGHT: move_LR(1) elif event.key == pygame.K_UP: rotate() elif event.key == pygame.K_DOWN: press = True elif event.type == pygame.KEYUP: if event.key == pygame.K_DOWN: press = False if press: times += 10 if times >= 50: move_down() times = 0 else: times += 1 if alive: pygame.display.set_caption("over分數:%d" % (score[0])) time.sleep(3) break new_draw() fclock.tick(100)
說明:
1,原來按一次「下」,方塊只會移動一格。。。。
因此修正了一下,支持 長按,爲此加了一個變量press
2,times用於計時
3,遊戲結束的有點突兀,直接就brake啦
最後發現漏了一行沒拷上來
源碼分享,加羣獲取:725479218 羣裏面能夠獲取學習pygame的學習方法 歡迎加入