1个回答
2016-10-24 · 百度知道合伙人官方认证企业
兄弟连教育
兄弟连教育成立于2006年,11年来专注IT职业教育,是国内专业的IT技术培训学校。2016年成功挂牌新三板(股票代码:839467)市值过亿。开设专注程序员培训专注php、Java、UI、云计算、Python、HTML5、
向TA提问
关注
展开全部
先介绍用到的技术:
GDI+
定义类
枚举
因为C#是一门面向对象的语言,我们不用把所有代码都写在一个窗体上,应该有一个分层思想(界面还界面,数据处理还数据处理),如果还要网上对战的话,搞个三层吧(界面层,数据处理或逻辑层,Socket层),这样不仅方便维护,还为后面添加新Idea会容易一点。
废话少讲,现在开始
在编写游戏代码之前,先想一想,贪食蛇里有什么呢?
蛇,这是必要的。
食物,这也是必要的。
蛇应该是怎样的一条蛇?
不断向一个方向移动,那就是有方向了。方向可以用整数代表,不过为了方便以后编写代码,
还是定义一个枚举好一点。还要会移动。还要有一个位置。还要有一个速度
蛇有一个长度,也要记录下它各个身体的位置,因为蛇吃食物会不断加长,所以他的身体数量(即长度)是会变化的,所以最好是定义一个泛型List<Point>来记录身体上的所有位置。
蛇怎样才能移动,原理是这样,后面一个蛇身替代头部的位置,然后头部向前走一步。
食物呢?我们不搞传统的贪吃蛇,食物可以是多个的,也应该有不同类型,吃到不同类型的食物,蛇会作出相应的变化。也就是说,食物也有类型,所以定义一个enum为食物类型
为了搞搞新意思,加上一个蛇的速度,蛇吃到快的食物,会加快速度,吃到慢的食物,会减慢速度。所以定义了速度
枚举一般写在一个Common.cs里
总的来说,定义类应该是这样:
蛇:方向(枚举),状态(枚举),移动(方法),位置(头部位置),长度,各身体的位置,速度
食物:位置,类型
不说太多,我将会在代码里写详尽的注释。大家应该看得明白。
代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace snake
{
public enum SnakeDirection
{
Up, Down, Left, Right
}
public enum SnakeState
{
Normal = 50, Fast = 20, Low = 100
}
public enum FoodType
{
Normal, Fast, Slow, Long, Short, LENGTH
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace snake
{
public class Snake
{
public Snake(Point headLocation, int snakeLength, SnakeDirection direction)
{
bodiesLocation = new List<Point>();
bodiesLocation.Add(headLocation);
for (int i = 0; i < snakeLength; i++)
{
bodiesLocation.Add(new Point(-1, -1));
}
this.direction = direction;
this.speed = (int)SnakeState.Normal;
}
/// <summary>向前移动一格</summary>
public void Run()
{
//从蛇尾开始,前面身体的位置替代后面的身体位置
for (int i = bodiesLocation.Count - 1; i >= 1; i--)
{
bodiesLocation[i] = bodiesLocation[i - 1];
}
//头部向前走一步
Point head = bodiesLocation[0];
switch (direction)
{
case SnakeDirection.Up:
head = new Point(head.X, head.Y - 1);
break;
case SnakeDirection.Down:
head = new Point(head.X, head.Y + 1);
break;
case SnakeDirection.Left:
head = new Point(head.X - 1, head.Y);
break;
case SnakeDirection.Right:
head = new Point(head.X + 1, head.Y);
break;
}
bodiesLocation[0] = head; //因为Point是Struct,是值类型,所以要赋值过来
}
/// <summary>移动方向</summary>
public SnakeDirection Direction
{
get { return direction; }
set { direction = value; }
}
/// <summary>状态</summary>
public SnakeState State
{
get { return state; }
set
{
state = value;
speed = (int)state; //改变蛇的速度
}
}
/// <summary>头部位置</summary>
public Point HeadLocation
{
get { return bodiesLocation[0]; }
}
/// <summary>蛇身体</summary>
public List<Point> BodiesLocation
{
get { return bodiesLocation; }
}
/// <summary>蛇的速度</summary>
public int Speed
{
get { return speed; }
set { speed = value; }
}
/// <summary>移动方向</summary>
private SnakeDirection direction;
/// <summary>状态</summary>
private SnakeState state;
/// <summary>蛇身体的位置</summary>
private List<Point> bodiesLocation;
/// <summary>蛇的速度</summary>
private int speed = (int)SnakeState.Normal;
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace snake
{
public class Food
{
public Food(Point location,FoodType type)
{
this.location = location;
this.type = type;
}
public Food() { }
/// <summary>食物类型</summary>
public FoodType Type
{
get { return type; }
set { type = value; }
}
/// <summary>位置</summary>
public Point Location
{
get { return location; }
set { location = value; }
}
/// <summary>食物类型</summary>
private FoodType type;
/// <summary>位置</summary>
private Point location;
}
}
为了方便维护,定义了一个类GameManager,专门处理游戏的逻辑,运算之类的。
首先这个类相当于一个游戏,所以蛇,食物是必不可少的,
游戏一定要有一个画面的,所以要定义一个Draw()方法把画面画出来
要随机产生食物,所以要定义一个produceFood()方法
蛇要吃到食物,所以要定义一个SnakeEatFood方法
还要判断游戏是否结束,所以要定义一个IsGameOver方法
因为GameManager相当于逻辑层,snake不对外开放,所以定义了两个属性,只返回snake的两个属性,这样方便把数据显示在界面上。因为蛇是在GameManager里的,不会在窗体出现,所以定义了一个方法SnakeRun(),调用snake.Run()就OK了。
还要定义很多常量参数,详细的请看代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace snake
{
public class GameManager
{
/// <summary>
/// 产生食物
/// </summary>
public void ProduceFood()
{
Random rnd = new Random();
//随机产生一个食物
Point newFoodLoaction; //新产生的食物位置
bool flag = false; //是否应该重新产生食物
do
{
newFoodLoaction = new Point(rnd.Next(FIELD_WIDTH), rnd.Next(FIELD_HEIGHT));
//如果食物在蛇的身上,则重新产生食物位置
foreach (Point snakeP in snake.BodiesLocation)
{
if (newFoodLoaction == snakeP)
{
flag = true;
break;
}
}
} while (flag);
Food f = new Food(newFoodLoaction, (FoodType)rnd.Next((int)FoodType.LENGTH));
foods.Add(f);
}
/// <summary>
/// 蛇吃食物
/// </summary>
public void SnakeEatFood()
{
foreach (Food food in foods)
{
//如果蛇的头部碰到食物
if (snake.HeadLocation == food.Location)
{
foods.Remove(food); //删去食物
//蛇吃食物的效果
Random rnd = new Random();
int r;
switch (food.Type)
{
case FoodType.Fast:
//状态为快
snake.State = SnakeState.Fast;
break;
case FoodType.Slow:
//状态为慢
snake.State = SnakeState.Low;
break;
case FoodType.Normal:
//速度变回正常
snake.State = SnakeState.Normal;
break;
case FoodType.Short:
//随机缩短
if (snake.BodiesLocation.Count > 1) r = 0;
else if (snake.BodiesLocation.Count < 5) r = 1;
else r = rnd.Next(5);
for (int i = 0; i < r; i++)
{
snake.BodiesLocation.RemoveAt(snake.BodiesLocation.Count - 1);
}
break;
case FoodType.Long:
//随机加长
r = rnd.Next(5);
for (int i = 0; i < r; i++)
{
snake.BodiesLocation.Add(new Point(-1, -1));
}
break;
//可以在这里添加更多吃下食物后蛇的变化
}
break; //--break foreach
}
}
}
因为所有逻辑方面的东西都放在GameManager里,所以,就算界面改N次都好,都可以轻松实现
窗体方面,主要定义两个Timer,一个用于产生食物,一个用于控制蛇的运动。
还有别忘了每次更新数据后,要调用控件的Invalidate()方法更新画面哦。不然什么都不会动。
最后,菜单什么的,随便你怎样加。
GDI+
定义类
枚举
因为C#是一门面向对象的语言,我们不用把所有代码都写在一个窗体上,应该有一个分层思想(界面还界面,数据处理还数据处理),如果还要网上对战的话,搞个三层吧(界面层,数据处理或逻辑层,Socket层),这样不仅方便维护,还为后面添加新Idea会容易一点。
废话少讲,现在开始
在编写游戏代码之前,先想一想,贪食蛇里有什么呢?
蛇,这是必要的。
食物,这也是必要的。
蛇应该是怎样的一条蛇?
不断向一个方向移动,那就是有方向了。方向可以用整数代表,不过为了方便以后编写代码,
还是定义一个枚举好一点。还要会移动。还要有一个位置。还要有一个速度
蛇有一个长度,也要记录下它各个身体的位置,因为蛇吃食物会不断加长,所以他的身体数量(即长度)是会变化的,所以最好是定义一个泛型List<Point>来记录身体上的所有位置。
蛇怎样才能移动,原理是这样,后面一个蛇身替代头部的位置,然后头部向前走一步。
食物呢?我们不搞传统的贪吃蛇,食物可以是多个的,也应该有不同类型,吃到不同类型的食物,蛇会作出相应的变化。也就是说,食物也有类型,所以定义一个enum为食物类型
为了搞搞新意思,加上一个蛇的速度,蛇吃到快的食物,会加快速度,吃到慢的食物,会减慢速度。所以定义了速度
枚举一般写在一个Common.cs里
总的来说,定义类应该是这样:
蛇:方向(枚举),状态(枚举),移动(方法),位置(头部位置),长度,各身体的位置,速度
食物:位置,类型
不说太多,我将会在代码里写详尽的注释。大家应该看得明白。
代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace snake
{
public enum SnakeDirection
{
Up, Down, Left, Right
}
public enum SnakeState
{
Normal = 50, Fast = 20, Low = 100
}
public enum FoodType
{
Normal, Fast, Slow, Long, Short, LENGTH
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace snake
{
public class Snake
{
public Snake(Point headLocation, int snakeLength, SnakeDirection direction)
{
bodiesLocation = new List<Point>();
bodiesLocation.Add(headLocation);
for (int i = 0; i < snakeLength; i++)
{
bodiesLocation.Add(new Point(-1, -1));
}
this.direction = direction;
this.speed = (int)SnakeState.Normal;
}
/// <summary>向前移动一格</summary>
public void Run()
{
//从蛇尾开始,前面身体的位置替代后面的身体位置
for (int i = bodiesLocation.Count - 1; i >= 1; i--)
{
bodiesLocation[i] = bodiesLocation[i - 1];
}
//头部向前走一步
Point head = bodiesLocation[0];
switch (direction)
{
case SnakeDirection.Up:
head = new Point(head.X, head.Y - 1);
break;
case SnakeDirection.Down:
head = new Point(head.X, head.Y + 1);
break;
case SnakeDirection.Left:
head = new Point(head.X - 1, head.Y);
break;
case SnakeDirection.Right:
head = new Point(head.X + 1, head.Y);
break;
}
bodiesLocation[0] = head; //因为Point是Struct,是值类型,所以要赋值过来
}
/// <summary>移动方向</summary>
public SnakeDirection Direction
{
get { return direction; }
set { direction = value; }
}
/// <summary>状态</summary>
public SnakeState State
{
get { return state; }
set
{
state = value;
speed = (int)state; //改变蛇的速度
}
}
/// <summary>头部位置</summary>
public Point HeadLocation
{
get { return bodiesLocation[0]; }
}
/// <summary>蛇身体</summary>
public List<Point> BodiesLocation
{
get { return bodiesLocation; }
}
/// <summary>蛇的速度</summary>
public int Speed
{
get { return speed; }
set { speed = value; }
}
/// <summary>移动方向</summary>
private SnakeDirection direction;
/// <summary>状态</summary>
private SnakeState state;
/// <summary>蛇身体的位置</summary>
private List<Point> bodiesLocation;
/// <summary>蛇的速度</summary>
private int speed = (int)SnakeState.Normal;
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace snake
{
public class Food
{
public Food(Point location,FoodType type)
{
this.location = location;
this.type = type;
}
public Food() { }
/// <summary>食物类型</summary>
public FoodType Type
{
get { return type; }
set { type = value; }
}
/// <summary>位置</summary>
public Point Location
{
get { return location; }
set { location = value; }
}
/// <summary>食物类型</summary>
private FoodType type;
/// <summary>位置</summary>
private Point location;
}
}
为了方便维护,定义了一个类GameManager,专门处理游戏的逻辑,运算之类的。
首先这个类相当于一个游戏,所以蛇,食物是必不可少的,
游戏一定要有一个画面的,所以要定义一个Draw()方法把画面画出来
要随机产生食物,所以要定义一个produceFood()方法
蛇要吃到食物,所以要定义一个SnakeEatFood方法
还要判断游戏是否结束,所以要定义一个IsGameOver方法
因为GameManager相当于逻辑层,snake不对外开放,所以定义了两个属性,只返回snake的两个属性,这样方便把数据显示在界面上。因为蛇是在GameManager里的,不会在窗体出现,所以定义了一个方法SnakeRun(),调用snake.Run()就OK了。
还要定义很多常量参数,详细的请看代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace snake
{
public class GameManager
{
/// <summary>
/// 产生食物
/// </summary>
public void ProduceFood()
{
Random rnd = new Random();
//随机产生一个食物
Point newFoodLoaction; //新产生的食物位置
bool flag = false; //是否应该重新产生食物
do
{
newFoodLoaction = new Point(rnd.Next(FIELD_WIDTH), rnd.Next(FIELD_HEIGHT));
//如果食物在蛇的身上,则重新产生食物位置
foreach (Point snakeP in snake.BodiesLocation)
{
if (newFoodLoaction == snakeP)
{
flag = true;
break;
}
}
} while (flag);
Food f = new Food(newFoodLoaction, (FoodType)rnd.Next((int)FoodType.LENGTH));
foods.Add(f);
}
/// <summary>
/// 蛇吃食物
/// </summary>
public void SnakeEatFood()
{
foreach (Food food in foods)
{
//如果蛇的头部碰到食物
if (snake.HeadLocation == food.Location)
{
foods.Remove(food); //删去食物
//蛇吃食物的效果
Random rnd = new Random();
int r;
switch (food.Type)
{
case FoodType.Fast:
//状态为快
snake.State = SnakeState.Fast;
break;
case FoodType.Slow:
//状态为慢
snake.State = SnakeState.Low;
break;
case FoodType.Normal:
//速度变回正常
snake.State = SnakeState.Normal;
break;
case FoodType.Short:
//随机缩短
if (snake.BodiesLocation.Count > 1) r = 0;
else if (snake.BodiesLocation.Count < 5) r = 1;
else r = rnd.Next(5);
for (int i = 0; i < r; i++)
{
snake.BodiesLocation.RemoveAt(snake.BodiesLocation.Count - 1);
}
break;
case FoodType.Long:
//随机加长
r = rnd.Next(5);
for (int i = 0; i < r; i++)
{
snake.BodiesLocation.Add(new Point(-1, -1));
}
break;
//可以在这里添加更多吃下食物后蛇的变化
}
break; //--break foreach
}
}
}
因为所有逻辑方面的东西都放在GameManager里,所以,就算界面改N次都好,都可以轻松实现
窗体方面,主要定义两个Timer,一个用于产生食物,一个用于控制蛇的运动。
还有别忘了每次更新数据后,要调用控件的Invalidate()方法更新画面哦。不然什么都不会动。
最后,菜单什么的,随便你怎样加。
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询