記得剛上大學還不會編程的時候就開始YY自己什麼時候寫個貪吃蛇、掃雷的小遊戲出來就好。如今acm競賽已經結束,自己終於有些空餘時間了。處於項目需要,最近又開始學習MFC,於是昨天花了一天時間寫了個簡陋的貪吃蛇遊戲。
由於剛學MFC,也沒有借鑑別人程序,剛開始還弄出很多錯誤,不過好歹自己最終都把這些bug搞定了。
自己目前也只是菜鳥,此篇文章更多只是爲了一個記錄,有興趣的人可以看看。
不過這裏想說一點用新出的IDE學習編程語言還真是麻煩。
比如說寫這個貪吃蛇,爲了程序的方便,所以想把客戶區的大小固定下來,網上找的方法都是說在
CMainFrame::PreCreateWindow(CREATESTRUCT& cs)這個函數裏面 設定cs 的cx和xy值,以達到設定窗口大小的效果,但是在vs2010裏面卻會出現意想不到的效果,想知道什麼效果的話,可以自己去試試。而且設定窗口大小並不是客戶區大小,要想使客戶區大小爲500*500的話,還得進行處理。
網上沒找到自己想要的解決辦法,於自己只好想了一個折衷的辦法,在自己的app類裏面加一個CRect rect;
然後利用 在CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
將需要的客戶區大小存儲在theApp.rect中,然後作爲參數傳遞給AdjustWindowRectEx,函數就會將所需要的窗口大小傳遞給theApp.rect
然後再 ShowWindow和UpdateWindow函數之前調用SetWindowPos來設定窗口大小
就能達到把客戶區大小設定爲560*560的效果了。
好像視圖文檔體系的特點就是,view類負責顯示,document類負責數據處理和存儲(呵呵,反正我是這麼理解的)
於是我把數據結構都放在了
document類裏面
在document類中加入
deque<CPoint> dq;
bool flag[70][70];
CPoint special;
int direction;
爲了方便,都設置爲public屬性
因爲簡單貪吃蛇是由一個個帶顏色的小方塊組成的,我設定的客戶區的大小爲560*560,將小方塊的邊長定爲8*8,於是整個客戶區可以看作一個70*70個小方塊。
雙端隊列用來存儲組成貪吃蛇的方塊的座標。
用雙端隊列的好處:
正常移動時,每一步的移動可以看作是尾部方塊消失,和頭部方塊沿着移動方向增加一個方塊,所以我們只用處理頭部和尾部就行,遇到需要增加的方塊也只用在頭部增加一個方塊就可以。所以雙端隊列用在這裏非常適用。
direction用來記錄蛇移動的方向,special用來記錄食物(就是隨機出現的哪個方塊),flag[][]則是用來記錄某方塊是不是蛇本身(true表示是,false爲不是)。
剩下的兩個問題就是隨機出現方塊的問題和定時器的問題了
隨機出現方塊比較簡單,就是用隨機數就行,將隨機對應到座標稍微處理一下就行了。
定時器的問題我糾結了好久,主要是MFC視圖文檔體系的問題,定時器的setTimer函數顯然是應該放在view類當中的,但是應該什麼時候調用網上的答案很多都不適用。
正常來說應該是在view類的OnCreate函數中調用,將view設定爲處理WM_CREATE 消息就行了,記得最後還要加上處理WM_CLOSE消息,在其中調用killTimer,釋放定時器。
不過這次爲了自己編程方便,我在OnPaint函數中調用的setTimer函數
還有一點是OnChar函數處理不了方向鍵消息,應該在OnKeyDown函數中處理。
因爲MFC的代碼太雜亂,這裏就不貼整個代碼了,主要貼一些View類的消息函數吧,也是主要的代碼了: