如何開(kāi)發(fā)一個(gè)蘋果手機(jī)App:俄羅斯方塊游戲

俄羅斯方塊游戲紊遵,是風(fēng)靡世界幾十年的經(jīng)典游戲,相信絕大多數(shù)人都玩過(guò)這個(gè)游戲汞贸,那么它是怎樣編寫出來(lái)的绳军,我們?nèi)绾尾拍茏约壕帉懸粋€(gè)這樣的游戲呢?

游戲開(kāi)發(fā)步驟

要編寫一個(gè)游戲矢腻,基本按照以下一些步驟進(jìn)行:

1.游戲規(guī)則定義

游戲規(guī)則決定了這個(gè)游戲怎么玩,好不好玩,也就決定了編寫程序?qū)崿F(xiàn)的目標(biāo)顷蟆。不同的需求導(dǎo)致不同的規(guī)則,不同的規(guī)則就需要不同的方法去實(shí)現(xiàn)帐偎。

例如蛔屹,俄羅斯方塊是由哪些類型方塊組成,棋盤布局是9*18還是10*20漫贞,是否允許旋轉(zhuǎn),消掉一行獲得的分?jǐn)?shù)和獲得多行獲得的分?jǐn)?shù)如何進(jìn)行累加豪嗽,等等隐锭。

2.選擇游戲運(yùn)行平臺(tái)和界面設(shè)計(jì)

在很多種平臺(tái)上都可以玩游戲钦睡,常見(jiàn)的比如電腦pc或者筆記本上面直接運(yùn)行游戲exe程序刘绣,或者在電腦瀏覽器中運(yùn)行flash游戲纬凤,或者手機(jī)上運(yùn)行游戲App停士,或者在特殊游戲機(jī)比如xbox等上直接運(yùn)行游戲程序,或者在VR設(shè)備上運(yùn)行游戲程序蜻底。

不同的平臺(tái)薄辅,需要不同的實(shí)現(xiàn)方式站楚,也就需要用不同的程序或開(kāi)發(fā)語(yǔ)言開(kāi)發(fā)工具來(lái)實(shí)現(xiàn)。

例如旧乞,在網(wǎng)頁(yè)上開(kāi)發(fā)游戲良蛮,可以用html+css+js實(shí)現(xiàn)货徙,也可以用flash實(shí)現(xiàn);在手機(jī)上開(kāi)發(fā)游戲蠢棱,可以用java語(yǔ)言在android系統(tǒng)中實(shí)現(xiàn),也可以用objective-c在ios系統(tǒng)上實(shí)現(xiàn)玉转;在電腦pc機(jī)上可以用c語(yǔ)言在windows系統(tǒng)中實(shí)現(xiàn)。

界面設(shè)計(jì)就是根據(jù)游戲規(guī)則決定人機(jī)交互界面刺下,決定了輸入和輸出的方式。

例如捺癞,俄羅斯方塊可以設(shè)計(jì)成左邊是棋盤惕鼓,右側(cè)上面是分?jǐn)?shù)矾飞,下一個(gè)方塊洒沦,還可以放一個(gè)重新來(lái)一句按鈕瞒津,或者暫停按鈕等等。

方塊設(shè)計(jì)成純一種顏色塊屁柏,還是多種顏色塊,或者是方的還是圓的裸删,或者是卡通圖案,這些就是界面設(shè)計(jì)伤塌。

3.考慮編程思路和算法設(shè)計(jì)

如果決定了在哪種平臺(tái)以及用何種開(kāi)發(fā)語(yǔ)言來(lái)編程實(shí)現(xiàn)游戲,則要考慮編程的思路药薯,數(shù)據(jù)的存儲(chǔ),以及具體的算法穷娱。

例如,俄羅斯方塊根據(jù)棋盤大小是用二維數(shù)組來(lái)實(shí)現(xiàn),還是用一維數(shù)組來(lái)實(shí)現(xiàn)羞秤,還是用字典表來(lái)實(shí)現(xiàn)

