这篇文章主要为大家分析了c#贪吃蛇游戏的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
今天无聊突发奇想做个贪吃蛇,虽然网上很多这东西了,不过自己写的感觉还行吧
贪吃蛇分析
游戏规则:
1、蛇起始长度5,每吃一个食物增加1,最大15过关
2、蛇用蓝色表示,食物用绿色,障碍物用黑色
3、当蛇碰到自己、墙壁、障碍物则游戏失败
4、方向键控制蛇的移动方向,蛇不可反方向移动,如正在向上移动,不能马上向下,只能向左、右、上运动
5、每过关一次速度提升一次
大概思路:
1、地图用网格的形式表示,蛇由方格组成,保存在list中
2、1中提到了方格,方格保存的内容有,颜色,坐标,是否可以通过,是否是食物
3、向前移动一次,将前面方格添加进蛇列表中,将列表最后一个移除,若为前方格子为食物,则不移除最后一个
4、使用while死循环来做整个移动
5、空格键为加速键,通过修改while循环sleep时间来实现加速
包括了3个类一个主窗体,分别是node(用来表示方格)、map(用来表示地图)、serpent(用来表示蛇),另外一个主窗体。下面依次把代码贴上,基本上每个方法都有注释
代码1:
using system;
using system.collections.generic;
using system.text;
using system.drawing;
namespace engorgeserpent
{
/// <summary>
/// 节点
/// </summary>
class node
{
#region 字段
private int x;
private int y;
private int width = 10;
private bool isfood = false;
private bool ispass = true;//是否可通过
private color bgcolor = color.fromargb(224, 224, 224);
private color foodcolor = color.green;
private color hindercolor = color.black;
private color thiscolor;
private color serpentcolor = color.chocolate;
#endregion
/// <summary>
/// 设置食物参数
/// </summary>
/// <param name="_isfood"></param>
public void setfood(bool _isfood)
{
isfood = _isfood;
if (_isfood)
{
thiscolor = foodcolor;
}
else
{
thiscolor = bgcolor;
}
}
/// <summary>
/// 设置障碍物参数
/// </summary>
/// <param name="_ishinder">是否为障碍物</param>
public void sethinder(bool _ishinder)
{
ispass =! _ishinder;
if (_ishinder)
{
thiscolor = hindercolor;
}
else
{
thiscolor = bgcolor;
}
}
/// <summary>
/// 设置蛇颜色
/// </summary>
/// <param name="_isserpent"></param>
public void setserpent(bool _isserpent)
{
ispass = !_isserpent;
if (_isserpent)
{
thiscolor = serpentcolor;
}
else
{
thiscolor = bgcolor;
}
}
#region 构造函数
public node()
{
thiscolor = bgcolor;
}
/// <summary>
/// 有参构造方法
/// </summary>
/// <param name="_x">相对x坐标</param>
/// <param name="_y">相对y坐标</param>
/// <param name="_width">边长</param>
/// <param name="_isfood">是否是食物</param>
/// <param name="_ispass">是否可通过</param>
public node(int _x, int _y, int _width, bool _isfood, bool _ispass)
{
thiscolor = bgcolor;
x = _x;
y = _y;
width = _width;
isfood = _isfood;
ispass = _ispass;
}
/// <summary>
/// 有参构造方法
/// </summary>
/// <param name="_x">相对x坐标</param>
/// <param name="_y">相对y坐标</param>
/// <param name="_width">边长</param>
public node(int _x, int _y, int _width)
{
x = _x;
y = _y;
width = _width;
}
/// <summary>
/// 有参构造方法
/// </summary>
/// <param name="_x">相对x坐标</param>
/// <param name="_y">相对y坐标</param>
public node(int _x, int _y)
{
x = _x;
y = _y;
}
#endregion
#region 属性
/// <summary>
/// 蛇颜色
/// </summary>
public color serpentcolor
{
get { return serpentcolor; }
}
/// <summary>
/// 背景色
/// </summary>
public color bgcolor
{
get { return bgcolor; }
}
/// <summary>
/// 食物颜色
/// </summary>
public color foodcolor
{
get { return foodcolor; }
}
/// <summary>
/// 障碍物颜色
/// </summary>
public color hindercolor
{
get { return hindercolor; }
}
/// <summary>
/// 当前颜色
/// </summary>
public color thiscolor
{
get { return thiscolor; }
set { thiscolor = value; }
}
/// <summary>
/// 获取或设置相对横坐标
/// </summary>
public int x
{
get { return x; }
set { x = value; }
}
/// <summary>
/// 获取或设置相对纵坐标
/// </summary>
public int y
{
get { return y; }
set { y = value; }
}
/// <summary>
/// 获取或设置节点边长
/// </summary>
public int width
{
get { return width; }
set { width = value; }
}
/// <summary>
/// 获取或设置是否为食物
/// </summary>
public bool isfood
{
get { return isfood; }
set { isfood = value; }
}
/// <summary>
/// 获取或设置是否可以通过
/// </summary>
public bool ispass
{
get { return ispass; }
set { ispass = value; }
}
#endregion
}
}
代码2:
using system;
using system.collections.generic;
using system.text;
using system.drawing;
namespace engorgeserpent
{
/// <summary>
/// 地图
/// </summary>
class map
{
/// <summary>
/// 节点数组
/// </summary>
private list<list<node>> _nodes;
private int rowcount;
private int comscount;
private color bgcolor = color.fromargb(224, 224, 224);
private system.windows.forms.control mappanel;
graphics g;
/// <summary>
/// 地图背景色 和node中背景色一致
/// </summary>
public color bgcolor
{
get { return bgcolor; }
}
/// <summary>
/// 构造方法
/// </summary>
/// <param name="rows">行数</param>
/// <param name="coms">列数</param>
public map(int rows, int coms, system.windows.forms.control c)
{
rowcount = rows;
comscount = coms;
mappanel = c;
g = c.creategraphics();
_nodes = new list<list<node>>();
for (int i = 0; i < rows; i++)//行
{
list<node> index = new list<node>();
for (int j = 0; j < coms; j++)
{
node node = new node(j, i);
index.add(node);
}
_nodes.add(index);
}
}
/// <summary>
/// 构造方法
/// </summary>
/// <param name="rows">行数</param>
/// <param name="coms">列数</param>
/// <param name="width">节点宽度</param>
public map(int rows, int coms, int width, system.windows.forms.control c)
{
rowcount = rows;
comscount = coms;
mappanel = c;
g = c.creategraphics();
_nodes = new list<list<node>>();
for (int i = 0; i < coms; i++)//行
{
list<node> index = new list<node>();
for (int j = 0; j < rows; j++)
{
node node = new node(j, i, width);
index.add(node);
}
_nodes.add(index);
}
}
/// <summary>
/// 重新加载地图
/// </summary>
public void resetmap()
{
for (int i = 0; i < comscount; i++)//行
{
for (int j = 0; j < rowcount; j++)
{
node node = getnode(i, j);
node.ispass = true;
node.isfood = false;
}
}
}
/// <summary>
/// 获得节点
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public node getnode(int x, int y)
{
return _nodes[y][x];
}
/// <summary>
/// 设置食物
/// </summary>
public void setfood()
{
solidbrush brush = null;
int _x, _y;
random r = new random();
while (true)
{
_x = r.next(0, rowcount);
_y = r.next(0, comscount);
if (_nodes[_x][_y].ispass)
{
break;
}
}
node nodeindex = _nodes[_x][_y];
nodeindex.setfood(true);
brush = new solidbrush(nodeindex.foodcolor);
rectanglef[] rects = { new rectanglef(nodeindex.x * nodeindex.width, nodeindex.y * nodeindex.width, nodeindex.width, nodeindex.width) };
g.fillrectangles(brush, rects);
}
/// <summary>
/// 设置障碍物
/// </summary>
/// <param name="list"></param>
public void sethinder(list<node> list)
{
solidbrush brush = null;
rectanglef[] rects = new rectanglef[list.count];
for (int i = 0; i < list.count; i++)
{
node _node = list[i];
_node.sethinder(true);
_node.ispass = false;
if (brush == null)
{
brush = new solidbrush(_node.hindercolor);
}
rectanglef r = new rectanglef(_node.x * _node.width, _node.y * _node.width, _node.width, _node.width);
rects[i] = r;
}
g.fillrectangles(brush, rects);
}
/// <summary>
/// 设置边界
/// </summary>
public void setborder()
{
//通过计算得出边界的个数是2(x+y-2)个方格
solidbrush brush = null;
int borders = 2 * (comscount + rowcount - 2);
rectanglef[] rects = new rectanglef[borders];
int indexcount = 0;
//添加顶部方格进rects列表中
for (int i = 0; i < rowcount; i++)
{
node _node = _nodes[i][0];
_node.sethinder(true);
if (brush == null)
{
brush = new solidbrush(_node.hindercolor);
}
rectanglef r = new rectanglef(_node.x * _node.width, _node.y * _node.width, _node.width, _node.width);
rects[indexcount] = r;
indexcount++;
}
//添加底部方格进rects列表中
for (int i = 0; i < rowcount; i++)
{
node _node = _nodes[i][comscount - 1];
_node.sethinder(true);
rectanglef r = new rectanglef(_node.x * _node.width, _node.y * _node.width, _node.width, _node.width);
rects[indexcount] = r;
indexcount++;
}
//添加左侧方格进列表,因为左侧最上面以及最下面的两个方格已经添加进去,这里不需要重复添加
for (int i = 1; i < comscount - 1; i++)
{
node _node = _nodes[0][i];
_node.sethinder(true);
rectanglef r = new rectanglef(_node.x * _node.width, _node.y * _node.width, _node.width, _node.width);
rects[indexcount] = r;
indexcount++;
}
//添加右侧方格进列表,因为右侧最上面以及最下面两个方格已经添加进去,这里不需要重复添加
for (int i = 1; i < comscount - 1; i++)
{
node _node = _nodes[rowcount - 1][i];
_node.sethinder(true);
rectanglef r = new rectanglef(_node.x * _node.width, _node.y * _node.width, _node.width, _node.width);
rects[indexcount] = r;
indexcount++;
}
g.fillrectangles(brush, rects);
}
}
}
代码3:
using system;
using system.collections.generic;
using system.text;
using system.drawing;
namespace engorgeserpent
{
/// <summary>
/// 蛇
/// </summary>
class serpent
{
private list<node> serpentlist = new list<node>();
private direction direction = direction.right;//运动方向
private int maxcount = 15;
private int mincount = 5;
private system.windows.forms.control mappanel;
graphics g;
/// <summary>
/// 设置蛇长度数据
/// </summary>
/// <param name="maxlength">最大长度</param>
/// <param name="minlength">最小长度</param>
public serpent(int maxlength, int minlength, system.windows.forms.control c)
{
maxcount = maxlength;
mincount = minlength;
mappanel = c;
g = mappanel.creategraphics();
}
/// <summary>
/// 初始化蛇
/// </summary>
public void initializeserpent()
{
solidbrush brush = null;
rectanglef[] rects = new rectanglef[mincount];
for (int i = 1; i < mincount; i++)
{
node indexnode = new node(i, 1);
indexnode.setserpent(true);//设置蛇颜色
serpentlist.insert(0, indexnode);
if (brush == null)
{
brush = new solidbrush(indexnode.serpentcolor);
}
rects[i] = new rectanglef(indexnode.x * indexnode.width, indexnode.y * indexnode.width, indexnode.width, indexnode.width);
}
g.fillrectangles(brush, rects);
}
/// <summary>
/// 插入一个
/// </summary>
/// <param name="node"></param>
public void insertnode(node node)
{
serpentlist.insert(0, node);
node.setserpent(true);
solidbrush brush = new solidbrush(node.serpentcolor);
rectanglef rect = new rectanglef(node.x * node.width, node.y * node.width, node.width, node.width);
g.fillrectangle(brush, rect);
}
/// <summary>
/// 移除尾巴
/// </summary>
/// <param name="node"></param>
public void removenode()
{
node node = serpentlist[serpentlist.count - 1];
serpentlist.remove(node);
node.setserpent(false);
solidbrush brush = new solidbrush(node.bgcolor);
rectanglef rect = new rectanglef(node.x * node.width, node.y * node.width, node.width, node.width);
g.fillrectangle(brush, rect);
}
/// <summary>
/// 获取蛇头
/// </summary>
/// <returns>蛇头方格</returns>
public node getserpenthead()
{
return serpentlist[0];
}
/// <summary>
/// 蛇是否最长
/// </summary>
/// <returns></returns>
public bool ismax()
{
if (serpentlist.count == maxcount)
return true;
else
return false;
}
/// <summary>
/// 蛇运动方向
/// </summary>
public direction direction
{
get { return direction; }
set { direction = value; }
}
}
/// <summary>
/// 运动方向
/// </summary>
public enum direction
{
left,
up,
right,
down
}
}
代码4:
using system;
using system.collections.generic;
using system.componentmodel;
using system.data;
using system.drawing;
using system.text;
using system.windows.forms;
using system.threading;
namespace engorgeserpent
{
public partial class mainform : form
{
public mainform()
{
initializecomponent();
}
list<list<node>> maplist = new list<list<node>>();
map map;
serpent serpent;
graphics g;
int level = 1;
/// <summary>
/// 运行线程
/// </summary>
thread work_thread = null;
/// <summary>
/// 运行线程监控值
/// </summary>
bool iswork = false;
int sleeptime = 1000;
int thissleeptime;
private void mainform_load(object sender, eventargs e)
{
g = this.panel1.creategraphics();
map = new map(40, 30, this.panel1);//这里可以对画布进行下大小设置 此处偷懒省略
loadmaplist();//加载障碍物列表
}
/// <summary>
/// 默认将地图设置为30*40
/// </summary>
private void setmap()
{
map.resetmap();
g.clear(map.bgcolor);
map.setborder();//设置边界
list<node> hiderlist = gethider();//获取障碍物列表
map.sethinder(hiderlist);//设置障碍物
setserpent();//初始化蛇
}
/// <summary>
/// 设置蛇
/// </summary>
private void setserpent()
{
serpent = new serpent(15, 5, this.panel1);
serpent.initializeserpent();//初始化蛇
}
/// <summary>
/// 获取地图障碍物列表 以增加不同级别难度
/// </summary>
private void loadmaplist()
{
//目前分为5个级别
//第一级别
list<node> hiderlist1 = new list<node>();
for (int i = 15; i < 25; i++)
{
hiderlist1.add(map.getnode(i, 15));
hiderlist1.add(map.getnode(15, i));
}
maplist.add(hiderlist1);
//第二级别
list<node> hiderlist2 = new list<node>();
for (int i = 7; i < 25; i++)
{
hiderlist2.add(map.getnode(i, 15));
hiderlist2.add(map.getnode(15, i));
}
maplist.add(hiderlist2);
//第三级别
list<node> hiderlist3 = new list<node>();
for (int i = 7; i < 25; i++)
{
hiderlist3.add(map.getnode(i, 15));
hiderlist3.add(map.getnode(15, i));
hiderlist3.add(map.getnode(i, 25));
}
maplist.add(hiderlist3);
//第四级别
list<node> hiderlist4 = new list<node>();
for (int i = 7; i < 25; i++)
{
hiderlist4.add(map.getnode(i, 25));
hiderlist4.add(map.getnode(i, 15));
hiderlist4.add(map.getnode(15, i));
hiderlist4.add(map.getnode(i, 7));
}
maplist.add(hiderlist4);
//第五级别
list<node> hiderlist5 = new list<node>();
for (int i = 7; i < 25; i++)
{
hiderlist5.add(map.getnode(i, 25));
hiderlist5.add(map.getnode(i, 15));
hiderlist5.add(map.getnode(15, i));
hiderlist5.add(map.getnode(i, 7));
hiderlist5.add(map.getnode(i, 35));
}
for (int i = 12; i < 20; i++)
{
hiderlist5.add(map.getnode(7, i));
hiderlist5.add(map.getnode(25, i));
}
maplist.add(hiderlist5);
}
/// <summary>
/// 获取障碍物列表
/// </summary>
/// <returns></returns>
private list<node> gethider()
{
//这里可以添加多个地图,当级别改变时需要重新加载
return maplist[level - 1];
}
/// <summary>
/// 重置地图
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnresetmap_click(object sender, eventargs e)
{
iswork = false;
btnstop.enabled = false;
button3.enabled = false;
button2.enabled = true;
//map.resetmap();
setmap();
}
/// <summary>
/// 运行
/// </summary>
private void work()
{
map.setfood();//设置食物
while (iswork)
{
node node_index;
node serpenthead = serpent.getserpenthead();
switch (serpent.direction)
{
case direction.left:
node_index = map.getnode(serpenthead.x - 1, serpenthead.y);
break;
case direction.right:
node_index = map.getnode(serpenthead.x + 1, serpenthead.y);
break;
case direction.up:
node_index = map.getnode(serpenthead.x, serpenthead.y - 1); break;
default:
node_index = map.getnode(serpenthead.x, serpenthead.y + 1);
break;
}
serpentstate index_move = serpentmove(node_index);
if (index_move == serpentstate.error)//游戏结束
{
iswork = false;
//map.resetmap();
messagebox.show("游戏结束!", "提示", messageboxbuttons.ok, messageboxicon.information);
sleeptime = 1000;
level = 1;
thissleeptime = sleeptime;
lbllevel.begininvoke(new methodinvoker(delegate()
{
btnstop.enabled = false;
button3.enabled = false;
button2.enabled = true;
lbllevel.text = "1";
lblcount.text = "5";
}));
}
else if (index_move == serpentstate.nextlevel)
{
iswork = false;
this.lblcount.begininvoke(new methodinvoker(delegate()
{
level += 1;
lbllevel.text = level.tostring();
lblcount.text = "5";
}));
sleeptime = sleeptime / 2;
thissleeptime = sleeptime;
setmap();//重置地图
}
else
{
thread.sleep(thissleeptime);
}
}
map.resetmap();
}
/// <summary>
/// 开始
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_click(object sender, eventargs e)
{
iswork = false;
btnstop.enabled = false;
button3.enabled = false;
button2.enabled = true;
//map.resetmap();
setmap();
thissleeptime = sleeptime;
this.panel1.focus();
iswork = true;
this.btnstop.enabled = true;
this.button3.enabled = true;
button2.enabled = false;
work_thread = new thread(new threadstart(work));
work_thread.isbackground = true;
work_thread.start();
}
private void mainform_keydown(object sender, keyeventargs e)
{
if (e.keycode == keys.right)
{
if (serpent.direction != direction.left)
serpent.direction = direction.right;
}
else if (e.keycode == keys.left)
{
if (serpent.direction != direction.right)
serpent.direction = direction.left;
}
else if (e.keycode == keys.up)
{
if (serpent.direction != direction.down)
serpent.direction = direction.up;
}
else if (e.keycode == keys.down)
{
if (serpent.direction != direction.up)
serpent.direction = direction.down;
}
else if (e.keycode == keys.space)
{
thissleeptime = sleeptime / 2;
}
else if (e.keycode == keys.escape)
{
if (iswork)
{
this.button3.text = "继续";
iswork = false;
}
}
}
/// <summary>
/// 暂停
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_click(object sender, eventargs e)
{
if (!iswork)
{
this.button3.text = "暂停";
iswork = true;
work_thread = new thread(new threadstart(work));
work_thread.isbackground = true;
work_thread.start();
}
else
{
this.button3.text = "继续";
iswork = false;
}
}
/// <summary>
/// 退出
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button4_click(object sender, eventargs e)
{
this.close();
}
private void mainform_formclosing(object sender, formclosingeventargs e)
{
iswork = false;
application.exit();
system.diagnostics.process.getcurrentprocess().kill();
}
private void btnstop_click(object sender, eventargs e)
{
// map.resetmap();
btnstop.enabled = false;
button3.enabled = false;
button2.enabled = true;
iswork = false;
work_thread.abort();
setmap();
}
/// <summary>
/// 移动
/// </summary>
/// <param name="node">将要移动到的节点</param>
/// <returns>返回状态</returns>
private serpentstate serpentmove(node node)
{
if (!node.ispass)
{
return serpentstate.error;
}
serpent.insertnode(node);
if (!node.isfood)
{
//不是食物,则移除最后一个节点
serpent.removenode();
}
else
{
lblcount.begininvoke(new methodinvoker(delegate()
{
this.lblcount.text = (convert.toint32(this.lblcount.text.trim()) + 1).tostring();
}));
map.setfood();//设置食物
}
if (serpent.ismax())
{
return serpentstate.nextlevel;
}
return serpentstate.moving;
}
private void mainform_keyup(object sender, keyeventargs e)
{
if (e.keycode == keys.space)
{
thissleeptime = sleeptime;
}
}
private void combobox1_selectedindexchanged(object sender, eventargs e)
{
int index = 1;
int index_count = convert.toint32(combobox1.text);
for (int i = 1; i < index_count; i++)
{
index = index * 2;
}
level = index_count;
sleeptime = 1000 / index;
thissleeptime = sleeptime;
btnstop.enabled = false;
button3.enabled = false;
button2.enabled = true;
iswork = false;
setmap();
lblcount.text = "5";
lbllevel.text = index_count.tostring();
serpent.direction = direction.right;
}
private void checkbox1_click(object sender, eventargs e)
{
combobox1.enabled = this.checkbox1.checked;
}
}
public enum serpentstate
{
moving,
nextlevel,
error
}
}
主界面
以上就是c#实现贪吃蛇游戏的示例代码分析的详细内容。