【C#】贪吃蛇小游戏
自学了几天C#,尝试写了一个贪吃蛇小游戏,比较详细地做了注释,实现:
(1)贪吃蛇基本功能
(2)长按加速
(3)计分板
XAML代码及界面
C#代码
using System;
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;namespace 贪吃蛇
{/// /// MainWindow.xaml 的交互逻辑/// public partial class MainWindow : Window{DispatcherTimer timer = new DispatcherTimer();//适用于UI界面的计时器DispatcherTimer keytimer = new DispatcherTimer();//用于判定键盘长按//界面300*400const int SIDE = 10;//每个格子的边长int row;//行数int column;//列数int score;//得分Random rNumber = new Random();//随机数Border food = new Border();//食物Snake snake = new Snake();//生成一条蛇public MainWindow()//初始化即主程序{InitializeComponent();//初始化窗体内容//行列数生成row = 300 / SIDE;column = 400 / SIDE;score = 0;//分数初始为0//食物初始化food.Width = food.Height = SIDE;//食物大小food.CornerRadius = new CornerRadius(90);//通过边缘角度设置食物形状:圆形food.Background = new RadialGradientBrush(Colors.Black, Colors.Black);//食物颜色:黑色//生成第一颗食物Canvas.SetLeft(food, rNumber.Next(0, column - 4) * SIDE);Canvas.SetTop(food, rNumber.Next(0, row - 4) * SIDE);map.Children.Add(food);Canvas.SetZIndex(food,1);//设置食物所在层数//计时器设置timer.Interval = TimeSpan.FromMilliseconds(200);//设置计时器事件间隔,即界面刷新速度,直接设置timer.Start();//计时器启动timer.Tick += timer_Tick;//蛇位置初始化 Canvas.SetLeft(snake[0], 2 * SIDE);Canvas.SetTop(snake[0], 0); map.Children.Add(snake[0]);Canvas.SetZIndex(snake[0], 2);//设置蛇头所在层数Canvas.SetLeft(snake[1], 1 * SIDE); Canvas.SetTop(snake[1], 0); map.Children.Add(snake[1]);Canvas.SetLeft(snake[2], 0); Canvas.SetTop(snake[2], 0); map.Children.Add(snake[2]);//记得“map.Children.Add”把元素加入窗口//得分板初始化showScore.Content = score;}//新食物生成public void NewFoodGenerate(){//删除已存在食物map.Children.Remove(food);//随机生成食物位置Canvas.SetLeft(food, rNumber.Next(0, column - 4) * SIDE);Canvas.SetTop(food, rNumber.Next(0, row - 4) * SIDE);//将食物加入Canvasmap.Children.Add(food);//本应加入程序防止食物生成在体内,但性能可能有限制}//计时器每一个计时周期内的时间处理程序void timer_Tick(object sender, EventArgs e){ //蛇身自动移动for (int n = snake.Count - 1; n >= 1; n--){//吃食物增长长度if ((Canvas.GetLeft(snake[0]) == Canvas.GetLeft(food)) && (Canvas.GetTop(snake[0]) == Canvas.GetTop(food))){snake.Add();map.Children.Add(snake[snake.Count - 1]);NewFoodGenerate();n = snake.Count - 1;score++;showScore.Content = score;//更改得分}Canvas.SetLeft(snake[n], Canvas.GetLeft(snake[n - 1]));Canvas.SetTop(snake[n], Canvas.GetTop(snake[n - 1])); }//蛇头移动switch (snake[0].Tag.ToString()){case "W":Canvas.SetTop(snake[0], Canvas.GetTop(snake[0])-SIDE); break;//待拓展出错处理程序case "A":Canvas.SetLeft(snake[0], Canvas.GetLeft(snake[0]) - SIDE);break;case "S":Canvas.SetTop(snake[0], Canvas.GetTop(snake[0]) + SIDE);break;case "D":Canvas.SetLeft(snake[0], Canvas.GetLeft(snake[0]) + SIDE);break;}//最后再检测是否失败if (Fail()){MessageBox.Show($"最终得分:{score}");timer.Stop();Close();}}//失败鉴定程序public bool Fail(){//碰壁if(Canvas.GetLeft(snake[0])<0|| Canvas.GetLeft(snake[0])> (column - 4) * SIDE|| Canvas.GetTop(snake[0])<0|| Canvas.GetTop(snake[0])> (row - 4) * SIDE){ return true;}//碰到自己for(int n = 1; n < snake.Count; n++){if(Canvas.GetLeft(snake[0])== Canvas.GetLeft(snake[n])&& Canvas.GetTop(snake[0])== Canvas.GetTop(snake[n])){ return true;} }return false;}//获取键盘值,输入则得值private void Window_KeyDown(object sender, KeyEventArgs e){string key = e.Key.ToString();//一个事件间隔内只能输入一个键if (key == "W" && snake[0].Tag.ToString() != "S"){snake[0].Tag = "W";}if (key == "A" && snake[0].Tag.ToString() != "D"){snake[0].Tag = "A";}if (key == "S" && snake[0].Tag.ToString() != "W"){snake[0].Tag = "S";}if (key == "D" && snake[0].Tag.ToString() != "A"){snake[0].Tag = "D";}keytimer.Interval = TimeSpan.FromMilliseconds(400);//400ms后开始加速keytimer.IsEnabled=true;//计时器启动keytimer.Tick += keytimer_Tick;//事件关联到事件处理程序上}//加速事件处理程序void keytimer_Tick(object sender, EventArgs e){timer.Interval = TimeSpan.FromMilliseconds(100);//加速}//结束加速private void Window_KeyUp(object sender, KeyEventArgs e){timer.Interval = TimeSpan.FromMilliseconds(200);//还原速度keytimer.IsEnabled=false;}}public class Snake : CollectionBase//继承链表类{const int SIDE = 10;//每个格子的边长//生成蛇节点public Border CreateSnakeNode(){Border snakeNode = new Border();snakeNode.Width = snakeNode.Height = SIDE;snakeNode.Background = new RadialGradientBrush(Colors.Red, Colors.Red);return snakeNode;}//重载Add,贪吃蛇游戏只需自动增加相同的节点即可public void Add(){List.Add(CreateSnakeNode());}//初始化的蛇有三个节点public Snake(){Add();Add();Add();this[0].Background = new RadialGradientBrush(Colors.White,Colors.Red);//标记蛇头this[0].Tag = "D";//初始蛇向右走}//重载[]public Border this[int nodeIndex]{get { return (Border)List[nodeIndex]; }}}
}
改进:可以做些界面联动,AI蛇
参考:
Hui110110 C#中的贪吃蛇
http://blog.csdn.net/hui110110/article/details/52431657
Yang-Fei [C#].NET中几种Timer的使用
https://www.cnblogs.com/yang-fei/p/6169089.html
绿意无痕 C# WPF Border控件总结
http://blog.csdn.net/lvyiwuhen/article/details/53212450
yongh701【C#】按钮长按
http://blog.csdn.net/yongh701/article/details/50134379
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