一局游戲是定時(shí)計(jì)算嗦董,還是用一個(gè)循環(huán)來(lái)處理

如何保存下一個(gè)類型京革,如何計(jì)算分?jǐn)?shù),如何判斷一個(gè)方塊是否落地不能再移動(dòng),如何判斷一行是否已經(jīng)被填滿坡垫,如何判斷游戲已經(jīng)結(jié)束

4.按照前面設(shè)計(jì)的思路編寫代碼實(shí)現(xiàn)

考慮好編程思路和算法設(shè)計(jì)之后,可以按照設(shè)想進(jìn)行實(shí)際的編程開(kāi)發(fā)

不停的驗(yàn)證思路溉卓,通過(guò)開(kāi)發(fā)中的實(shí)際情況,可能對(duì)編程思路進(jìn)行修改調(diào)整,直到完成整個(gè)游戲功能

代碼就是一行一行的編寫出來(lái)代赁,直到成為一個(gè)可以運(yùn)行的游戲程序

5.游戲測(cè)試

測(cè)試就是把自己當(dāng)成實(shí)際用戶來(lái)運(yùn)行游戲程序徒役,找到游戲可能存在的問(wèn)題杉女,避免程序沒(méi)有按照預(yù)期執(zhí)行速勇,防止程序崩潰死機(jī)等情況,驗(yàn)證游戲確實(shí)按照游戲規(guī)則能完整可靠的運(yùn)行都伪,這個(gè)開(kāi)發(fā)人員可以找其他人進(jìn)行測(cè)試,防止自己存在思維盲區(qū)先誉。

6.游戲發(fā)布

游戲測(cè)試完成之后,就可以將游戲發(fā)布到相應(yīng)的渠道或者平臺(tái),讓更多的人可以玩到這個(gè)游戲杨帽。

例如,蘋果手機(jī)App可以發(fā)布到蘋果的AppStore,安卓手機(jī)App可以發(fā)布到各大應(yīng)用市場(chǎng)胧砰。

最簡(jiǎn)單的發(fā)布就是直接發(fā)送給自己的朋友,讓他們大吃一驚贪薪。

游戲規(guī)則定義

俄羅斯方塊游戲有如下規(guī)則:

棋盤由寬度為10格高度為20格的方塊組成

方塊共有7種形態(tài):

長(zhǎng)條形1個(gè),正方形1個(gè),T型1個(gè)庞萍,L型2個(gè),S型2個(gè)

方塊出現(xiàn)在最上方正中間私恬,同時(shí)知道下一個(gè)方塊是什么

方塊往下掉落,每隔1秒下落一行

方塊下落中如果碰到有方塊阻擋不能下落則停止下落

方塊停止下落后,判斷是否有整行都被方塊填滿涮瞻,如果有,則整行消失,上面的全部行整體下落一行

統(tǒng)計(jì)消掉的總行數(shù)

方塊在下落過(guò)程中慕匠,可以按向下方向鍵讓方塊直接掉落到直到停止位置

可以按向左或者向右方向鍵讓方塊進(jìn)行旋轉(zhuǎn)青伤,每按鍵一次旋轉(zhuǎn)90度

如果沒(méi)有足夠的空間讓方塊落下則游戲結(jié)束

游戲運(yùn)行平臺(tái)和界面設(shè)計(jì)

如果以最流行的蘋果手機(jī)作為游戲運(yùn)行環(huán)境狠角,則需要開(kāi)發(fā)一個(gè)蘋果手機(jī)App

蘋果手機(jī)使用的是iOS操作系統(tǒng),開(kāi)發(fā)環(huán)境需要Mac電腦和開(kāi)發(fā)工具軟件Xcode

開(kāi)發(fā)語(yǔ)言可以使用objective-C,開(kāi)發(fā)游戲可以使開(kāi)發(fā)用工具包c(diǎn)ocos2d

如果需要發(fā)布到蘋果AppStore晓勇,則需要一個(gè)開(kāi)發(fā)者賬號(hào),以及一年99美金

界面設(shè)計(jì):

