想敲代码又怕女朋友找?那就让她去玩桌面图标贪吃蛇,再也不用担心打扰自己敲代码了

最近在逛博客的时候看见了一个有趣的项目,使用桌面图标进行贪吃蛇游戏。采用的代码是vb,但我实在不会vb,就找了C++中关于桌面图标获取句柄的文章进行查看(第一次接触这个,实属菜鸟)。效果还行 一步步获取到了想要的东西,然后偶然性看见了一位python大佬的博客,这就很OK了,看python代码就没啥问题了,然后就复制复制复制,看了一遍他的代码,接着就是来一个golang版的了。

在这里附上这位python版大佬的文章地址:用Windows10桌面图标玩python贪吃蛇

程序简单,思路算明确,至少我一遍就看懂了整个流程。然后就来一个golang吧。

一、定义一个航线结构体

type Vector struct {x int32y int32
}func (vector *Vector) Add(vec Vector) Vector {return Vector{vector.x + vec.x, vector.y + vec.y}
}func (vector *Vector) Set(vec Vector) {vector.x = vec.xvector.y = vec.y
}func (vector *Vector) Mult(num int32) Vector {return Vector{vector.x * num, vector.y * num}
}

这里就不累赘了,简单的来说就是一个步伐坐标点。

二、获取窗体句柄、窗体大小以及图标数

这里使用了 “github.com/lxn/win” 包。下载吧,直接go get

至于这里如何获取桌面的句柄吧,给为可参考spy++如何使用的。

从spy++中可以看见,要获取viewlist窗口的句柄,只需要从"Program Manager"获取两级子窗口即可。

var hwnd win.HWNDhwnd = win.FindWindow(nil, syscall.StringToUTF16Ptr("Program Manager"))hwnd = win.GetWindow(hwnd, win.GW_CHILD)
hwnd = win.GetWindow(hwnd, win.GW_CHILD)
var rect win.RECT
win.GetWindowRect(hwnd, &rect)
count := win.SendMessage(hwnd, win.LVM_GETITEMCOUNT, 0, 0)

代码如上,其中LVM_GETITEMCOUNT对于这个常量在,lxn/win这个包中并没有,所有我们就手动给他加一个即可。listview.go文件。

LVM_GETITEMCOUNT             = LVM_FIRST + 4

三、给每一个图标进行位置重定位

pos = make([]Vector, count)
pos[0] = Vector{rect.Right / 2, rect.Bottom / 2}
pos[1] = Vector{rect.Right / 2, rect.Bottom / 2}
pos[2] = Vector{rand.Int31n(rect.Right-400) + 200, rand.Int31n(rect.Bottom-400) + 200}
win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, 0, MAKELPARAM(pos[0].x, pos[0].y))
win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, 1, MAKELPARAM(pos[1].x, pos[1].y))
lcur := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&cur))))
fmt.Println(lcur)
win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, lcur, MAKELPARAM(pos[cur].x, pos[cur].y))
var i int
countInt = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&count))))
for i = cur + 1; i < countInt; i++ {pos[i] = Vector{0, -100}lp := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&i))))win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, lp, MAKELPARAM(pos[i].x, pos[i].y))
}

代码如上,其中LVM_SETITEMPOSITION对于这个常量在,lxn/win这个包中并没有,所有我们就手动给他加一个即可。listview.go文件。

LVM_SETITEMPOSITION          = LVM_FIRST + 15

四、实现一个键盘监听

这个简单,直接上代码了:

func getKey() {for {if windev.KeyDownUp(windev.VK_LEFT) == 1 {key = 37}if windev.KeyDownUp(windev.VK_UP) == 1 {key = 38}if windev.KeyDownUp(windev.VK_RIGHT) == 1 {key = 39}if windev.KeyDownUp(windev.VK_DOWN) == 1 {key = 40}}
}

五、实现一个贪吃蛇了

首先是当蛇头位置改变时,后面的蛇身也需要跟着变化,那么剧需要对每一个位置重新赋值。

func run(pv Vector) {for i := cur - 1; i > 0; i-- {pos[i].Set(pos[i-1])}pos[0] = pos[0].Add(pv.Mult(60))for i := 0; i < countInt; i++ {lp := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&i))))win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, lp, MAKELPARAM(pos[i].x, pos[i].y))}time.Sleep(time.Millisecond * 200)
}func MAKELPARAM(x, y int32) uintptr {xt := int(x)yt := int(y)tem := yt << 16a := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&tem))))b := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&xt))))return *a | *b
}

然后将键盘控制结合:

