1. 程式人生 > >[Python3] 2048小遊戲

[Python3] 2048小遊戲

程式碼來源:https://www.shiyanlou.com/courses/368/labs/1172/document

小白,最近看到實驗樓的2048的小遊戲,在程式碼上帶了自己的註釋。

前期準備:

  1. 有限狀態機      ##https://www.cnblogs.com/21207-iHome/p/6085334.html
  2. defaultdict()    ##https://blog.csdn.net/real_ray/article/details/17919289
  3. zip()    ##zip() 函式用於將可迭代的物件作為引數,將物件中對應的元素打包成一個個元組,然後返回由這些元組組成的列表。
  4. assert  ##在開發一個程式時候,與其讓它執行時崩潰,不如在它出現錯誤條件時就崩潰(返回錯誤)。
  5. randrange()  ##randrange() 方法返回指定遞增基數集合中的一個隨機數,基數預設值為1。
  6. any()   ##any() 函式用於判斷給定的可迭代引數 iterable 是否全部為空物件,如果都為空、0、false,則返回 False,如果不都為空、0、false,則返回 True。
  7. curses()   //關於curses的使用與安裝,將會另外開一篇文章來說
#-*- coding:utf-8 -*-
import curses
from random import randrange, choice
from collections import defaultdict


letter_codes = 
[ord(ch) for ch in 'WASDRQwasdrq'] #ord函式是把字元轉換成對應的數字 actions = ['Up','Left','Down','Right','Restart','Exit'] actions_dict = dict(zip(letter_codes,actions * 2)) #zip是把元組的數值對應起來 def get_user_action(keyboard): char = "N" ##初始值為N while char not in actions_dict: char = keyboard.getch() return
actions_dict[char] def transpose(field): return [list(row) for row in zip(*field)] ##相當於旋轉90度。zip後加*,是把行變成列,把列變成行 def invert(field): return [row[::-1] for row in field] #步長為-1。相當於是調轉180,把前後列表調轉 ##Merge and tighten,移動方向時候應該有的邏輯判斷, 整個遊戲的畫面繪製,規則定製等。 class GameField(object): def __init__(self,height=4,width=4,win=2048): self.height = height self.width = width self.win_value = win self.score = 0 self.highscore = 0 self.reset() def reset(self): if self.score >self.highscore: self.highscore = self.score self.score = 0 self.field = [[0 for i in range(self.width)] for j in range(self.height)] #橫縱座標恢復為0 self.spawn() #呼叫spawn函式,下面會有定義 self.spawn() def move(self,direction): def move_row_left(row): def tighten(row): #squeese non-zero elements together new_row = [i for i in row if i!= 0] new_row += [0 for i in range(len(row)-len(new_row))] #其餘位置用0fill in return new_row def merge(row): pair = False new_row = [] for i in range(len(row)): #在格子裡迴圈 if pair: #如果pair為真 new_row.append(2 * row[i]) #乘以2的值追加到new_rowself.score += 2 * row[i] pair = False else: if i + 1 < len(row) and row[i] == row[i+1]: #如果pair為假,然後i+1還沒到邊界,並且row[i]=row[i+1] pair = True ##那麼執行上面的pair為真的部分 new_row.append(0) #追加0 else: new_row.append(row[i]) #pair為假,不能合併,超出邊界,多加row[i] assert len(new_row) == len(row) ##報錯提醒 return new_row return tighten(merge(tighten(row))) #先擠在一起,然後合併,然後再擠在一起 moves = {} #將只有一個方向左,旋轉90度成為向上(transpose(field)),利用左方向調轉(invert(field))成為右方向。因此擁有四個方向 moves['Left'] = lambda field: [move_row_left(row) for row in field] moves['Right'] = lambda field: invert(moves['Left'](invert(field))) ##moves['Left']已經定義了mergetighten的操作 moves['Up'] = lambda field: transpose(moves['Left'](transpose(field))) moves['Down'] = lambda field: transpose(moves['Right'](transpose(field))) if direction in moves: if self.move_is_possible(direction): self.field=moves[direction](self.field) self.spawn() return True else: return False #輸贏判斷 def is_win(self): return any(any(i >= self.win_value for i in row) for row in self.field) #i在格子中,並且i的值超出了2048 def is_gameover(self): return not any(self.move_is_possible(move) for move in actions) ###遊戲頁面繪製 def draw(self,screen): help_string1='(W)Up (S)Down (A)Left (D)Right' help_string2=' (R)Restart (Q)Exit' gameover_string=' Game Over' win_string=' Congratulation! You Win!' def cast(string): screen.addstr(string +'\n') def draw_hor_separator(): ##橫座標分割線 line = '+' + ('+------' * self.width + '+')[1:] separator = defaultdict(lambda:line) if not hasattr(draw_hor_separator,"counter"): draw_hor_separator.counter = 0 cast(separator[draw_hor_separator.counter]) draw_hor_separator.counter += 1 def draw_row(row): cast(''.join('|{: ^5} '.format(num) if num > 0 else '| ' for num in row) + '|') #在螢幕上畫豎列 screen.clear() cast('SCORE: ' + str(self.score)) if 0 != self.highscore: cast('HIGHSCORE: ' + str(self.highscore)) for row in self.field: draw_hor_separator() draw_row(row) draw_hor_separator() if self.is_win(): cast(win_string) else: if self.is_gameover(): cast(gameover_string) else: cast(help_string1) cast(help_string2) ##隨機生成2或者4 def spawn(self): new_element = 4 if randrange(100) > 89 else 2 #100次有89次出現4 (i,j) = choice([(i,j) for i in range(self.width) for j in range(self.height) if self.field[i][j]==0]) ##就是2,4隨機出現的區域,要在widthheight的裡面。前提self.field[i][j]==0 self.field[i][j] = new_element ##那麼, 2,4出現的要獲取他的橫縱座標 ##判斷是否可移動 def move_is_possible(self, direction): def row_is_left_movable(row): def change(i): ##True if there will be change in i-th tile if row[i] == 0 and row[i+1] != 0: ##有空位可以移動 return True if row[i] != 0 and row[i+1] == row[i]: ##沒有空位,但是二者數值相同可以合併處理及移動 return True return False return any(change(i) for i in range(len(row)-1)) ##any()為一個函式,全為0false check ={} check['Left'] = lambda field: any(row_is_left_movable(row) for row in field) check['Right'] = lambda field: check['Left'](invert(field)) check['Up'] = lambda field: check['Left'](transpose(field)) check['Down'] = lambda field: check['Right'](transpose(field)) if direction in check: return check[direction](self.field) else: return False ##Main Logic def main(stdsrc): def init(): #重置遊戲棋盤 game_field.reset() return 'Game' def not_game(state): #畫出GameOver或者Win的介面 game_field.draw(stdsrc) #讀取使用者輸入得到action,判斷是重啟遊戲還是結束遊戲 action = get_user_action(stdsrc) responses = defaultdict(lambda:state) #預設當前狀態,沒有行為就會在當前介面迴圈 responses['Restart'],responses['Exit'] = 'Init','Exit' #對應不同的行為轉換到不同的狀態 return responses[action] def game(): ##畫出當前棋盤狀態 game_field.draw(stdsrc) #Getthe action action = get_user_action(stdsrc) if action == 'Restart': return 'Init' if action == 'Exit': return 'Exit' if game_field.move(action): if game_field.is_win(): return 'Win' if game_field.is_gameover(): return 'GameOver' return 'Game' state_actions={ 'Init': init, 'Win': lambda: not_game('Win'), 'Gameover': lambda:not_game('Gameover'), 'Game': game } curses.use_default_colors() ##Color #設定終結狀態最大數值為32 game_field = GameField(win=32) state='Init' #狀態機開始迴圈 while state != 'Exit': state = state_actions[state]() curses.wrapper(main) ##Once the callable returns, wrapper() will restore the original state of the terminal.

