这次,又是一个全新的小玩意。就是把windows桌面上的图标,让他们整齐划一,变成贪吃蛇小游戏(没错,我就是和贪吃蛇杠上了)。

这个游戏,可以称之为“没有界面的贪吃蛇”。下面放上效果图。

下面介绍详细过程。

0.准备工作

  • 系统:Win10
  • 开发工具:Visual Studio2019
  • 语言:C#

1.关键点

  • 如何生成食物(动态创建桌面图标)
  • 如何移动蛇身体和食物(移动桌面图标到指定位置)

创建桌面图标用到了接口IWshShortcut,具体代码如下

        public void _createShortcut(){//选择随机图标var rnd = new Random().Next(0, ICONS.Length);var LinkPathName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);var IconPath = ICONS[rnd];var guid = Guid.NewGuid().ToString();//获取图标名字var name = ICONNAMES[rnd];WshShell shell = new WshShell();            IWshShortcut link = (IWshShortcut)shell.CreateShortcut($"{LinkPathName}/{name+guid}.lnk");link.IconLocation = IconPath;link.TargetPath = IconPath;link.Save();            }

而移动桌面图标则用到了WindowsAPI中的函数,代码如下

        [DllImport("User32.dll", EntryPoint = "SendMessage")]public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);private void _movdDeskTopIons(int i, int x, int y){WindowsAPIs.SendMessage((int)_shortCut, (int)LVM_SETITEMPOSITION, i, (int)WindowsAPIs.MakeLParam(x, y));            }

解决了这两个问题,还存在一个隐藏的问题,即通过IWshShortcut创建的图标,在一定的时间之后或创建第二个图标之后,这个图标才能被移动。所以你会发现桌面左上角有一个多余的图标,那就是先将图标创建好放在左上角,当游戏需要食物时,才将该图标移动到随机位置,同时再创建一个备用图标放在左上角。

解决了这个问题,再加上贪吃蛇的基础游戏规则代码,这个游戏就可以完整独立流畅地运行了。

2.代码片段

下面贴出一些关键类代码,有需要完整工程文件或游戏执行文件的小伙伴可以私信我。