程序啟動(dòng)之后進(jìn)入主界面,只能豎屏顯示游戲

主界面分為左右部分

左邊為棋盤:顯示整個(gè)棋盤,正方形的格子組成年叮,寬10格高20格

按照蘋果手機(jī)尺寸320點(diǎn)*480點(diǎn)來(lái)設(shè)計(jì),20格高度為480點(diǎn),則寬度10格占用240點(diǎn)

因此左邊棋盤占用240點(diǎn)辈挂,右側(cè)剩余80點(diǎn)

右邊分為上部和下部

上部為狀態(tài)欄靠上顯示:最上方顯示顯示當(dāng)前消掉的行數(shù),下面顯示方塊類型小圖標(biāo)

下部為按鈕欄靠下顯示:從上往下顯示3個(gè)按鈕噪叙,排行榜/關(guān)于/重新開(kāi)始

大概的界面設(shè)計(jì)如下示意圖:


界面運(yùn)行邏輯:

點(diǎn)擊排行榜按鈕進(jìn)入一個(gè)新頁(yè)面债朵,上面顯示消掉的行數(shù)最多的8個(gè)行數(shù)數(shù)字臭杰,下面是一個(gè)返回按鈕

點(diǎn)擊關(guān)于按鈕進(jìn)入一個(gè)新頁(yè)面,上面顯示一張說(shuō)明圖片,下面是一個(gè)返回按鈕

點(diǎn)擊重新開(kāi)始按鈕点寥,將當(dāng)前棋盤清空并重新開(kāi)始一局游戲,游戲啟動(dòng)

游戲啟動(dòng)之后,第一個(gè)方塊從最上面中間開(kāi)始往下掉落,每秒下落一行

同時(shí)迫肖,上方的狀態(tài)欄,顯示下一個(gè)即將出現(xiàn)的方塊類型小圖標(biāo)

方塊下落過(guò)程中诬垂,在屏幕上單指左滑可以向左逆時(shí)針旋轉(zhuǎn)當(dāng)前方塊,或者在屏幕上單指右滑可以向右順時(shí)針旋轉(zhuǎn)當(dāng)前方塊

還可以在屏幕上單指下滑可以讓當(dāng)前方塊直接掉落到底部

方塊如果不能再往下移動(dòng)一行的時(shí)候,則方塊停止,同時(shí)開(kāi)始判斷是否能夠消掉某些行

如果能夠消掉某些行,則統(tǒng)計(jì)消掉的行數(shù),增加到上方狀態(tài)欄顯示消掉的數(shù)字上派草,刷新顯示

消掉的行從屏幕上消除簸州,同時(shí)上方的所有行往下整體移動(dòng)

加入棋盤最上方中間的供方塊出現(xiàn)的地方已經(jīng)被方塊占住了搏存,則認(rèn)為這一局游戲結(jié)束

游戲結(jié)束則彈出一個(gè)窗口顯示游戲結(jié)束信息,顯示總共消掉了多少行,然后將該記錄保存到數(shù)據(jù)庫(kù)中

彈出窗口上有返回按鈕泰演,點(diǎn)擊返回按鈕,彈出窗口關(guān)閉猾普,回到游戲主界面乌助,主界面停止游戲掖肋,點(diǎn)擊重新開(kāi)始按鈕開(kāi)始新一局

編程思路和算法設(shè)計(jì)

數(shù)據(jù)存儲(chǔ):

考慮用二維列表來(lái)存儲(chǔ)棋盤上的每一個(gè)格子

[[0,0,0,0,0,0,0,0,0,0],

[0,0,0,0,0,0,0,0,0,0],

......

[0,0,0,0,0,0,0,0,0,0]]

二維列表里面赏参,第一層是放總計(jì)20行志笼,第二層里面是放每一行的10個(gè)格子

如果格子里面有方塊,則存放數(shù)字1把篓,如果沒(méi)有方塊則存放數(shù)字0

判斷一行如果全部是1敬惦,則表示該行填滿了方格葵姥,需要消掉