for {// var v Vectorv := Vector{0, 0}if key == 37 {v = Vector{-1, 0}}if key == 38 {v = Vector{0, -1}}if key == 39 {v = Vector{1, 0}}if key == 40 {v = Vector{0, 1}}run(v)f1, _ := strconv.ParseFloat(fmt.Sprintf("%d", pos[0].x-pos[cur].x), 64)f2, _ := strconv.ParseFloat(fmt.Sprintf("%d", pos[0].y-pos[cur].y), 64)// fmt.Println(math.Sqrt(math.Pow(f1, 2) + math.Pow(f2, 2)))if math.Sqrt(math.Pow(f1, 2)+math.Pow(f2, 2)) < 60 {fmt.Println("jinru")cur++pos[cur].Set(Vector{rand.Int31n(rect.Right-400) + 200, rand.Int31n(rect.Bottom-400) + 200})lp := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&cur))))win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, lp, MAKELPARAM(pos[cur].x, pos[cur].y))}fmt.Printf("当前蛇头地址坐标:%d,%d\n", pos[0].x, pos[0].y)fmt.Printf("当前食物地址坐标:%d,%d\n", pos[cur].x, pos[cur].y)
}

六、全部实现代码

package mainimport ("fmt""math""math/rand""strconv""syscall""time""unsafe""github.com/cppdebug/windev""github.com/lxn/win"
)type Vector struct {x int32y int32
}func (vector *Vector) Add(vec Vector) Vector {return Vector{vector.x + vec.x, vector.y + vec.y}
}func (vector *Vector) Set(vec Vector) {vector.x = vec.xvector.y = vec.y
}func (vector *Vector) Mult(num int32) Vector {return Vector{vector.x * num, vector.y * num}
}var cur = 2
var key intfunc getKey() {for {if windev.KeyDownUp(windev.VK_LEFT) == 1 {key = 37}if windev.KeyDownUp(windev.VK_UP) == 1 {key = 38}if windev.KeyDownUp(windev.VK_RIGHT) == 1 {key = 39}if windev.KeyDownUp(windev.VK_DOWN) == 1 {key = 40}}
}var pos []Vector
var countInt int
var hwnd win.HWNDfunc main() {rand.Seed(time.Now().UnixNano())hwnd = win.FindWindow(nil, syscall.StringToUTF16Ptr("Program Manager"))hwnd = win.GetWindow(hwnd, win.GW_CHILD)hwnd = win.GetWindow(hwnd, win.GW_CHILD)var rect win.RECTwin.GetWindowRect(hwnd, &rect)count := win.SendMessage(hwnd, win.LVM_GETITEMCOUNT, 0, 0)fmt.Println(count)pos = make([]Vector, count)pos[0] = Vector{rect.Right / 2, rect.Bottom / 2}pos[1] = Vector{rect.Right / 2, rect.Bottom / 2}pos[2] = Vector{rand.Int31n(rect.Right-400) + 200, rand.Int31n(rect.Bottom-400) + 200}win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, 0, MAKELPARAM(pos[0].x, pos[0].y))win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, 1, MAKELPARAM(pos[1].x, pos[1].y))lcur := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&cur))))fmt.Println(lcur)win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, lcur, MAKELPARAM(pos[cur].x, pos[cur].y))var i intcountInt = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&count))))for i = cur + 1; i < countInt; i++ {pos[i] = Vector{0, -100}lp := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&i))))win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, lp, MAKELPARAM(pos[i].x, pos[i].y))}go getKey()print(key)for {// var v Vectorv := Vector{0, 0}if key == 37 {v = Vector{-1, 0}}if key == 38 {v = Vector{0, -1}}if key == 39 {v = Vector{1, 0}}if key == 40 {v = Vector{0, 1}}run(v)f1, _ := strconv.ParseFloat(fmt.Sprintf("%d", pos[0].x-pos[cur].x), 64)f2, _ := strconv.ParseFloat(fmt.Sprintf("%d", pos[0].y-pos[cur].y), 64)// fmt.Println(math.Sqrt(math.Pow(f1, 2) + math.Pow(f2, 2)))if math.Sqrt(math.Pow(f1, 2)+math.Pow(f2, 2)) < 60 {fmt.Println("jinru")cur++pos[cur].Set(Vector{rand.Int31n(rect.Right-400) + 200, rand.Int31n(rect.Bottom-400) + 200})lp := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&cur))))win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, lp, MAKELPARAM(pos[cur].x, pos[cur].y))}fmt.Printf("当前蛇头地址坐标:%d,%d\n", pos[0].x, pos[0].y)fmt.Printf("当前食物地址坐标:%d,%d\n", pos[cur].x, pos[cur].y)}
}func run(pv Vector) {for i := cur - 1; i > 0; i-- {pos[i].Set(pos[i-1])}pos[0] = pos[0].Add(pv.Mult(60))for i := 0; i < countInt; i++ {lp := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&i))))win.SendMessage(hwnd, win.LVM_SETITEMPOSITION, lp, MAKELPARAM(pos[i].x, pos[i].y))}time.Sleep(time.Millisecond * 200)
}func MAKELPARAM(x, y int32) uintptr {xt := int(x)yt := int(y)tem := yt << 16a := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&tem))))b := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&xt))))return *a | *b
}

最后执行的时候别忘了,把这个取消了。点个赞收藏一波哦