##執行結果

SCORE: 0
+------+------+------+------+
|      |      |      |      |
+------+------+------+------+
|      |  2   |      |      |
+------+------+------+------+
|      |      |      |  4   |
+------+------+------+------+
|      |      |      |      |
+------+------+------+------+
(W)Up (S)Down (A)Left (D)Right
      (R)Restart (Q)Exit

一路上遇到的問題:

  1. Redirection is not supported.    >>>>把pycharm改成cmd來執行
  2. import curses的問題

懶,決定在這裡也講述如何在Windows上安裝curses。 Curses庫在Windows下沒有直接的安裝的,有大神搞了在windows下的wheel版。

  •  檢視自己的pip支援什麼格式內容

E:\MyDownloads\Download>python
Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pip
>>> print(pip.pep425tags.get_supported())
[('cp36', 'cp36m', 'win_amd64'), ('cp36', 'none', 'win_amd64'), ('py3', 'none', 'win_amd64'), ('cp36', 'none', 'any'), ('cp3', 'non
e', 'any'), ('py36', 'none', 'any'), ('py3', 'none', 'any'), ('py35', 'none', 'any'), ('py34', 'none', 'any'), ('py33', 'none', 'an
y'), ('py32', 'none', 'any'), ('py31', 'none', 'any'), ('py30', 'none', 'any')]

>>> ^Z

  • 從以下網站中download wheel檔案。

從上面可以得知, 我的pip支援的是cp36的。於是從以下網址下載cp36的wheel

https://www.lfd.uci.edu/~gohlke/pythonlibs/#curses

  • 一鍵安裝  
E:\MyDownloads\Download>python -m pip install Scripts/curses-2.2-cp36-cp36m-win_amd64.whl
Processing e:\mydownloads\download\scripts\curses-2.2-cp36-cp36m-win_amd64.whl
Installing collected packages: curses

Successfully installed curses-2.2

以後目標:

1. 改變顏色跟邊框曲線2. 把數字改變為朝代。相同朝代碰撞能變為下一個朝代。

相關推薦

[Python3] 2048遊戲

程式碼來源:https://www.shiyanlou.com/courses/368/labs/1172/document小白,最近看到實驗樓的2048的小遊戲,在程式碼上帶了自己的註釋。前期準備:有限狀態機      ##https://www.cnblogs.com/2

2048遊戲Python3.6.5實現

這個2048遊戲是我自學python以後寫的, 用了幾天時間。 其中的某些方法可能寫的很笨, 也可能還存在各種BUG, 歡迎各位評論指出。 下面貼出完整程式碼供大家學習交流。 import random #遊戲分數 gameScore = 0 #遊戲矩陣 matrix

2048遊戲主要算法實現

mes 方向 時間限制 上下左右 print ron weight color ges http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4681 4681: 2

【python學習】使用python寫一個2048遊戲

ast stc 遊戲 多少 wan nbsp 小遊戲 效果 參考 個人博客:jerwang.cn 沒有參考其他代碼,效果圖: 話不多少,源代碼: https://github.com/jerustc/Python/blob/master/2048.py【python學

用原生js寫2048遊戲

gin 小遊戲 替換 上下 數位 免費學習 title index.php parseint <!DOCTYPE html> <html> <head> <title> 2048-game </title&g

2048遊戲】——CSS/原生js爬坑之純CSS模態對話框&遊戲結束

函數 一半 窗口 內容 href 標準 tex true 存儲空間 引言:2048小遊戲的結束界面,使用純CSS制作模態對話框,一般做模態對話框都會使用BootStrap自帶的模態對話框組件方便使用,但在制作要運行在移動端的小項目時,就不能使用BootStrap,因為文件太

Qt 制作2048遊戲

inf mes yellow mar point spl head switch 空格 相信大家都玩過2048把,下面是我用qt寫得2048小遊戲。 2048.pro HEADERS += Widget.h SOURCES += Widget.cpp

C語言實現簡易2048遊戲

blog 而在 而是 null 移動 是我 我們 空指針 主體 一直很喜歡玩這個小遊戲,簡單的遊戲中包含運氣與思考與策略,喜歡這種簡約又不失內涵的遊戲風格。於是萌生了用C語言實現一下的想法。 具體代碼是模仿這個:https://www.cnblogs.com/judgeyo

“實驗樓"中的2048遊戲復現

#-*- coding:utf-8 -*- import curses from random import randrange,choice from collections import defaultdict #所有的有效輸入轉換為“上下左右,重置,退出”這六種行為,用actions表

【總結篇】js編寫的2048遊戲開發(上:思路)

2048是大家都熟悉的一款魔性小遊戲,其操作簡單,卻極其有效地殺時間。本篇將詳細講解如何構建這款小遊戲的開發思路、如何根據玩法進一步分析設計程式設計結構,適合有一定html、css、js、jquery語言基礎的讀者閱讀。 一.遊戲試玩       遊戲玩法大家都很

[原始碼和文件分享]基於組合語言的MVC思想架構2048遊戲

一 需求分析 在Win32環境下,使用MVC思想架構,同時應用多檔案多模組的軟體設計實踐,以MASM6.15為主要彙編工具,Sublime Text 3為程式碼編寫工具,綜合利用多種彙編命令語句,進行2048遊戲設計開發。 二 技術路線 2.1 系統架構 程式分為一個主模組和三個子模

C語言寫的2048遊戲

基於"基於C_語言的2048演算法設計_顏冠鵬.pdf" 這一篇文獻提供的思路 在中國知網上能找到 就不貼具體內容了 [摘 要] 針對2048的遊戲規則,分析了該遊戲的演算法特點,對其相關的功能需求和演算法設計進行了簡單介紹,提出了一種 新的設計方案。解決了該設計在方陣資料結構、運動演算法和遊戲結束判斷方面的

C語言實現最簡單的2048遊戲

網上解釋很多了,直接上程式碼吧,這個功能很簡單,易於學習,後期有時間會完善功能 #include<stdio.h> #include<stdlib.h> #include<string.h> #define Key_Up 0x4800

C語言介面實現2048遊戲

這是我在大一第二學期(兩年前)為了參加比賽,自學後寫的一個Dome,拿出來和大家分享一下,程式碼為兩年前的程式碼,未改動,優化以及各式可能很一般,請見諒。 #include "stdio.h" #include "stdlib.h" #include "time.h" #d

[原始碼和文件分享]基於Python的PyGame庫實現的2048遊戲

一、簡介 2048的遊戲規則很簡單,每次可以選擇上下左右其中一個方向去滑動,每滑動一次,所有的數字方塊都會往滑動的方向靠攏外,系統也會在空白的地方亂數出現一個數字方塊,相同數字的方塊在靠攏、相撞時會相加。系統給予的數字方塊不是2就是4,玩家要想辦法在這小小的16格範圍中湊出“2048”這個數字方

JQuery初體驗-JavaScript實現2048遊戲PC端

目錄 效果圖 遊戲頁面 遊戲頁面樣式 遊戲基礎邏輯 遊戲動畫邏輯 遊戲主邏輯 遊戲互動邏輯 效果圖: 遊戲頁面: <!DOCTYPE html> <html lang="en"> <head> <

如何用Axure製作2048遊戲

2048這款遊戲肯定很多人都玩過吧,2048屬於一款數字遊戲。如果要自己設計2048該如何實現呢?我們都知道,Axure(http://www.axurechina.cc/)是一款強大的原型設計工具 ,所以,今天想給大家分享一下關於用Axure製作2048遊戲的教程,如果感興趣,可以閱讀接下

C++實現2048遊戲(控制檯版的)

無聊,在公司寫了個2048小遊戲的程式,聊以自娛。(事實是我手機壞了,沒得玩)。 很簡單,直接上程式碼了。 #include <iostream> #include <windows.h> #include <ctime> using

lua實現一個2048遊戲

用lua寫了個在consle上執行的2048,這裡簡單說下是如何實現的。(原始碼地址:http://download.csdn.net/detail/c_boy_lu/9393255) 1.實現一

c語言課程結束專案:2048遊戲

《C語言程式設計基礎》學習完畢,完成第一個專案:2048小遊戲。 //思考:程式設計時,要先想整個框架還是先想每個函式的演算法。 //思考:每一個函式要不要傳引數(即陣列) //思考:每一個函式之間的聯絡是什麼,誰呼叫誰…這裡很容易搞得頭暈,越想越覺得複雜,便不想完成專案了。 &nb