使用下列數(shù)字來(lái)對(duì)7種方塊進(jìn)行區(qū)分旭等,存儲(chǔ)2個(gè)變量,當(dāng)前方塊和下一個(gè)方塊

1:長(zhǎng)條形 2:正方形 3:T型 4:L型向左 5:L型向右 6:S型左上右下 7:S型右上左下

生成下一個(gè)方塊則使用隨機(jī)函數(shù)生成1到7當(dāng)中的隨機(jī)數(shù)

然后不同方塊如果進(jìn)行了旋轉(zhuǎn)會(huì)出現(xiàn)不同的狀態(tài)疗锐,定義旋轉(zhuǎn)狀態(tài)如下:

11:豎立長(zhǎng)條 12:橫排長(zhǎng)條

21:正方形

31:T型尖頭朝下 32:T型尖頭朝左 33:T型尖頭朝上 34:T型尖頭朝右

41:L型短頭向左長(zhǎng)頭向上 42:L型短頭向上長(zhǎng)頭向右 43:L型短頭向右長(zhǎng)頭向下 44:L型短頭向下長(zhǎng)頭向左

51:L型短頭向右長(zhǎng)頭向上 52:L型短頭向下長(zhǎng)頭向右 53:L型短頭向左長(zhǎng)頭向下 54:L型短頭向上長(zhǎng)頭向左

61:S型左上右下豎立 62:S型左上右下橫排

71:S型右上左下豎立 72:S型右上左下橫排

使用2個(gè)變量x,y存儲(chǔ)當(dāng)前方塊的左上角的方塊的行號(hào)和列號(hào)

使用變量存儲(chǔ)當(dāng)前已經(jīng)消除的行數(shù)

算法設(shè)計(jì):

點(diǎn)擊重新開(kāi)始按鈕后郎楼,主程序啟動(dòng)

清空整個(gè)棋盤,對(duì)二維列表全部數(shù)字清零

然后生成第1個(gè)隨機(jī)數(shù)窒悔,賦值給當(dāng)前方塊變量

然后生成第2個(gè)隨機(jī)數(shù)呜袁,賦值給下一個(gè)方塊變量

刷新顯示頁(yè)面

進(jìn)入定時(shí)處理函數(shù),定時(shí)間隔時(shí)間為1秒:

定時(shí)處理函數(shù):

判斷當(dāng)前方塊如果可以往下移動(dòng)简珠,則向下移動(dòng)阶界,修改二維列表變量

如果不可以下移了,則判斷是否可以消除某行聋庵,如果消除了某行則上方的所有行的值整體下移一行

如果不可以下移也不可以消除了膘融,則將下一個(gè)方塊的數(shù)值賦值給當(dāng)前方塊,隨機(jī)數(shù)生成下一個(gè)方塊

然后判斷當(dāng)前方塊是否可以放入棋盤最上方的中間位置祭玉,如果可以放入則修改二維列表變量氧映,如果不能放入,則游戲結(jié)束

判斷當(dāng)前方塊是否可以下移函數(shù):

根據(jù)當(dāng)前方塊類型變量脱货,以及方塊當(dāng)前旋轉(zhuǎn)狀態(tài)岛都,結(jié)合二維列表變量判斷律姨,舉例:

如果是11豎立長(zhǎng)條形,則根據(jù)當(dāng)前方塊左上角的行號(hào)和列號(hào)臼疫,可以知道最下方的坐標(biāo)位置

比如x=0行,y=5列择份,則最下方的坐標(biāo)為(3,5)烫堤,那么只要看二維列表的(4荣赶,5)如果為1則不可下移,否則可以下移

比如如果是31:T型尖頭朝下

x=0,y=4鸽斟,那么下方可能有3個(gè)方塊可能碰到阻礙拔创,分別是(0,4)/(1富蓄,5)/(0伏蚊,6)

那么只要看二維列表的(1,4)/(2格粪,5)/(1,6)只要有一個(gè)為1則不可下移氛改,否則可以下移

判斷是否可以消除某行函數(shù):