WindowsAPI类

    public class WindowsAPIs{        const int WM_MOUSEWHEEL = 0x020A; //鼠标滚轮const int WM_LBUTTONDOWN = 0x0201;//鼠标左键const int WM_LBUTTONUP = 0x0202;const int WM_KEYDOWN = 0x0100;//模拟按键const int WM_KEYUP = 0x0101;const int MOUSEEVENTF_MOVE = 0x0001;//用于琴台鼠标移动const int MOUSEEVENTF_LEFTDOWN = 0x0002;//前台鼠标单击const int MOUSEEVENTF_LEFTUP = 0x0004;const int WM_SETTEXT = 0x000C;//设置文字const int WM_GETTEXT = 0x000D;//读取文字[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);[DllImport("User32.dll", EntryPoint = "SendMessage")]public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);[DllImport("User32.dll", EntryPoint = "SendMessage")]public static extern int SendMessage(int hWnd, int Msg, int wParam, string lParam);[DllImport("user32.dll")]//在窗口列表中寻找与指定条件相符的第一个子窗口public static extern int FindWindowEx(int hwndParent, // handle to parent windowint hwndChildAfter, // handle to child windowstring className, //窗口类名            string windowName);[DllImport("user32.DLL")]public static extern IntPtr FindWindowEx(IntPtr hwndParent,IntPtr hwndChildAfter, string lpszClass, string lpszWindow);[DllImport("user32.dll", SetLastError = true)]public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);public static IntPtr MakeLParam(int wLow, int wHigh){return (IntPtr)(((short)wHigh << 16) | (wLow & 0xffff));}}

Snake类

    public class Snake{//0123 左上右下public int Direction = 2;//组成蛇身的位置信息public List<Pos> Body;//蛇身宽度 食物宽度public int Width=76;//蛇身高度 食物高度public int Height= 104;//未消化的食物private Queue<Pos> _digestion = new Queue<Pos>();public Snake(){Body = new List<Pos>();Body.Add(new Pos { x = 0, y = 0 });}public void TurnDirection(int direction){if (Math.Abs(direction - Direction) == 2) return;Direction = direction;}public void Move(){Pos head = new Pos{x=Body.First().x,y=Body.First().y};switch (Direction){case 0:{head.x -= Width;break;}case 1:{head.y -= Height;break;}case 2:{head.x += Width;break;}case 3:{head.y += Height;break;}}Pos food = null;if (_digestion.Count > 0){                food = _digestion.Dequeue();food.x = Body.Last().x;food.y = Body.Last().y;}for(var i=Body.Count-1;i>0;i--){Body[i] =new Pos { x = Body[i - 1].x, y = Body[i - 1].y };}Body[0] = head;if (food != null) Body.Add(food);}public void Eat(Pos food){_digestion.Enqueue(food);}}

Map类

    public class Map{public double  Width { get; set; }public double Height { get; set; }public Map(){Width = SystemParameters.WorkArea.Width;//25  1920    76.8Height = SystemParameters.WorkArea.Height;//10  1040   104}}

Game类

    public class Game{public string[] ICONS= new string[] {@"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\devenv.exe",@"D:\Program Files\Microsoft VS Code\Code.exe",@"C:\Program Files\JetBrains\IntelliJ IDEA 2020.2.3\bin\idea64.exe",@"D:\Program Files\Android Studio\Studio\bin\studio64.exe",@"D:\Program Files (x86)\DingDing\DingtalkLauncher.exe",@"D:\Program Files\YouDaoDic\Dict\YoudaoDict.exe",@"D:\Program Files (x86)\Steam\steam.exe",@"D:\Program Files\WeGame\wegame.exe",            @"C:\Program Files\Adobe\Adobe Photoshop CC 2017\Photoshop.exe",};public string[] ICONNAMES = new string[]{"Visual Studio","VSCode","IDEA","Android Studio","Dingtalk","YoudaoDict","Steam","WeGame","Photoshop"};private const uint LVM_SETITEMPOSITION = 0x1000 + 15;private IntPtr _shortCut;private bool _gaming=false;private Snake _snake;private Map _map;private Pos _food;public delegate void GameNotify(bool Gaming);public GameNotify GameStoped;public Game(){_map = new Map();_shortCut = _getIconHandle();}public void Start(){_snake = new Snake();_gaming = true;new Thread(() => {_createShortcut();Thread.Sleep(1000);while (_gaming){_snake.Move();if (_food == null)_createFood();if (!_checkCollision()){MessageBox.Show("游戏结束!");_gaming = false;Application.Current.Dispatcher.Invoke(GameStoped,_gaming);break;}_drawBody();                    Thread.Sleep(250);}}).Start();}public void TurnDirection(int direction){_snake.TurnDirection(direction);}public void _createFood(){var rnd = new Random();var x = rnd.Next(0, (int)_map.Width-_snake.Width);var y = rnd.Next(0, (int)_map.Height-_snake.Height);_createShortcut();            _movdDeskTopIons(_snake.Body.Count, x, y);            _food = new Pos { x = x, y = y };}private bool _checkCollision(){var head = _snake.Body.First();//碰撞墙壁            if (head.x < 0 || head.x > _map.Width-_snake.Width)return false;if (head.y < 0 || head.y > _map.Height-_snake.Height)return false;//碰撞自身for (var i = 1; i < _snake.Body.Count; i++){if (Math.Abs(head.x - _snake.Body[i].x) < _snake.Width&&Math.Abs(head.y - _snake.Body[i].y) < _snake.Height){return false;}}//碰撞食物if (Math.Abs(head.x - _food.x) < _snake.Width&&Math.Abs(head.y - _food.y) < _snake.Height){_snake.Eat(new Pos { x = _food.x, y = _food.y });_food = null;}return true;}private void _drawBody(){for(var i = 0; i < _snake.Body.Count; i++){var pos = _snake.Body[i];_movdDeskTopIons(i, pos.x, pos.y);}}public void _createShortcut(){//选择随机图标var rnd = new Random().Next(0, ICONS.Length);var LinkPathName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);var IconPath = ICONS[rnd];var guid = Guid.NewGuid().ToString();//获取图标名字var name = ICONNAMES[rnd];WshShell shell = new WshShell();            IWshShortcut link = (IWshShortcut)shell.CreateShortcut($"{LinkPathName}/{name+guid}.lnk");link.IconLocation = IconPath;link.TargetPath = IconPath;link.Save();            }private IntPtr _getIconHandle(){IntPtr vHandle = WindowsAPIs.FindWindow("Progman", "Program Manager");vHandle = WindowsAPIs.FindWindowEx(vHandle, IntPtr.Zero, "SHELLDLL_DefView", null);vHandle = WindowsAPIs.FindWindowEx(vHandle, IntPtr.Zero, "SysListView32", "FolderView");return vHandle;}private void _movdDeskTopIons(int i, int x, int y){WindowsAPIs.SendMessage((int)_shortCut, (int)LVM_SETITEMPOSITION, i, (int)WindowsAPIs.MakeLParam(x, y));            }}

在Windows上将桌面图标做成贪吃蛇游戏相关推荐

  1. 用Windows API 编写的简单贪吃蛇游戏

    一.基础知识笔记 <1. COORD结构体,是Windows API中定义的一种结构体,用于在控制台屏幕上定位一个字符的坐标. <2.句柄,是整个windows编程的基础,一个句柄是指使用 ...

  2. 开发Windows贪吃蛇游戏——(二)代码实现

    目录 前言 窗体部分 Frame部分 声明全局变量 Panel的初始化 startGame方法 paintComponent方法 drawGame方法 newSnake方法 newFood方法 mov ...

  3. 如何还原桌面图标_如何为Windows 10桌面图标还原或更改文本的默认外观?

    如何还原桌面图标 For whatever reason, sooner or later we all have someone or something mess around with our ...

  4. win7桌面上显示html,win7桌面图标不见了怎么办,显示Windows 7桌面图标的方法

    打开电脑发现电脑桌面没有任何图标的显示,默认的Windows 7桌面就只有一个垃圾桶,"我的电脑"."Internet Explorer图标".及"我 ...

  5. 计算机软件实习(二)贪吃蛇游戏实现

    基于C++的贪吃蛇游戏实现 实验内容: (1)实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右 控制"蛇"的移动,吃到"豆子&q ...

  6. 基于单片机的贪吃蛇游戏

    绪论 1.1 研究背景与意义 随着社会的发展,人们生活的步调日益加快,越来越多的人加入了全球化的世界. 人们不再拘泥于--,J,块天地,加班,出差成了现代人不可避免的公务.而此时一款可以 随时随地娱乐 ...

  7. 基于linux的贪吃蛇游戏设计_贪吃蛇还能这么玩?绝对是你从未体验过的全新版本(上)...

    上个月 Gitee 宣布推出「Python 贪吃蛇魔改大赛」的活动,受到了众多开发者们的欢迎.半个多月后,我们收到了共计 42 个参赛作品,有的作品创意无限,有的作品视觉效果极佳,看看下面的作品一览, ...

  8. C 语言实现经典贪吃蛇游戏

    原文链接:C语言 贪吃蛇游戏 文章目录 一.说明 二.效果 2.1 欢迎界面 2.2 游戏规则 2.3 得分排行 2.4 退出游戏 2.5 游戏界面 2.6 游戏结束 三.源码 3.1 cmd.h 3 ...

  9. 用C++语言实现贪吃蛇游戏

    最近更了个新的关于用C/C++写贪吃蛇的blog,感觉那个帮助会更大些,这篇中用DirectX技术不适合刚开始试着写游戏的同学,传送:https://blog.csdn.net/weixin_3781 ...

  10. JAVA游戏开发-超炫酷贪吃蛇游戏源码及教程

    一.前言 某日,看见隔壁家的小朋友在玩一款网络爆款贪吃蛇游戏,感觉很好玩.自己刚好正在学习JAVA编程,也想实现一个类似功能的游戏Demo练手,在网上查看了不少源码案例,全都是很古老的方块式贪吃蛇游戏 ...

最新文章

  1. 第三十九篇 Python异常处理
  2. 框架:SpringMVC常用注解总结
  3. Qt实现延时sleep函数功能
  4. daocloud创建mysql_GitHub - DaoCloud/php-apache-mysql-sample
  5. python语_Python 基本语法
  6. 数据结构、算法及应用 课内模板整理
  7. 如何使用bash / sed脚本删除文本文件的第一行?
  8. Spring Boot 打的包为什么能直接运行?
  9. 基于STM32的DMX512开发
  10. 快递电子面单接口:四通一达,百世,邮政,顺丰,德邦等快递电子面单接口免费接入
  11. 2020年最新中科院期刊分区表
  12. Worker小Demo
  13. windows下远程连接Mysql
  14. [网鼎杯 2018]Fakebook
  15. 微商利用手机APP挣钱方法与大家分享
  16. upupoo启动不了 mysql_【upupoo动态桌面壁纸和MySQL API 中文手册哪个好用】upupoo动态桌面壁纸和MySQL API 中文手册对比-ZOL下载...
  17. 利用镜像解决一系列下载速度慢的问题
  18. 报错:“TypeError: Cannot read property ‘0‘ of undefined“的原因
  19. 数字图像直方图处理涉及的数学知识介绍
  20. lecture09 Convex 模型预测控制(MPC)

热门文章

  1. VMware虚拟机不能上网了怎么办
  2. Unity3D帧动画,图片的切换实现动画效果
  3. ST-Link v2 下载 出现target dll has been cancelled 的错误的解决方法
  4. vscode 升级时失败 win10
  5. 【综述】A Comprehensive Survey on Graph NeuralNetworks(2)
  6. 如何轻松入门西门子 SCL(结构化控制语言) | 附官方教程下载
  7. java+mysql基于JSP0801报刊订阅系统(java,web)
  8. MAME set 4 player
  9. ORR和BIC伪指令应用
  10. php返回token什么意思,token什么意思