c#實現簡單的俄羅斯方塊
由於最近剛進出c#,想快速上手,所以決定寫幾個小遊戲(後面會陸續更新)來熟悉語言,並且記錄學習winform的一些相關問題和解決方法。
首先給我的感覺winform和c++中的介面設計MFC還是非常類似的(很可惜當時MFC深入淺出沒吃透徹),下面我們就從最基礎簡單的來實現俄羅斯方塊:
1首先弄出一個窗體:
我是在pictureBox控制元件上面實現畫圖的(因為沒找到圖片資源,所以我的方塊都是GDI繪製的)然後就是設定一個定時器,再點選開始選單的時候啟動定時器,具體時間間隔自己決定,其中可能要用到的定時器的函式和屬性:
timer.Enable :表示定時器是否啟動,true是啟動,false是關閉。
timer.Interval:表示定時器的間隔時間。
然後是邏輯的設計:採用一個二維陣列記住pictureBox,然後1表示該格子是有方塊的,每次計時器中呼叫重新整理函式來重新整理窗體,這樣就可以呼叫paint函式來繪製圖形,然後邏輯的操作其實都是對二維陣列的操作,最後傳給paint函式的都是操作後的結果陣列。
this.Invalidate() :重新整理窗體,可以呼叫到paint函式。
然後再PictureBox上面畫圖的時候要注意,如果是直接繪製的話,會出現一些很奇怪的問題,所以我們採用繪製再點陣圖上面然後再貼在pictureBox上面(詳情請見上一篇)
下面貼上一些部分關鍵程式碼:
public partial class Form1 : Form
{
public int Down_Type; //方塊的大種類
public int Type_Direction; //方塊的什麼朝向
public int Down_Speed = 25;
public int Control_Speed = 25; //左右的速度
public int[][] map; //pictureBox的二維地圖對映
public Boolean IsLand = true; //是否該產生塊
public Point CorePosition; //左上角用來重新整理的時候定位用的點
public Boolean Is_Go_Left = false;
public Boolean Is_Go_Down = false;
public Boolean Is_Go_Up = false;
public Boolean Is_Go_Right = false; //是否右前進
public int Max_Right,Max_Buttom; //最右邊的橫座標和最下面的豎著的座標
public int Score = 0; //記分器
public int level = 1; //難度級別
public Form1()
{
InitializeComponent();
this.ScorePain.Text = "0";
}
下面是擦除的函式,實現動畫效果我是直接擦除上一次的痕跡然後重新繪製,但是由於可以按“↑”來改變圖形,多以在擦除的程式碼應該分情況。
public void ClearScreen()
{
switch (Down_Type)
{
//14列大概是中點
case 1:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down && CorePosition.X > 0)
CorePosition.X -= 1;
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X + 1][CorePosition.Y] = 0;
map[CorePosition.X][CorePosition.Y+1] = map[CorePosition.X+1][CorePosition.Y+1] = 0;
break;
}
case 2:
{
switch (Type_Direction)
{
case 1:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if(!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X+1][CorePosition.Y] = 0;
map[CorePosition.X+2][CorePosition.Y] = map[CorePosition.X + 2][CorePosition.Y + 1] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X+1][CorePosition.Y] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X + 1][CorePosition.Y + 2] = 0;
}
break;
}
case 2:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if(!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y+1] = 0;
map[CorePosition.X][CorePosition.Y+2] = map[CorePosition.X -1][CorePosition.Y+2] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X+1][CorePosition.Y] = 0;
map[CorePosition.X+2][CorePosition.Y] = map[CorePosition.X + 2][CorePosition.Y + 1] = 0;
}
break;
}
case 3:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if(!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X+1][CorePosition.Y] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X + 1][CorePosition.Y + 2] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y+1] = 0;
map[CorePosition.X][CorePosition.Y+2] = map[CorePosition.X -1][CorePosition.Y+2] = 0;
}
break;
}
}
break;
}
case 3:
{
switch (Type_Direction)
{
case 1:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X + 1][CorePosition.Y + 2] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X + 1][CorePosition.Y] = 0;
map[CorePosition.X][CorePosition.Y + 1] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
break;
}
case 2:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X + 1][CorePosition.Y] = 0;
map[CorePosition.X][CorePosition.Y + 1] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X + 1][CorePosition.Y + 2] = 0;
}
break;
}
}
break;
}
case 4:
{
switch (Type_Direction)
{
case 1:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X][CorePosition.Y + 3] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X + 1][CorePosition.Y] = 0;
map[CorePosition.X + 2][CorePosition.Y] = map[CorePosition.X + 3][CorePosition.Y] = 0;
}
break;
}
case 2:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X + 1][CorePosition.Y] = 0;
map[CorePosition.X + 2][CorePosition.Y] = map[CorePosition.X + 3][CorePosition.Y] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X][CorePosition.Y + 3] = 0;
}
break;
}
}
break;
}
case 5:
{
switch (Type_Direction)
{
case 1:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
break;
}
case 2:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X + 1][CorePosition.Y + 1] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
break;
}
case 3:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X + 1][CorePosition.Y + 1] = 0;
}
break;
}
}
break;
}
}
}
然後是難度的選擇,難度窗體我是在設計的一個窗體,所以需要在兩個窗體中傳遞資料,但是操作起來並沒有想象中的那麼難,直接新增變數就可以完成操作。:
private void menuItem5_Click(object sender, EventArgs e)
{
Level L = new Level();
L.Text = "難度選擇";
L.ShowDialog();
level = L.level;
//MessageBox.Show(level.ToString());
}
然後是radioButton,有多個的時候想要在初始的時候選中其中一個,那麼它有個屬性Checked可以選擇上為True就行了。
還有一個Key的事件的問題:注意下面的
其中我使用的列舉值Keys.Up等是用KeyData來實現的:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//MessageBox.Show("Left!");
if (e.KeyData == Keys.Left && !Is_Go_Left)
{
if (CorePosition.Y > 0)
{
CorePosition.Y -= 1;
Is_Go_Left = true;
}
}
else if (e.KeyData == Keys.Right && !Is_Go_Right)
{
if (Max_Right < 16)
{
CorePosition.Y += 1;
Is_Go_Right = true;
}
}
else if (e.KeyData == Keys.Down && !Is_Go_Down)
{
if (Max_Buttom < 20)
{
CorePosition.X += 1;
Is_Go_Down = true;
}
}
else if (e.KeyData == Keys.Up && !Is_Go_Up)
{
Is_Go_Up = true;
}
}
相關文章
- canvas實現俄羅斯方塊Canvas
- 初學者——Java之實現簡易俄羅斯方塊Java
- 使用JavaScript實現一個俄羅斯方塊JavaScript
- Flutter Web 實戰 - 俄羅斯方塊FlutterWeb
- 俄羅斯方塊聯機小遊戲的實現遊戲
- 俄羅斯方塊練習
- 俄羅斯方塊(JS+CSS)JSCSS
- Tetris 俄羅斯方塊遊戲遊戲
- 使用C#和MonoGame開發俄羅斯方塊遊戲C#MonoGAM遊戲
- 【Java遊戲】java俄羅斯方塊!Java遊戲
- 300行Python程式碼實現俄羅斯方塊,致敬逝去的童年Python
- 最新《 java實戰開發俄羅斯方塊教程》Java
- Python 實戰開發俄羅斯方塊遊戲Python遊戲
- Python:遊戲:300行程式碼實現俄羅斯方塊Python遊戲行程
- 基於Flutter的俄羅斯方塊小遊戲Flutter遊戲
- Python3+pygame實現的俄羅斯方塊 程式碼完整 有演示效果PythonGAM
- 如何讓 Emacs 俄羅斯方塊變得更難Mac
- wxpython入門第十一步(俄羅斯方塊)Python
- 基於MonoGame重製《俄羅斯方塊》遊戲MonoGAM遊戲
- 【補檔STM32】STM32F103俄羅斯方塊遊戲實現遊戲
- 如何讓AI教機器自己玩俄羅斯方塊?AI
- 用React、Redux、Immutable做俄羅斯方塊 | 掘金技術徵文ReactRedux
- 從俄羅斯方塊,邁向強化學習大門強化學習
- 俄羅斯方塊歷史發展與變革創新
- 用 SQL 寫的俄羅斯方塊遊戲「GitHub 熱點速覽」SQL遊戲Github
- 函數語言程式設計嘗試之俄羅斯方塊函數程式設計
- “漢字俄羅斯方塊”《一字不落》今日上架Steam
- 為了上班摸魚我用Python製作了俄羅斯方塊?Python
- python開發俄羅斯方塊小遊戲程式碼例項Python遊戲
- [分享]純python3手寫Tetris(俄羅斯方塊)遊戲Python遊戲
- 回顧「俄羅斯方塊」曾經的一段蒸汽波時代
- 超越《俄羅斯方塊》後,《我的世界》想打造一個更具野心的世界
- pyqt5製作俄羅斯方塊小遊戲-----原始碼解析QT遊戲原始碼
- 俄羅斯玩偶
- 俄羅斯:‘區塊鏈屬於我們’區塊鏈
- 《俄羅斯方塊》系列 35 週年 一窺遊戲歷年玩法演變遊戲
- 俄羅斯軍方正在建設區塊鏈研究實驗室區塊鏈
- 俄羅斯的加密貨幣註冊公司白名單加密