對(duì)二維列表進(jìn)行循環(huán)帐萎,如果一行當(dāng)中的所有值都為1,則可以消除

直接將所有上面的行的值往下復(fù)制胜卤,最上面一行的值全部賦值為0疆导,同時(shí)總的消除行數(shù)變量加1

判斷當(dāng)前方塊是否可以放入棋盤最上方的中間位置函數(shù):

根據(jù)當(dāng)前方塊類型變量,以及方塊當(dāng)前旋轉(zhuǎn)狀態(tài)葛躏,結(jié)合二維列表變量判斷澈段,舉例:

如果是1長(zhǎng)條形,默認(rèn)為11樹(shù)立長(zhǎng)條形

則需要判斷(0舰攒,5)/(1败富,5)/(2,5)/(3摩窃,5)這4個(gè)坐標(biāo)在二維列表中是否為1兽叮,只要有1個(gè)位置為1則不可放入

比如如果是3T型尖頭朝下

則需要判斷(0,4)/(0猾愿,5)/(0鹦聪,6)/(1,5)這4個(gè)坐標(biāo)

旋轉(zhuǎn)處理:

總共允許有3種滑動(dòng)手指操作蒂秘,向下/向左/向右

向下滑動(dòng)手指泽本,表示將當(dāng)前方塊直接掉落到最下方直到碰到阻礙停住

向左滑動(dòng)手指,表示將當(dāng)前方塊進(jìn)行逆時(shí)針旋轉(zhuǎn)

向右滑動(dòng)手指姻僧,表示將當(dāng)前方塊進(jìn)行順時(shí)針旋轉(zhuǎn)

向下掉落處理:

重復(fù)調(diào)用前面定義的判斷當(dāng)前方塊是否可以下移函數(shù)

從第一行循環(huán)到最后一行坐標(biāo)规丽,即可得出最多可以掉落到哪一行

逆時(shí)針旋轉(zhuǎn)處理:

根據(jù)當(dāng)前方塊類型變量蒲牧,以及方塊當(dāng)前旋轉(zhuǎn)狀態(tài),結(jié)合二維列表變量判斷嘁捷,舉例:

如果是11豎立長(zhǎng)條形造成,旋轉(zhuǎn)中心點(diǎn)取從上往下第2個(gè)方塊

那么根據(jù)旋轉(zhuǎn)后需要占用的位置,需要判斷(1雄嚣,4)/(1晒屎,6)/(1,7)這3個(gè)位置在二維列表中的值必須是0才可以旋轉(zhuǎn)

旋轉(zhuǎn)完成后應(yīng)該左上角坐標(biāo)應(yīng)該從(0缓升,5)變成(1鼓鲁,4),方塊當(dāng)前旋轉(zhuǎn)狀態(tài)從11變成12

請(qǐng)看下面的示意圖:


那么港谊,順時(shí)針旋轉(zhuǎn)和這個(gè)類似骇吭,只是選擇后的左上角左邊變量變化,以及方塊當(dāng)前旋轉(zhuǎn)狀態(tài)值變化

具體代碼實(shí)現(xiàn)

由于篇幅所限歧寺,這里只能大概描述核心的一些代碼實(shí)現(xiàn)方式

開(kāi)發(fā)準(zhǔn)備:

首先取注冊(cè)一個(gè)AppleID

然后在Mac電腦上安裝好Xcode開(kāi)發(fā)軟件

引入相關(guān)工具開(kāi)發(fā)包:

導(dǎo)入cocos2d開(kāi)發(fā)工具包以及需要的一些系統(tǒng)Frameworks

數(shù)據(jù)操作類:

AllData.h

#define SIZE 24

#define WIDTH 320

#define HEIGHT 480

@interface AllData : NSObject

@property int next;

@property int current;

@property int currentstatus;

@property int posx;

@property int posy;

@property int alllines;

@property (nonatomic,retain) NSMutableArray *numberdatas;

//取得當(dāng)前類的實(shí)例

+(AllData *) sharedAllData;

//初始化棋盤

-(void)initAllData;

