这两天花了点时间写了贪吃蛇这个小程序,现在将大体的设计过程描述一下,源程序请在www.csdn.net下载,我的用户名为andamajing。
简单的分析一下,贪吃蛇从总体上说显示和控制两大部分,第一方面显示部分包含窗体的整体布局,游戏活动部分的显示,以及得分的显示,游戏帮助和关于这个游戏的说明;第二方面是控制部分,控制部分包含游戏中蛇和食物的颜色设置,开始,暂停,停止等控制按键以及方向键的控制。
首先对于蛇,我们需要定义一个类,这个类包含蛇的组成单元及大小,蛇的颜色,蛇的长度和蛇的运动方向等基本字段,蛇的移动,吃食物等基本方法,以及是否死亡等标识。具体定义如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
namespace SnakeGame
{
class Snake
{
//蛇身单元
private Label bodyCeil;
//蛇身单元大小
static private Size size=new Size(10,10);
//蛇身颜色
public Color snakeColor;
//蛇身链表
ArrayList snake = new ArrayList();
//蛇身长度
private int snakeLength=5;
public int SnakeLength
{
get
{
return snake.Count;
}
}
//蛇运动方向,初始向右
private Direction snakeDirection=Direction.Right;
public Direction SnakeDirection
{
get
{
return snakeDirection;
}
set
{
snakeDirection=value;
}
}
//食物是否吃完标志
private bool flag = false;
public bool Flag
{
get
{
return flag;
}
set
{
flag = value;
}
}
//画初始蛇体
private void DrawBeginSnake()
{
for (int i = 0; i < 5; i++)
{
bodyCeil = new Label();
bodyCeil.BackColor = snakeColor;
bodyCeil.Size = size;
bodyCeil.Location = new Point(40 - i * 10, 0);
bodyCeil.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
snake.Add(bodyCeil);
}
}
//带参数的构造函数,可设置蛇身颜色
public Snake(Color newcolor)
{
snakeColor = newcolor;
DrawBeginSnake();
}
//返回蛇体
public ArrayList GetSnake()
{
return snake;
}
//是否有食物标志
private bool hasFood = false;
//定义蛇是否死亡标志,true为死亡,false为没死
private bool isDead = false;
public bool IsDead
{
get
{
return isDead;
}
}
//蛇移动
public void Move(System.Windows.Forms.Control control,Label food)
{
if (!hasFood)
{
control.Controls.Remove(control.GetChildAtPoint(((Label)snake[snake.Count-1]).Location));
snake.RemoveAt(snake.Count - 1);
}
Label snakeHead = new Label();
CopySnakeBodyCeil(snakeHead, (Label)snake[0]);
switch (snakeDirection)
{
case Direction.Up:
snakeHead.Top -= 10;
if (snakeHead.Top < 0)
isDead = true;
break;
case Direction.Down:
snakeHead.Top += 10;
if (snakeHead.Top > 270)
isDead = true;
break;
case Direction.Left:
snakeHead.Left-= 10;
if (snakeHead.Left < 0)
isDead = true;
break;
case Direction.Right:
snakeHead.Left+= 10;
if (snakeHead.Left > 340)
isDead = true;
break;
}
snake.Insert(0, snakeHead);
if (hasFood)
{
hasFood = false;
control.Controls.Remove(control.GetChildAtPoint(food.Location));
//control.Controls.Clear();
this.flag = true;
}
}
//复制蛇单元
private void CopySnakeBodyCeil(Label to, Label from)
{
to.BackColor = from.BackColor;
to.Size = from.Size;
to.Location = from.Location;
to.BorderStyle = from.BorderStyle;
}
//判断是否有食物标志
public void EatFood(Label _food)
{
switch (snakeDirection)
{
case Direction.Up:
if (((Label)snake[0]).Left == _food.Left && ((Label)snake[0]).Top == _food.Top + 10)
hasFood = true;
else
hasFood = false;
break;
case Direction.Down:
if (((Label)snake[0]).Left == _food.Left && ((Label)snake[0]).Top == _food.Top - 10)
hasFood = true;
else
hasFood = false;
break;
case Direction.Left:
if (((Label)snake[0]).Left == _food.Left + 10 && ((Label)snake[0]).Top == _food.Top)
hasFood = true;
else
hasFood = false;
break;
case Direction.Right:
if (((Label)snake[0]).Left == _food.Left - 10 && ((Label)snake[0]).Top == _food.Top )
hasFood = true;
else
hasFood = false;
break;
}
}
}
}
接下来就是食物的定义了,具体第一如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace SnakeGame
{
class Food
{
//定义一个食物
private Label foodCeil=new Label();
public Label FoodCeil
{
get
{
return foodCeil;
}
set
{
foodCeil = value;
}
}
//定义食物的颜色
private Color foodColor;
public Color FoodColor
{
get
{
return foodColor;
}
}
//定义食物位置
private Point foodLocation;
public Point FoodLocation
{
get
{
return new Point(foodCeil.Top, foodCeil.Left);
}
}
//定义食物的大小
private static Size foodSize = new Size(10, 10);
//构造函数,
public Food(Color color,Point point)
{
foodCeil.Size = foodSize;
foodCeil.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
foodCeil.BackColor = color;
foodCeil.Left = point.X;
foodCeil.Top = point.Y;
foodColor = color;
}
//复制食物单元
public void CopyFoodCeil(Label to, Label from)
{
to.BackColor = from.BackColor;
to.Size = from.Size;
to.Location = from.Location;
to.BorderStyle = from.BorderStyle;
}
}
}
上面两个类定义了这个游戏中的两个对象,接下来就需要在主题的显示界面中去控制蛇的运动,主题的界面如下所示:
运行的界面如下所示:
游戏结束的画面如下:
设置颜色的窗体显示如下:
接下来说一下主程序中控制程序,在程序中控制菜单项和按键如何进行处理。
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;
using SnakeGame.Properties;
namespace SnakeGame
{
public partial class FormSnakeGame : Form
{
//定义一个蛇
private Snake mySnake;
//定义一个食物
private Food myFood;
//定义蛇颜色
private Color mySnakeColor;
//定义食物颜色
private Color myFoodColor;
//定义一个颜色设置窗口
颜色设置 gameColorSetting =new 颜色设置();
public FormSnakeGame()
{
InitializeComponent();
this.buttonStop.Enabled = false;
ClearDirection();
this.低水平ToolStripMenuItem.Checked = true;
this.panelGame.BackgroundImage = Resources.myblog;
}
private void 游戏说明ToolStripMenuItem1_Click(object sender, EventArgs e)
{
游戏操作 gameOperationInformation = new 游戏操作();
gameOperationInformation.Show();
}
private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
{
关于 gameAbout = new 关于();
gameAbout.Show();
}
private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void 颜色设置ToolStripMenuItem_Click(object sender, EventArgs e)
{
//gameColorSetting = new 颜色设置();
gameColorSetting.Show();
}
//停止或暂停按键按下
private static int i = 0;//用于判断显示Stop还是显示Continue
private void buttonStop_Click(object sender, EventArgs e)
{
if (i++ % 2 == 0)
{
this.buttonStop.Text = "Continue";
this.timerSnakeSpeed.Enabled = false;
}
else
{
this.buttonStop.Text = "Stop";
this.timerSnakeSpeed.Enabled = true;
}
}
//开始按键按下
private void buttonStart_Click(object sender, EventArgs e)
{
this.panelGame.BackgroundImage = null;
this.buttonStart.Enabled = false;
EnableDirection();
mySnakeColor = gameColorSetting.SetSnakeColor;
myFoodColor = gameColorSetting.SetFoodColor;
this.buttonStop.Enabled = true;
mySnake = new Snake(mySnakeColor);
foreach (Label lbl in mySnake.GetSnake())
{
this.panelGame.Controls.Add(lbl);
}
myFood = new Food(myFoodColor,new Point(100,100));
this.panelGame.Controls.Add(myFood.FoodCeil);
this.myFood.CopyFoodCeil(currentfood, this.myFood.FoodCeil);
this.timerSnakeSpeed.Enabled = true;//启动计时器
}
//画蛇函数
private void DrawSnake(Snake _newsnake)
{
foreach (Label lbl in _newsnake.GetSnake())
{
this.panelGame.Controls.Add(lbl);
}
}
//定义一个Label存放当前食物
Label currentfood = new Label();
//发放食物
private void PutFood()
{
Random randfood = new Random();
int newfoodx = randfood.Next(35);
int newfoody = randfood.Next(28);
Label newfood = new Label();
this.myFood.CopyFoodCeil(newfood, currentfood);
newfood.Left = newfoodx*10;
newfood.Top = newfoody*10;
this.panelGame.Controls.Remove(this.myFood.FoodCeil);
this.panelGame.Controls.Add(newfood);
this.myFood.CopyFoodCeil(this.myFood.FoodCeil, newfood);
this.myFood.CopyFoodCeil(currentfood, newfood);
}
//画食物函数
private void DrawFood(Label newfood)
{
this.panelGame.Controls.Add(newfood);
}
//移除食物
private void RemoveFood(Label oldfood)
{
this.panelGame.Controls.Remove(oldfood);
}
//计时器函数
private void timerSnakeSpeed_Tick(object sender, EventArgs e)
{
mySnake.EatFood(this.myFood.FoodCeil);
mySnake.Move(this.panelGame,this.myFood.FoodCeil);
DrawSnake(mySnake);
if (this.mySnake.IsDead)
{
this.buttonStart.Enabled = true;
this.buttonStop.Enabled = false;
this.timerSnakeSpeed.Enabled = false;
ClearColor();
ClearDirection();
this.textBoxScore.Text = "";
this.panelGame.Controls.Clear();
this.panelGame.BackgroundImage = Resources.gameover1;
}
if (mySnake.Flag)
{
PutFood();
mySnake.Flag = false;
}
this.textBoxScore.Text = ((mySnake.SnakeLength - 5) * 10).ToString();
}
//清除水平选择标志
private void ClearFlag()
{
this.低水平ToolStripMenuItem.Checked = false;
this.普通水平ToolStripMenuItem.Checked = false;
this.高水平ToolStripMenuItem.Checked = false;
}
//选择普通水平
private void 普通水平ToolStripMenuItem_Click(object sender, EventArgs e)
{
ClearFlag();
this.普通水平ToolStripMenuItem.Checked = true ;
this.timerSnakeSpeed.Interval = 300;
}
private void 高水平ToolStripMenuItem_Click(object sender, EventArgs e)
{
ClearFlag();
this.高水平ToolStripMenuItem.Checked = true;
this.timerSnakeSpeed.Interval = 200;
}
private void 低水平ToolStripMenuItem_Click(object sender, EventArgs e)
{
ClearFlag();
this.低水平ToolStripMenuItem.Checked = true;
this.timerSnakeSpeed.Interval = 400;
}
//按键处理程序
private void FormSnakeGame_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 'a' || e.KeyChar == 'A')
{
this.mySnake.SnakeDirection=(this.mySnake.SnakeDirection==Direction.Right?Direction.Right:Direction.Left);
ClearColor();
this.buttonKeyA.BackColor = Color.Blue;
}
else if (e.KeyChar == 'd' || e.KeyChar == 'D')
{
this.mySnake.SnakeDirection = (this.mySnake.SnakeDirection == Direction.Left ? Direction.Left : Direction.Right);
ClearColor();
this.buttonKeyD.BackColor = Color.Blue;
}
else if (e.KeyChar == 'w' || e.KeyChar == 'W')
{
this.mySnake.SnakeDirection = (this.mySnake.SnakeDirection == Direction.Down ? Direction.Down : Direction.Up);
ClearColor();
this.buttonKeyW.BackColor = Color.Blue;
}
else if (e.KeyChar == 's' || e.KeyChar == 'S')
{
this.mySnake.SnakeDirection = (this.mySnake.SnakeDirection == Direction.Up ? Direction.Up : Direction.Down);
ClearColor();
this.buttonKeyS.BackColor = Color.Blue;
}
else
{
e.Handled = true;
}
}
//W键按下
private void buttonKeyW_Click(object sender, EventArgs e)
{
this.mySnake.SnakeDirection = (this.mySnake.SnakeDirection == Direction.Down ? Direction.Down : Direction.Up);
ClearColor();
this.buttonKeyW.BackColor = Color.Blue;
}
//A键按下
private void buttonKeyA_Click(object sender, EventArgs e)
{
this.mySnake.SnakeDirection = (this.mySnake.SnakeDirection == Direction.Right ? Direction.Right : Direction.Left);
ClearColor();
this.buttonKeyA.BackColor = Color.Blue;
}
//S键按下
private void buttonKeyS_Click(object sender, EventArgs e)
{
this.mySnake.SnakeDirection = (this.mySnake.SnakeDirection == Direction.Up ? Direction.Up : Direction.Down);
ClearColor();
this.buttonKeyS.BackColor = Color.Blue;
}
//D键按下
private void buttonKeyD_Click(object sender, EventArgs e)
{
this.mySnake.SnakeDirection = (this.mySnake.SnakeDirection == Direction.Left ? Direction.Left : Direction.Right);
ClearColor();
this.buttonKeyD.BackColor = Color.Blue;
}
//清除方向键背景颜色
private void ClearColor()
{
this.buttonKeyW.BackColor = System.Windows.Forms.Button.DefaultBackColor;
this.buttonKeyA.BackColor = System.Windows.Forms.Button.DefaultBackColor;
this.buttonKeyS.BackColor = System.Windows.Forms.Button.DefaultBackColor;
this.buttonKeyD.BackColor = System.Windows.Forms.Button.DefaultBackColor;
}
//方向键不可用
private void ClearDirection()
{
this.buttonKeyA.Enabled = false;
this.buttonKeyW.Enabled = false;
this.buttonKeyD.Enabled = false;
this.buttonKeyS.Enabled = false;
}
//方向键可用
private void EnableDirection()
{
this.buttonKeyA.Enabled = true;
this.buttonKeyW.Enabled = true;
this.buttonKeyD.Enabled = true;
this.buttonKeyS.Enabled = true;
}
}
}
上面简单的介绍了一下贪吃蛇的编程,大家相互交流,呵呵....