python入門python的基本語法
751
2025-04-01
1????????系統(tǒng)設(shè)計要求
1.1???需求分析
本系統(tǒng)為一個用C#實(shí)現(xiàn)的為我們所熟悉的簡單的俄羅斯方塊游戲,該系統(tǒng)的具體功能如下:
1).???????能簡便的開始游戲,游戲中的方塊的功能與日常我們所熟悉的游戲的功能一致,各種塊的設(shè)置也一致,包括塊的旋轉(zhuǎn),加速下降,平移,滿行消去,到頂游戲結(jié)束功能;
2).???????能夠自定義游戲中功能鍵的具體按鍵,顯示下一方塊提示信息,以及游戲數(shù)據(jù)的統(tǒng)計;
3).???????考慮需要解決的問題:怎么樣設(shè)置圖形顯示;怎樣獲取鍵盤輸入;怎樣控制方塊的移動;怎樣控制時間間隔(用于游戲中控制形狀的下落);游戲中的各種形狀及整個游戲空間怎么用數(shù)據(jù)表示;游戲中怎么判斷左右及向下移動的可能性;游戲中怎么判斷某一形狀旋轉(zhuǎn)的可能性;按向下方向鍵時加速某一形狀下落速度的處理;怎么判斷某一形狀已經(jīng)到底;怎么判斷某一已經(jīng)被填滿;怎么消去已經(jīng)被填滿的一行;怎么消去某一形狀落到底后能夠消去的所有的行;(如長條最多可以消去四行)怎樣判斷游戲結(jié)束,關(guān)于“下一個”形狀取法的問題。
2????????設(shè)計思路
2.1???用面向?qū)ο?/a>的方法分析系統(tǒng)
從游戲的基本玩法出發(fā),主要就是俄羅斯方塊的形狀和旋轉(zhuǎn),在設(shè)計中在一個圖片框中構(gòu)造了一個20*20(像素)的小塊,由這些小塊組合成新的形狀,每四個小塊連接在一起就可以構(gòu)造出一種造型,總共設(shè)計了7中造型,每種造型又可以通過旋轉(zhuǎn)而變化出2到4種形狀,在游戲窗體中用戶就可以使用鍵盤的方向鍵來控制方塊的運(yùn)動,然后對每一行進(jìn)行判斷,如果有某行的方塊是滿的,則消除這行的方塊,并且使上面的方塊自由下落,其中,方塊向下的速度是有時鐘控件控制的。俄羅斯方塊游戲設(shè)計主要包括以下10個方面:
1).?????????游戲界面的設(shè)計。
2).?????????俄羅斯方塊的實(shí)現(xiàn)。
3).?????????鍵盤輸入信息的獲取。
4).?????????俄羅斯方塊的移動(向左,向右和向下)。
5).?????????俄羅斯方塊的變換。
6).?????????方塊自動下落與速度的選擇。
7).?????????慢行的判斷與消行。
8).?????????游戲結(jié)束判斷。
9).?????????用戶配置保存。
在主窗口中,通過調(diào)用俄羅斯方塊類來實(shí)現(xiàn)程序的表示層,在該窗口中通過兩個Panel控件來實(shí)現(xiàn)方塊疊放窗口和下一方塊信息窗口;調(diào)用設(shè)置窗口,保存設(shè)計窗口類傳回的信息,并設(shè)置到游戲中去,保存在配置文件中;
在設(shè)置窗口中,以良好的界面提供用戶自定義快捷鍵的接口,保存相應(yīng)設(shè)置參數(shù),以提供給調(diào)用窗口。
2.2運(yùn)用的控件和主要對象
在設(shè)計過程中主要用到的控件有:PictureBox控件,MenuStrip控件,Button控件,Label控件,Timer控件,winmm組件,DirectSound等等。
3????????系統(tǒng)功能實(shí)現(xiàn)
3.1???屏幕信息初始化
用來顯示狀態(tài)信息的框
privateSystem.Windows.Forms.GroupBox statusBox;
開始按鈕
privateSystem.Windows.Forms.Button btnStart;
顯示“下一塊”的標(biāo)簽
privateSystem.Windows.Forms.Label label3;
顯示“分?jǐn)?shù)”的標(biāo)簽
privateSystem.Windows.Forms.Label label2;
顯示“等級”的標(biāo)簽
privateSystem.Windows.Forms.Label label1;
用來畫下一塊方塊的區(qū)域
privateSystem.Windows.Forms.PictureBox panel1;
游戲區(qū)域
privateSystem.Windows.Forms.PictureBox gameArea;
實(shí)現(xiàn)如下主界面效果圖(圖3-1):
1.1???方塊的實(shí)現(xiàn)
在程序中每一個方塊都是一個Block類的實(shí)例。Block包括的參數(shù)有方塊的寬度,高度,最左端橫坐標(biāo),最上端縱坐標(biāo),方塊的數(shù)組表示。其中一共有7中形狀的方塊,以數(shù)組表示為:
11???? 11????1???? ??11???? 010????10???? 01
01???? 10????1?????? 11??? ?111???? 11????11
01???? 10????1????????????????????? 01? ???10
1
方塊的7種形狀分別以數(shù)字0-6來代表,在構(gòu)造函數(shù)中,隨機(jī)生成0-6中數(shù)字,以此來隨機(jī)生成方塊的形狀。用來在界面上顯示方塊的貼圖也以0-6的數(shù)字來代表,同樣以隨機(jī)數(shù)的形式來隨機(jī)的現(xiàn)實(shí)方塊的顏色。
1.2???鍵盤輸入事件處理
因?yàn)樵诮缑嫔嫌幸粋€按鈕,并且只有一個按鈕,所以該按鈕在通常情況下都是默認(rèn)為焦點(diǎn)。在這種情況下按下某些鍵,比如空格,就會產(chǎn)生出發(fā)按鈕事件的情況。因此必須重載整個WinForm的ProcessCmdKey來避免這樣的問題。
當(dāng)按向左,向右及旋轉(zhuǎn)按鈕時,只要相應(yīng)的處理方塊的位置或者形狀即可,但是當(dāng)按向下或者立即下落時,需要不同的處理。向下移動時,如果移動到最底部但還未固定,則需要重新設(shè)置計時器間隔時間,從而使自動下落時,底部未固定的方塊到固定的時間相同。如果方塊在最底部而未固定的時候,向下移動,則立即固定。這兩種情況,當(dāng)方塊固定后,都需要判斷是否消行,立即下落時,需要判斷是否消行。
1.3???方塊的移動
游戲中方塊的移動分為向左移動,向右移動,向下移動和立即落下。
向左移動:
public void MoveLeft() {
int xPos =runBlock.XPos-1;
intyPos = runBlock.YPos;
for(int i = 0; i < runBlock.Length; i++)
{
if(xPos + runBlock[i].X <0)//如果超出左邊界則失敗
{
return;
}
if(!coorArr[xPos + runBlock[i].X, yPos - runBlock[i].Y].IsEmpty)//如果左邊有東西擋則失敗
{
return;
}
}
runBlock.erase(gpPaltte);//擦除原來位置的轉(zhuǎn)塊
runBlock.XPos--;
runBlock.Paint(gpPaltte);//在新位置上畫轉(zhuǎn)塊
}
向右移動:
public void MoveRight()
{
intxPos = runBlock.XPos + 1;
intyPos = runBlock.YPos;
for(int i = 0; i < runBlock.Length; i++)
{
if(xPos + runBlock[i].X >_width-1)//如果超出右邊界則失敗
{
return;
}
if(!coorArr[xPos + runBlock[i].X, yPos - runBlock[i].Y].IsEmpty)//如果右邊有東西擋則失敗
{
return;
}
}
runBlock.erase(gpPaltte);//擦除原來位置的轉(zhuǎn)塊
runBlock.XPos++;
runBlock.Paint(gpPaltte);//在新位置上畫轉(zhuǎn)塊
}
向下移動:
public void Drop() {
timerBlock.Stop();
while(Down()) ;
timerBlock.Start();
}
1.4???方塊的變換
public voidDeasilRotate() //順時針旋轉(zhuǎn)
{
for (int i = 0; i< runBlock.Length;i++ )
{
int x = runBlock.XPos + runBlock[i].Y;
int y = runBlock.YPos + runBlock[i].X;
if (x < 0 || x > _width - 1)//如果超出左右邊界,則失敗
return;
if (y < 0 || y > _height - 1)//如果超出上下邊界,則失敗
return;
if (!coorArr[x, y].IsEmpty)//如果旋轉(zhuǎn)后的位置上有轉(zhuǎn)塊,則失敗
return;
}
runBlock.erase(gpPaltte);//擦除原來位置的轉(zhuǎn)塊
runBlock.DeasilRotate();
runBlock.Paint(gpPaltte);//在新位置上畫轉(zhuǎn)塊
}
public voidContraRotate() //逆時針旋轉(zhuǎn)
{
for (int i = 0; i< runBlock.Length; i++)
{
int x = runBlock.XPos - runBlock[i].Y;
int y = runBlock.YPos - runBlock[i].X;
if (x < 0 || x > _width - 1)//如果超出左右邊界,則失敗
return;
if (y < 0|| y > _height - 1)//如果超出上下邊界,則失敗
return;
if (!coorArr[x, y].IsEmpty)//如果旋轉(zhuǎn)后的位置上有轉(zhuǎn)塊,則失敗
return;
}
runBlock.erase(gpPaltte);//擦除原來位置的轉(zhuǎn)塊
runBlock.ContraRotate();
runBlock.Paint(gpPaltte);//在新位置上畫轉(zhuǎn)塊
}
1.5???判斷方塊是否到底
public voidCheckAndOverBlock()//檢查轉(zhuǎn)塊是否到底,如果到底則把當(dāng)前轉(zhuǎn)塊歸入coorArr,并產(chǎn)生新的轉(zhuǎn)塊
{
boolover = false;//設(shè)置一個當(dāng)前運(yùn)行轉(zhuǎn)塊是否到底的標(biāo)志
for(int i = 0; i < runBlock.Length;i++ )//遍歷當(dāng)前運(yùn)行轉(zhuǎn)塊的所有小方塊
{
intx = runBlock.XPos + runBlock[i].X;
inty = runBlock.YPos - runBlock[i].Y;
if(y == _height - 1)//如果到達(dá)下邊界,則結(jié)束當(dāng)前轉(zhuǎn)塊
{
over = true;
break;
}
if(!coorArr[x, y+1].IsEmpty) //如果下面有轉(zhuǎn)塊,則當(dāng)前轉(zhuǎn)塊結(jié)束
{
over = true;
break;
}
}
if(over)
{
for(int i = 0; i < runBlock.Length; i++)//把當(dāng)前轉(zhuǎn)塊歸入coordinateArr
{
coorArr[runBlock.XPos +runBlock[i].X, runBlock.YPos - runBlock[i].Y] = runBlock.BlockColor;
}
//檢查是否有滿行情況,如果有則刪除
CheckAndDelFullRow();
//產(chǎn)生新轉(zhuǎn)塊
runBlock = readyBlock;//新的轉(zhuǎn)塊為準(zhǔn)備好的轉(zhuǎn)塊
runBlock.XPos = _width / 2;//確定當(dāng)前運(yùn)行轉(zhuǎn)塊的出生位置
int y = 0;//確定轉(zhuǎn)塊Ypos,確定剛出生的轉(zhuǎn)塊頂上沒空行
for (int i = 0; i < runBlock.Length; i++)
{
if (runBlock[i].Y > y)
y = runBlock[i].Y;
}
runBlock.YPos = y;
//檢查新生成的轉(zhuǎn)塊所占用的地方是否已經(jīng)有轉(zhuǎn)塊存在,如果有,游戲結(jié)束
for (int i = 0; i { if (!coorArr[runBlock.XPos+ runBlock[i].X, runBlock.YPos - runBlock[i].Y].IsEmpty) { StringFormat drawFormat= new StringFormat(); drawFormat.Alignment =StringAlignment.Center; gpPaltte.DrawString("GAME OVER", newFont("Arial Black", 25f), newSolidBrush(Color.White), newRectangleF(0, _height * rectPix / 2 - 100, _width * rectPix, 100), drawFormat); timerBlock.Stop();//關(guān)閉定時器 return; } } runBlock.Paint(gpPaltte); //獲取新的準(zhǔn)備轉(zhuǎn)塊 readyBlock = bGroup.GetABlock(); readyBlock.XPos = 2; readyBlock.YPos = 2; gpReady.Clear(Color.Black); readyBlock.Paint(gpReady); } } 1.6???滿行判斷并消行 privatevoid CheckAndDelFullRow() //檢查并刪除滿行 { //找出當(dāng)前轉(zhuǎn)塊所在行的范圍 int lowRow = runBlock.YPos - runBlock[0].Y;//lowRow代表當(dāng)前轉(zhuǎn)塊的y軸的最小值 int highRow = lowRow;//highRow代表當(dāng)前轉(zhuǎn)塊y軸的最大值 for (int i = 0; i < runBlock.Length; i++)//找出當(dāng)前轉(zhuǎn)塊所占行的范圍,放入low和high變量內(nèi) { int y = runBlock.YPos - runBlock[i].Y; if (y < lowRow) lowRow = y; if (y > highRow) highRow = y; } bool repaint = false;//判斷是否重畫標(biāo)志 for (int i = lowRow; i <= highRow; i++) //檢查是否滿行,如果有,則刪除 { bool rowFull = true; for (int j = 0; j < _width;j++ ) { if (coorArr[j,i].IsEmpty)//如果有一行為空,則說明這行不滿 { rowFull = false; break; } } if (rowFull) //如果是滿行,則刪除這一行 { repaint = true;//如果有要刪除的行,則需要重畫 for (int k = i; k > 0;k--) {//把第n行的值用n-1行的值來代替 for (int j = 0; j <_width; j++) { coorArr[j, k] =coorArr[j, k - 1]; } } for (int j = 0; j <_width;j++ )//清空第0行 { coorArr[j, 0] = Color.Empty; } } } if(repaint)//重畫 { PaintBackground(gpPaltte); } } 3.8? 產(chǎn)生下一方塊 public bool GeneBlock(int shapeNO, Point firstPos, Colorcolor)//產(chǎn)生下一方塊 { this.SetLastPos(); this.EraseLast(); this.SetPos(shapeNO,firstPos); if(!this.CanRotate(this.pos)) { this.pos=null; returnfalse; } else { this.color=color; returntrue; } } 3.9????????游戲設(shè)置 保存配置 private void SaveSetting() { try { XmlDocumentdoc = new XmlDocument(); XmlDeclarationxmlDec=doc.CreateXmlDeclaration ("1.0","gb2312",null); XmlElementsetting=doc.CreateElement("SETTING"); doc.AppendChild(setting); XmlElementlevel=doc.CreateElement("LEVEL"); level.InnerText=this.startLevel.ToString(); setting.AppendChild(level); XmlElementtrans=doc.CreateElement("TRANSPARENT"); trans.InnerText=this.trans.ToString(); setting.AppendChild(trans); XmlElementkeys=doc.CreateElement("KEYS"); setting.AppendChild(keys); foreach(Keysk in this.keys) { KeysConverterkc=new KeysConverter(); XmlElementx=doc.CreateElement("SUBKEYS"); x.InnerText=kc.ConvertToString(k); keys.AppendChild(x); } XmlElementroot=doc.DocumentElement; doc.InsertBefore(xmlDec,root); doc.Save("c:\\setting.cob"); } catch(Exceptionxe) { MessageBox.Show(xe.Message); } } 4? 總結(jié) 本設(shè)計通過Vusial Studio 方便的Windows表單設(shè)計界面,增加了相應(yīng)的按鈕單擊響應(yīng)函數(shù),通過與用戶的交互,反饋回用戶所需要的信息。 設(shè)計出的程序符合設(shè)計需求,既有基本的游戲邏輯功能,又能保存用戶的設(shè)置,取得較好的實(shí)驗(yàn)結(jié)果。 C#
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。