//取得下一個(gè)方塊

-(int) getNextValue;

//逆時(shí)針旋轉(zhuǎn)當(dāng)前方塊

-(void)changeLeft;

//順時(shí)針旋轉(zhuǎn)當(dāng)前方塊

-(void)changeRight;

//判斷是否可以下移當(dāng)前方塊

-(boolean)canMoveDown;

//處理消除慢行操作

-(void)removeLines;

@end

存儲(chǔ)控制類:

DBUtil.h

@interface DBUtil : NSObject

+ (NSString *)dataFilePath;

+ (void)initDataBase;

//存儲(chǔ)一局游戲消除行數(shù)數(shù)字

+(void)insertOneData:(int)topnumber;

//取得最大的8個(gè)記錄數(shù):消除行數(shù)

+ (NSMutableArray *)getListDataFromDb;

@end

方塊繪畫類:

#import "CommonUtil.h"

#import "AllData.h"

@implementation CommonUtil

//繪畫棋盤當(dāng)中的一個(gè)格子

+ (void) drawOneNumber:(int)number pos:(CGPoint)pos layer:(CCLayer*)layer {

CCSpriteBatchNode *numbatch = [CCSpriteBatchNode batchNodeWithFile:[NSString stringWithFormat:@"num_%d.png",number] capacity:15];

numbatch.anchorPoint = CGPointZero;

[numbatch setPosition:pos];

[layer addChild:numbatch];

CCSprite *sprite1 = [CCSprite spriteWithTexture:numbatch.texture rect:CGRectMake(0, 0, SIZE-2, SIZE-2)];

sprite1.position = ccp(0,0);

sprite1.anchorPoint = CGPointZero;

[numbatch addChild:sprite1];

}

// 繪畫整個(gè)棋盤

......

啟動(dòng)進(jìn)入主界面:

@implementation AppDelegate

- (void) applicationDidFinishLaunching:(UIApplication*)application

{

......

[[AllData sharedAllData] initAllData];

[DBUtil initDataBase];

[[CCDirector sharedDirector] runWithScene: [MainLayer scene]];

.......

狀態(tài)欄和工具欄:

@interface ToolLayer : CCLayer {

}

@implementation ToolLayer

- (void) drawTool {

[self removeAllChildrenWithCleanup:YES];

//畫底部背景

CCSprite *bg = [CCSprite spriteWithFile:@"tool_bootom_back.png"];

bg.anchorPoint = CGPointZero;

[self addChild:bg z:0 tag:0];

//排行按鈕

CCMenuItem *gold = [CCMenuItemImage itemFromNormalImage:@"gold.png" selectedImage:@"gold_pressed.png" target:self selector:@selector(gold:)];

//關(guān)于按鈕

CCMenuItem *about = [CCMenuItemImage itemFromNormalImage:@"about.png" selectedImage:@"about_pressed.png" target:self selector:@selector(about:)];

//重新開(kāi)始按鈕

CCMenuItem *restart = [CCMenuItemImage itemFromNormalImage:@"restart.png" selectedImage:@"restart_pressed.png" target:self selector:@selector(restart:)];

......

// 繪畫消除行數(shù)的圖標(biāo)

// 繪畫消除行數(shù)的數(shù)字

// 繪畫下一個(gè)方塊的圖標(biāo)

- (void) restart:(id) sender

{

[[AllData sharedAllData] initAllData];

MapLayer *mapLayer = (MapLayer *)[[CCDirector sharedDirector].runningScene getChildByTag:0];

[mapLayer startGame];

[self drawTool];

}

棋盤滑動(dòng)手勢(shì)控制方法:

- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

NSSet *allTouches = [event allTouches];

switch ([allTouches count])

{

case 1:

{

UITouch *touch1 = [[allTouches allObjects] objectAtIndex:0];

single = [touch1 locationInView:[touch1 view]];

} break;

default:

break;

}

}

- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

NSSet *allTouches = [event allTouches];

switch ([allTouches count])

{

case 1:

{

UITouch *touch1 = [[allTouches allObjects] objectAtIndex:0];

CGPoint singleend = [touch1 locationInView:[touch1 view]];

float x = single.x - singleend.x;

float y = single.y - singleend.y;

if (x*x > y*y && x*x > 2500 && x > 0) {

//向左橫向滑動(dòng)超過(guò)50

NSLog(@"左");

[self changeLeft];

}else if (x*x > y*y && x*x > 2500 && x < 0) {

//向右橫向滑動(dòng)超過(guò)50

NSLog(@"右");

[self changeRight];

}else if (x*x < y*y && y*y > 2500 && y < 0) {

//向下縱向滑動(dòng)超過(guò)50

NSLog(@"下");

[self moveDown];

}

} break;

default:

break;

}

}

