我自己本身是逢甲機電系,因為在大二的時候學到自己系內的「計算機程式」,學得蠻有心得的,因此在系外選修的部分就選了有關程式設計的課程。
那老師上課的時候出了一份加分的期末作業給我們同學,一心想拿滿分的我就帶有這一份衝勁來撰寫這套程式 - 貪吃蛇,因為我小時候第一次接觸的遊戲就是貪吃蛇,就決定我的期末作品的主題了。
程式說明:
因為我自以本身比較常在寫數值分析的程式,對於以From視窗的事件發生比較不熟悉,卡BUG卡得比較久花了點時間。~"~
好了進入正題,一開始我宣告了以下幾個物件:
Button Start_Btn 是為了按下開始
Button CtrlSz_Btn 控制邊界大小,不過BUG太多了,暫時先不啟用這個功能
GroupBox Bdry_GB 為了設定貪吃蛇可以行走的邊界範圍
Label Snk_Lbl 貪吃蛇的頭
Label FdRdom_Lbl 食物每一次出現都必須隨機
Label[] SkB_Lbl 貪吃蛇的身體,食物吃得越多,身體就越長,是一個矩陣label
Label Msg_Lbl 訊息Label
Timer Mv_Timer 讓貪吃蛇移動,宣告Timer事件移動
Random SnakePositionX_Rand 隨機的食物位置X
Random SnakePositionY_Rand 隨機的食物位置Y
我當然還有一些變數,不過那之後就再介紹就行了。進入Form1_Load裡面,當然就是先設定每個物件的參數,包含:位置、尺寸等等,以及非常重要的三個事件,開始鍵的設定時間的前進以及按鍵的事件等。
Start_Btn_Click:
當「Start」按下去時,必須先重新設定「SnakeHead」、「FoodRandom」、「SnakeBody」、「Grade」、「Timer」、「Direction」。
SnakeHead:包含了可視化、尺寸、位置、顏色以及秀出在GroupBox上的語句。
FoodRandom:同上
SnakeBody:因為身體的數量會不斷增加,因此必須利用矩陣的方式宣告,宣告完後也必須設定參數,同上。但是不能先宣告位置跟加入控制,因為還沒吃到食物。
Grade:就是分數,一開始的分數一定等於零。
Timer:設定每次發生之間的間隔以及開啟時間計時。
Determined_Direction:顧名思義,就是設定貪吃蛇前進的方向。
Boundary_GBox_KeyUp:
其實就是設定「W」「A」「S」「D」的方向控制,不過必須要注意一點,方向在轉的時候,每次就只能夠轉九十度、不能夠一百八十度。
Move_Timer_Tick:
「SnakeBody moving」:貪吃蛇的身體會隨著「FN_int」增加而增加,增加之後必須要讓前面的身體往後補到後面的位置,必須要做位置交換的動作。這時,為了要存起第一個位置的變數,必須先宣告一個暫時的變數儲存。
「SnakeHead Moving」:貪吃蛇開始往前進。控制方向已經由按鍵事件控制了,左右一個控制變數、上下一個控制變數,分別以1、0、-1來做表示。
「Setting the mesh」:為了確保貪吃蛇的位置都能夠在整數上面,因此在此程式統一為20像素為一個單位,無論上下左右前進步距皆為20個像素,因此在這裡做設定。
「Boundary Line」:在這裡必須設定兩個遊戲的限制條件,第一個不能夠超過邊界、第二個不能夠接觸到貪吃蛇自己本身的身體。所以特別宣告了布林變數
「Eaing the Food」:當吃到食物所發生的事件,也就意味著貪吃蛇的頭與食物的位置相等,這個假設成立後,「FN_int」增加。因為難度設計的關係速度也要變快,意味著事件發生的時間間距縮短。在秀出貪吃蛇的身體。
貪吃蛇:程式碼
========================================================================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace 貪吃蛇
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//=======================================
Button Start_Btn = new Button(); // Start_Button
Button CtrlSz_Btn = new Button(); // ControlSize_Button
GroupBox Bdry_GB = new GroupBox(); // Boundary_GroupBox
Label Snk_Lbl = new Label(); // SnakeHead_Label
Label FdRdom_Lbl = new Label(); // FoodRandom_Label
Label[] SkB_Lbl; // SnakeBody_Label
Label Msg_Lbl = new Label(); // Message_Label
Timer Mv_Timer = new Timer(); // Move_Timer
Random SnakePositionX_Rand = new Random(RandY_int); // SnakePositionX_Random
Random SnakePositionY_Rand = new Random(FN_int); // SnakePositionY_Random
private int Level_int = 1; // Game Level
private int SnakeMoveStep_int = 20; // Move the 20 unit
public int TopBottom_int = 0, RightLeft_int = 1; // Determine the direction
private static int RandX_int = 200, RandY_int = 200; // FoodLocation
private static int FN_int = 0; // FoodNumber_int
private int GBox_X, GBox_Y, GBox_h, GBox_w, Btn_X, Btn_Y; //
private int Tmp_X = 0, Tmp_Y = 0; // Temporary Position
private int Grade = 0; //
//=======================================
private void Form1_Load(object sender, EventArgs e)
{
//--Boundary_GBox--
GBox_X = 400 + 20; GBox_Y = 400 + 10; // Getting the X , Y
GBox_h = 20; GBox_w = 20; // Getting the h , w
Bdry_GB.Text = ""; // Setting the name
Bdry_GB.Location = new Point(GBox_w, GBox_h); // Setting the point
Bdry_GB.Size = new Size(GBox_X, GBox_Y); // Setting the Size
this.Controls.Add(Bdry_GB); // Showing the Boundary_GBox
//--Start_Btn_Setting--
Btn_X = 100; Btn_Y = 30;
Start_Btn.Text = "Start Game"; // Setting the Name
Start_Btn.Location = new Point(GBox_h, GBox_h + GBox_X); // Setting the position
Start_Btn.Size = new Size(Btn_X, Btn_Y); // Setting the size
Start_Btn.Click += Start_Btn_Click; // Adding the Event
this.Controls.Add(Start_Btn); // Showing this Start_Btn
//--ControlSize_Btn_Setting-- 視窗放大
//CtrlSz_Btn.Text = "Choice Size"; // Setting the name
//CtrlSz_Btn.Location = new Point(GBox_h, GBox_h + GBox_X + Btn_Y); // Setting the point
//CtrlSz_Btn.Size = new Size(Btn_X, Btn_Y); // Setting the Size
//CtrlSz_Btn.Click += ChoiceSize_Btn_Click; // Adding the Eevnt
//this.Controls.Add(CtrlSz_Btn); // Showing this ControlSize_Btn
//--Message_Lbl--
Msg_Lbl.AutoSize = true; // Setting the AutoSize is true
Msg_Lbl.Location = new Point(Btn_X + GBox_h, GBox_X + Btn_Y); // Setting the Location
this.Controls.Add(Msg_Lbl); // Showing in the this from
//--Event--
Mv_Timer.Tick += Move_Timer_Tick; // Adding the Event
Bdry_GB.KeyUp += Boundary_GBox_KeyUp; // Adding the Event
//--From Setting--
this.Text = "貪吃蛇"; // Setting the windows's Name
this.Width = GBox_Y + 3 * GBox_w; // Setting the windows's Width
this.Height = 5 * GBox_X / 3; // Setting the windows's Height
}
//--Event--
void Start_Btn_Click(object sender, EventArgs e)
{
//--SnakeHead--
int w = this.Bdry_GB.Size.Width; // Getting the this width
int h = this.Bdry_GB.Size.Height; // Getting the this Height
Snk_Lbl.Enabled = true; // Setting the Enabled is true
Snk_Lbl.Size = new Size(20, 20); // Setting the Size
Snk_Lbl.Location = new Point(0, w / 2 - Snk_Lbl.Size.Width); // Setting the Location
Snk_Lbl.BackColor = Color.Red; // Setting the Color red
this.Bdry_GB.Controls.Add(Snk_Lbl); // Showing the GBox
//--FoodRandom_Lbl--
FdRdom_Lbl.Size = new Size(20, 20);
FdRdom_Lbl.BackColor = Color.Blue;
FdRdom_Lbl.Location = new Point(200, 190);
this.Bdry_GB.Controls.Add(FdRdom_Lbl);
//--SnakeBooy--
SkB_Lbl = new Label[w * h / 400 + 1];
for (int i = 1; i < SkB_Lbl.Length; i++)
{
SkB_Lbl[i] = new Label();
SkB_Lbl[i].Size = new Size(20, 20);
SkB_Lbl[i].BackColor = Color.Black;
}
//--Grade--
Grade = 0;
//--Timer--
//Mv_Timer.Interval = 15 * (10 - Level_int); // Following the Level with decreasing
Mv_Timer.Interval = 150; // Following the Level with decreasing
Mv_Timer.Enabled = true; // Trun on the Enabled
//--Determined_Direction--
TopBottom_int = 0; RightLeft_int = 1; // Initial direction
Bdry_GB.Focus(); // Getting the Boundary Control
}
/*void ChoiceSize_Btn_Click(object sender, EventArgs e)
{
// Control this windows Size
if (Bdry_GB.Size.Width == GBox_X) Bdry_GB.Size = new Size(GBox_X * 13 / 10, GBox_Y * 13 / 10);
else if (Bdry_GB.Size.Width == GBox_X * 13 / 10) Bdry_GB.Size = new Size(GBox_X * 16 / 10, GBox_Y * 16 / 10);
else if (Bdry_GB.Size.Width == GBox_X * 16 / 10) Bdry_GB.Size = new Size(GBox_X, GBox_Y);
// follow chance
//---form---
this.Width = Bdry_GB.Size.Width + 3 * Bdry_GB.Location.X; // Setting the windows's Width
this.Height = 5 * Bdry_GB.Size.Height / 3; // Setting the windows's Height
//---Btn---
Start_Btn.Location = new Point(Bdry_GB.Location.X, Bdry_GB.Location.Y + Bdry_GB.Size.Height); // Setting the position
CtrlSz_Btn.Location = new Point(Bdry_GB.Location.X, Bdry_GB.Location.X + Bdry_GB.Size.Height + Btn_Y); // Setting the point
//---Lbl---
Msg_Lbl.Location = new Point(Btn_X + Bdry_GB.Location.X, Bdry_GB.Size.Width + Btn_Y); // Setting the Location
Snk_Lbl.Location = new Point(0, this.Bdry_GB.Size.Width / 2 - Snk_Lbl.Size.Width); // Setting the Location
// Restart
if (Mv_Timer.Enabled == true)
{
Mv_Timer.Enabled = false; // Trun off the Enabled
Snk_Lbl.Enabled = false; // Hidding the SnakeHead
Snk_Lbl.Location = new Point(0, Bdry_GB.Size.Height); // Setting the Location
TopBottom_int = 0; RightLeft_int = 1; // Initial direction
MessageBox.Show("Restart!!"); // MessageBox
}
}*/
void Boundary_GBox_KeyUp(object sender, KeyEventArgs e)
{
// Control the direction
switch (e.KeyCode)
{
case Keys.A:
{
if (RightLeft_int == 1) break;
TopBottom_int = 0;
RightLeft_int = -1;
break;
}
case Keys.D:
{
if (RightLeft_int == -1) break;
TopBottom_int = 0;
RightLeft_int = 1;
break;
}
case Keys.W:
{
if (TopBottom_int == 1) break;
TopBottom_int = -1;
RightLeft_int = 0;
break;
}
case Keys.S:
{
if (TopBottom_int == -1) break;
TopBottom_int = 1;
RightLeft_int = 0;
break;
}
}
}
void Move_Timer_Tick(object sender, EventArgs e)
{
// SnakeBody moving
for (int i = FN_int; i >= 1; i--)
{
Tmp_X = SkB_Lbl[i].Location.X; Tmp_Y = SkB_Lbl[i].Location.Y;
SkB_Lbl[i + 1].Location = new Point(Tmp_X, Tmp_Y);
}
// Body will follow the SnakeHead
SkB_Lbl[1].Location = new Point(Snk_Lbl.Location.X, Snk_Lbl.Location.Y);
// SnakeHead moving
// OK
Snk_Lbl.Left += SnakeMoveStep_int * RightLeft_int; // SnakeHead move
Snk_Lbl.Top += SnakeMoveStep_int * TopBottom_int; // SnakeHead move
// Make sure meshes are 20 unit Setting the mesh
// OK
int[] X = new int[(Bdry_GB.Width - FdRdom_Lbl.Size.Width) / 20];
int[] Y = new int[(Bdry_GB.Width - FdRdom_Lbl.Size.Width) / 20];
for (int i = 0; i < X.Length; i++)
{
X[i] = i * ((Bdry_GB.Width - FdRdom_Lbl.Size.Width) / 20);
Y[i] = 10 + i * ((Bdry_GB.Width - FdRdom_Lbl.Size.Width) / 20);
}
// Can't be over the boundary line
// OK
bool BoundaryLine_bool =
(
Snk_Lbl.Left <= -10 | // Left Boundary
Snk_Lbl.Left >= Bdry_GB.Size.Width | // Right Boundary
Snk_Lbl.Top <= -10 | // Top Boundary
Snk_Lbl.Top >= Bdry_GB.Size.Height // Button Boundary
);
// Can't touch Snake Body
// OK
for (int i = 1; i <= FN_int; i++)
if (Snk_Lbl.Location == SkB_Lbl[i].Location)
BoundaryLine_bool = true;
// If that's true
if (BoundaryLine_bool == true)
{
int w = Bdry_GB.Width; // Simpifity
Snk_Lbl.Location = new Point(0, w / 2 - 2 * Snk_Lbl.Width); // Setting the Location
TopBottom_int = 0; RightLeft_int = 0; // Initial direction and Speed equal zero
Snk_Lbl.Location = new Point(0, w / 2 - Snk_Lbl.Size.Width); // Setting the Location
//
Mv_Timer.Enabled = false; // Close the Timer
for (int i = 1; i <= FN_int; i++) SkB_Lbl[i].Visible = false;// Body
FN_int = 0; // Restart
this.Bdry_GB.Controls.Remove(FdRdom_Lbl); // Adding the FoodRandom
MessageBox.Show("Game Over"); // Show "You over the Boundary Line"
return;
}
// Eating the Food
// OK
if (Snk_Lbl.Location == FdRdom_Lbl.Location)
{
FN_int++; // Number plus one
Mv_Timer.Interval -= 2; // Level Faster
for (int i = 1; i <= FN_int; i++) this.Bdry_GB.Controls.Add(SkB_Lbl[i]); // Adding the Snaek Body
//
RandX_int = SnakePositionX_Rand.Next(0, X.Length); // Setting the New Random X
RandY_int = SnakePositionY_Rand.Next(0, Y.Length); // Setting the New Random Y
FdRdom_Lbl.Location = new Point(X[RandX_int], Y[RandY_int]); // Setting the New Position
this.Bdry_GB.Controls.Add(FdRdom_Lbl); // Show the FdRdom_Lbl
for (int i = 1; i <= FN_int; i++) Grade += 200 - Mv_Timer.Interval; // Plus Grade
}
// MessageBox
Msg_Lbl.Text = "Your Grade is " + Grade.ToString();
}
}
}
========================================================================
沒有留言:
張貼留言