Snake类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace SnakeGame
{
public class Snake
{
public int SnkWidth = 16;//蛇的每个点的宽度
public const int SNAKE_MAX_LENGTH = 500;//最大长度
public Point[] SnkLct=new Point[SNAKE_MAX_LENGTH];
public int SnkLen;//蛇的长度
public byte SnkDrt = 2;//方向 1上 2右 3下 4 左
///
/// 蛇的属性初始化
///
public void SnakeInit()
{
int start = 0;
SnkLen = 5;
for (int i = 5; i >= 1; i--)
{
SnkLct[i].X = start;
SnkLct[i].Y = 32;
start += SnkWidth;
}
SnkDrt = 2;//初始方向
}
///
/// 判断蛇头是否撞到蛇尾
///
///
public bool CheckSnakeHeadInSnakeBody()
{
return CheckInSnakeBody(SnkLct[1].X, SnkLct[1].Y, 2);
}
///
/// 检查输入的坐标是否在蛇的身上
///
///
///
///
///
public bool CheckInSnakeBody(int x, int y, int snkHead)
{
for (int i = snkHead; i <= SnkLen; i++)
{
if (x == SnkLct[i].X && y == SnkLct[i].Y)
{
return true;
}
}
return false;
}
///
/// 判断是否撞墙
///
///
public bool CheckSnakeBodyInFrm()
{
if (SnkLct[1].X >= 560 || SnkLct[1].Y >= 512 || SnkLct[1].X < 0 || SnkLct[1].Y < 32)
{
return true;
}
else
{
return false;
}
}
///
/// 判断是否吃到食物
///
///
///
public bool EatedFood(Point FoodLct)
{
if (SnkLct[1].X == FoodLct.X && SnkLct[1].Y == FoodLct.Y)
{
if (SnkLen < SNAKE_MAX_LENGTH)
{
SnkLen++;
SnkLct[SnkLen].X=SnkLct[SnkLen - 1].X;
SnkLct[SnkLen].Y = SnkLct[SnkLen - 1].Y;
}
return true;
}
else
{
return false;
}
}
///
/// 蛇的控制前进
///
///
public void Forward(int drc)
{
Point tmp = new Point();
tmp.X = SnkLct[1].X;
tmp.Y = SnkLct[1].Y;
for (int i = SnkLen; i > 1; i--)
{
//蛇头动,把蛇头的坐标逐个后移(蛇身往蛇头方向位移)
SnkLct[i].X = SnkLct[i - 1].X;
SnkLct[i].Y = SnkLct[i - 1].Y;
}
switch (drc)
{
//根据设置的方向,计算蛇头的坐标
case 1:
SnkLct[1].X = tmp.X;
SnkLct[1].Y = tmp.Y - SnkWidth;
break;//上
case 2:
SnkLct[1].X = tmp.X + SnkWidth;
SnkLct[1].Y = tmp.Y;
break;//右
case 3:
SnkLct[1].X = tmp.X;
SnkLct[1].Y = tmp.Y + SnkWidth;
break;//下
case 4:
SnkLct[1].X = tmp.X - SnkWidth;
SnkLct[1].Y = tmp.Y;
break;//下
}
}
}
}
Game类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace SnakeGame
{
//经过了两层封装,先封装了蛇这个类,然后蛇以对象的形式在Game类中调用,在接口处只调用游戏类就行了。也是三层封装的思想。
//三层封装为:表现层、逻辑层、实体层
public class Game
{
public Point FoodLct = new Point();//缓存食物的坐标
public int score = 0;//得分
public bool pause;//暂停
public Snake snake = new Snake();
///
/// 游戏初始化
///
public void GameInit()
{
pause = false;
score = 0;
snake.SnakeInit();//初始化蛇
}
///
/// 随即显示食物
///
public void ShowFood()
{
Random rmd = new Random();
int x, y;
x = rmd.Next(0, 35) * snake.SnkWidth;
y = 32 + rmd.Next(0, 30) * snake.SnkWidth;
while (snake.CheckInSnakeBody(x, y, 1))
{
x = rmd.Next(0, 32) * snake.SnkWidth;
y = 32 + rmd.Next(0, 30) * snake.SnkWidth;
}
FoodLct.X = x;
FoodLct.Y = y;
}
///
/// 分数
///
///
public bool AddScore()
{
if (snake.EatedFood(FoodLct))
{
score += 10;
return true;
}
return false;
}
///
/// 判断游戏是否结束
///
///
public bool Dead()
{
return snake.CheckSnakeBodyInFrm() || snake.CheckSnakeHeadInSnakeBody();
}
}
}
主程序:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SnakeGame
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Game game = new Game();
///
/// 绘制一个方块
///
///
///
private void DrawShape(int x, int y)
{
Graphics g = CreateGraphics();
Pen pen = new Pen(Color.Green, 1);
SolidBrush brush = new SolidBrush(Color.GreenYellow);
g.DrawRectangle(pen, x, y, 15, 15);
g.FillRectangle(brush, x, y, 15,15);
}
///
/// 开始
///
///
///
private void tsmiStart_Click(object sender, EventArgs e)
{
tsmiPause.Enabled = true;
game.GameInit();
timerMove.Start();
game.ShowFood();
lblFood.Location = game.FoodLct;
}
///
/// 暂停
///
///
///
private void tsmiPause_Click(object sender, EventArgs e)
{
if (game.pause == false)
{
game.pause = true;
timerMove.Enabled = false;
}
else
{
game.pause = false;
timerMove.Enabled = true;
}
tsmiPause.Checked = game.pause;
}
///
/// 退出
///
///
///
private void tsmiStop_Click(object sender, EventArgs e)
{
Application.Exit();
}
///
/// 加载
///
///
///
private void Form1_Load(object sender, EventArgs e)
{
timerMove.Interval = 150;
tsmiPause.Enabled = false;
}
///
/// 时间事件
///
///
///
private void timerMove_Tick(object sender, EventArgs e)
{
if (game.score < 100)
{
timerMove.Interval = 150;
}
else if (game.score < 150)
{
timerMove.Interval = 100;
}
else
{
timerMove.Interval = 50;
}
Graphics g = CreateGraphics();
g.Clear(Color.DarkKhaki);//清除整个画面
game.snake.Forward(game.snake.SnkDrt);
for (int i = 1; i <= game.snake.SnkLen; i++)
{
DrawShape(game.snake.SnkLct[i].X, game.snake.SnkLct[i].Y);
}
if (game.AddScore())
{
game.ShowFood();
lblFood.Location = game.FoodLct;
}
this.Text = this.Text.Substring(0, this.Text.IndexOf(": ") + 9) + this.game.score.ToString();
if (game.Dead())
{
timerMove.Enabled = false;
tsmiPause.Enabled = false;
MessageBox.Show("游戏结束!\n" + "得分:" + game.score, "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
///
/// 方向键
///
///
///
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (game.pause == false)
{
string key = e.KeyCode.ToString();
switch (key)
{
//按上方向键 或小键盘的8键时,向上移动一单元格
case "Up":
{
//正在向下走时,不允许向上,下面相同
if (game.snake.SnkDrt != 3)
{
game.snake.SnkDrt = 1;
}
break;
}
case "Right":
{
if (game.snake.SnkDrt != 4)
{
game.snake.SnkDrt = 2;
}
break;
}
case "Down":
{
if (game.snake.SnkDrt != 1)
{
game.snake.SnkDrt = 3;
}
break;
}
case "Left":
{
if (game.snake.SnkDrt != 2)
{
game.snake.SnkDrt = 4;
}
break;
}
}
}
}
}
}
这个程序不仅实现了贪吃蛇游戏,也体现了面向对象封装的思想,即先封装“蛇”实体类,然后封装“游戏”逻辑类,最后在窗体中调用Game类,Game类调用Snake类,体现三层架构的思想:实体层、逻辑层、表现层。