主界面程序:

@interface MapLayer : CCLayer {

}

@implementation MapLayer

-(void) startGame{

[self removeAllChildrenWithCleanup:YES];

int toppos = 0;

for (NSMutableArray *onerow in [AllData sharedAllData].numberdatas) {

int leftpos = 0;

toppos = toppos + SIZE + 1;

for (NSNumber *onepos in onerow) {

leftpos = leftpos + SIZE + 1;

[CommonUtil drawOneNumber:[onepos intValue] pos:CGPointMake(leftpos, toppos) layer:self];

}

}

// 設(shè)置定時(shí)器處理函數(shù)燥狰,定時(shí)間隔時(shí)間1秒

......

}

//定時(shí)器處理函數(shù)

//判斷當(dāng)前方塊如果可以往下移動(dòng),則向下移動(dòng)斜筐,修改二維列表變量

//如果不可以下移了龙致,則判斷是否可以消除某行,如果消除了某行則上方的所有行的值整體下移一行

//如果不可以下移也不可以消除了顷链,則將下一個(gè)方塊的數(shù)值賦值給當(dāng)前方塊目代,隨機(jī)數(shù)生成下一個(gè)方塊

//然后判斷當(dāng)前方塊是否可以放入棋盤最上方的中間位置,如果可以放入則修改二維列表變量嗤练,如果不能放入榛了,則游戲結(jié)束

......

具體代碼這里不貼了,有了詳細(xì)的算法程序設(shè)計(jì)和數(shù)據(jù)存儲(chǔ)類型煞抬,要實(shí)現(xiàn)出來(lái)并不是太難霜大,只是需要耐心細(xì)心而已。

游戲測(cè)試

游戲的主體程序完成后革答,就可以一邊測(cè)試一邊修改

測(cè)試的時(shí)候要注意測(cè)試各種邊界情況僧诚,例如

將當(dāng)前方塊移動(dòng)到最左邊,看看碰到邊界的時(shí)候會(huì)不會(huì)出錯(cuò)

將當(dāng)前方塊卡入一個(gè)正好插入的空槽形狀中蝗碎,看程序是不是會(huì)出錯(cuò)

等待當(dāng)前方塊掉入一個(gè)空槽湖笨,然后立刻旋轉(zhuǎn),理論上應(yīng)該不能旋轉(zhuǎn)了蹦骑,測(cè)試看看程序會(huì)不會(huì)出錯(cuò)

測(cè)試一次性消掉4行慈省,看看程序是不是會(huì)出錯(cuò)

如果自己測(cè)試的差不多了,就可以將程序打包發(fā)送給朋友測(cè)試

有時(shí)候,開(kāi)發(fā)的人很難測(cè)試自己編寫的程序边败,但是反而讓別人可以測(cè)試出來(lái)很多問(wèn)題

游戲發(fā)布

下面介紹一下大概的發(fā)布流程袱衷,讓大家有個(gè)初步印象,詳細(xì)的發(fā)布流程網(wǎng)上可以搜索到很多

游戲測(cè)試到基本沒(méi)有錯(cuò)誤之后笑窜,就可以將游戲發(fā)布到蘋果的AppStore了

發(fā)布App需要購(gòu)買蘋果的開(kāi)發(fā)者賬號(hào)致燥,一年是99美金,目前用信用卡支付也很方便