如有需要改程序.exe执行文件的,可点击免费下载:桌面贪吃蛇go版.exe

想敲代码又怕女朋友找?那就让她去玩桌面图标贪吃蛇,再也不用担心打扰自己敲代码了相关推荐

  1. Idea代码自动补全!插件推荐:Codota,再也不用担心写不出代码了。

    前言 最近,有小伙伴推荐给D哥一款IDEA插件,叫我一定得给大家分享一下,简直太好用了~ 这款插件解决的痛点:当你不知道一个类该怎么用的时候,它能帮你快速找到想要的实例代码. 群里有不少同学说,&qu ...

  2. Idea代码自动补全,良心插件推荐:Codota,再也不用担心写不出代码了。

    这款插件就是 Codota.基于AI技术,通过对大量开源的项目学习,帮助开发者提供更可靠的智能推荐,让编程变得更easy! 官网:https://www.codota.com 看官方发现,目前支持的语 ...

  3. 看完这篇文章再也不用担心代码格式不对无法合并了

    本文由RT-Thread论坛用户@RTT_逍遥原创发布:https://club.rt-thread.org/ask/article/3121.html GITHUB仓库: git_auto_scri ...

  4. php你们想不到的强大,找电影的好网站,再也不用担心下不到好电影了!

    找电影的好网站,再也不用担心下不到好电影了! 首先要声明一点,往前方不会推荐PT站或者其他需要邀请注册的网站,本文提到的一定都是无需注册或者开放注册的.简单实用的网站. 如果你不是那么热爱电影,只是闲 ...

  5. 自媒体人必备的4个素材网站,再也不用担心找不到素材

    经常看到很多自媒体人问,不知道怎么找素材,每次写文章的时候都觉得灵感枯竭,素材不够用,文章没有足够的内容支撑.不慌,今天就给大家介绍5个实用的素材网站,让你再也不用担心找不到素材: 01 热文素材-- ...

  6. 自助定制OpenWRT,麻麻再也不用担心我找不到固件用辣

    博客地址:自助定制OpenWRT,麻麻再也不用担心我找不到固件用辣 - 黄·BLOG (huanggame.top) 众所周知,OpenWRT是一款出色的路由器固件,他可以安装许多插件以提升用户体验. ...

  7. 重装系统后桌面找不到计算机,电脑重装找不到桌面文件了?教你一招,再也不用担心文件消失!...

    原标题:电脑重装找不到桌面文件了?教你一招,再也不用担心文件消失! 在工作中,我们习惯性的都会将一些文件直接保存在桌面,这样方便我们去查找,但是也会遇到电脑系统崩溃,需要重装电脑,不过这时候在登录到桌 ...

  8. 有了这套模板,女朋友再也不用担心我刷不动 LeetCode 了

    作者 | 李威 来源 | https://www.liwei.party/ 整理 | 五分钟学算法 全文包含 12000+ 字.30 张高清图片,预计阅读时间为 40 分钟,强烈建议先收藏再仔细阅读. ...

  9. c++贪吃蛇游戏-详细解释-非单纯贴代码

    先说明下:本文来源:https://blog.csdn.net/silence1772/article/details/55005008 写在前面,这个项目,希望大家先下载下来,玩一玩.然后2天左右把 ...

最新文章

  1. 数据结构Stack:关系以及方法
  2. 第八周项目二-用对象数组操作长方柱类
  3. .Net 之匿名类(AnonymousType)(转载)
  4. 监控服务器登录用户的操作脚本(linux下shell.sh)
  5. js中函数的参数为函数的情况即回调函数
  6. 【图数据结构的遍历】java实现广度优先和深度优先遍历
  7. Android中用GridView实现九宫格的两种方法(转)
  8. 新手学完Java可以面试哪些岗位?
  9. Oracle在JavaOne上宣布Java EE 8将会延期至2017年底
  10. ecshop二次开发 给商品添加自定义字段【包含我自己进一步的开发实例详解】
  11. 一般处理程序在VS2012中打开问题
  12. 量子计算机美国华裔科学家,量子计算机很神?18岁华裔少年用经典计算机算得一样快...
  13. ADL SDK V10.2 中文文档
  14. 前端九年老司机的一天作息
  15. 购买服务器不显示d盘,购买云服务器后d盘
  16. Android测试——(下篇)
  17. 二十三种设计模式之原型模式
  18. 从正多面体到斐波拉契网格
  19. 大工21春《船舶制图》大作业离线作业
  20. 网络通信面试题详细解答

热门文章

  1. sqlserver dba
  2. jaffe 数据库百度网盘下载
  3. matlab计算程序运行时间
  4. 微信小程序:云开发开通
  5. HC32F460+RTthread U盘使用详解
  6. 招商银行信用卡中心邀请你参加M-Geeker技术竞赛初赛
  7. 快乐大掌柜源码--快乐大掌柜系统开发模式介绍
  8. 从安装包中提取wear OS手表端应用
  9. Docker常用命令大全(万字详解)
  10. 2022年乡村医生考试模拟题及答案