然后登陸https://developer.apple.com,進(jìn)行一些證書的設(shè)置

生成好證書之后排截,將證書下載到Mac電腦中導(dǎo)入到Xcode之中

然后使用Xcode進(jìn)行編譯和打包好一個(gè)ipa文件

然后登陸https://itunesconnect.apple.com創(chuàng)建一個(gè)App嫌蚤,填寫一些介紹信息,需要一些App的截圖

然后回到Xcode使用Application Loader這個(gè)工具軟件將ipa文件上傳到itunesconnect當(dāng)中

然后回到itunesconnect網(wǎng)站上提交App

然后就是等待蘋果AppStore的審核断傲,一般7-10個(gè)工作日可以完成審核

完成審核之后脱吱,你的App就會(huì)出現(xiàn)在蘋果手機(jī)的AppStore里面了,就可以搜索到了

然后就可以告訴你的朋友們认罩,讓他們大吃一驚吧箱蝠。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市垦垂,隨后出現(xiàn)的幾起案子宦搬,更是在濱河造成了極大的恐慌,老刑警劉巖劫拗,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件间校,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡杨幼,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門聂渊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)差购,“玉大人,你說(shuō)我怎么就攤上這事汉嗽∮樱” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵饼暑,是天一觀的道長(zhǎng)稳析。 經(jīng)常有香客問(wèn)我,道長(zhǎng)弓叛,這世上最難降的妖魔是什么彰居? 我笑而不...
    開(kāi)封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮撰筷,結(jié)果婚禮上陈惰,老公的妹妹穿的比我還像新娘。我一直安慰自己毕籽,他們只是感情好抬闯,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布井辆。 她就那樣靜靜地躺著,像睡著了一般溶握。 火紅的嫁衣襯著肌膚如雪杯缺。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天睡榆,我揣著相機(jī)與錄音萍肆,去河邊找鬼。 笑死肉微,一個(gè)胖子當(dāng)著我的面吹牛匾鸥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播碉纳,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼勿负,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了劳曹?” 一聲冷哼從身側(cè)響起奴愉,我...
    開(kāi)封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铁孵,沒(méi)想到半個(gè)月后锭硼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜕劝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年檀头,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岖沛。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡暑始,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出婴削,到底是詐尸還是另有隱情廊镜,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布唉俗,位于F島的核電站嗤朴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏虫溜。R本人自食惡果不足惜雹姊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望衡楞。 院中可真熱鬧容为,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至得滤,卻和暖如春陨献,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背懂更。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工眨业, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沮协。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓龄捡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親慷暂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子聘殖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 學(xué)習(xí)Java半年有余,總想做點(diǎn)什么出來(lái)行瑞,而不是只糾結(jié)與語(yǔ)法和各種類包不可自拔奸腺。 于是我想,何不搞一個(gè)小游戲出來(lái)血久。 ...
    TaXue_WWL閱讀 2,576評(píng)論 0 9
  • 思路: 首先要畫出游戲背景墻突照; 其次,要有方塊氧吐,以及方塊單元讹蘑; 方塊的不同形狀,顏色隨機(jī)產(chǎn)生筑舅; 游戲的控制面板座慰。 ...
    傲子閱讀 2,650評(píng)論 0 3
  • 先上個(gè)成品效果圖。 說(shuō)下思路: 前提: ·我們知道豁翎,canvas.drawRect(left, top, righ...
    廢柴大媽閱讀 1,408評(píng)論 0 2
  • [代碼運(yùn)行效果截圖] [c++]代碼庫(kù) /* */ #include #include #include #def...
    小辰帶你看世界閱讀 2,136評(píng)論 0 1
  • 國(guó)慶節(jié)假日有的回老家了角骤,有的出去玩兒了隅忿。而我就一個(gè)人在屋里呆著心剥,因?yàn)槲疑±病拈_(kāi)運(yùn)動(dòng)會(huì)我就開(kāi)始咳嗽背桐,昨...
    張余蔚閱讀 250評(píng)論 0 0