/* 关于 贪吃蛇v20201219-虚荣.ahk 说明: 抽空瞎写的比较粗糙, 为了找机会测试链表结构 加上从没写过完整游戏, 还有一个最近拿python控制台输出写游戏很勤快的兄弟的刺激, 特地写了这个贪吃蛇 感谢大佬fwt(狗头同志)的斗气, 不然我该没动力完成了 狗头同志厉害不到150行完成了这样的效果, 特此记录以警示后人**装逼莫早** 顺带挑战纯中文书写代码, 发现真的不是很容易, 太长了 写得有点乱, 总算跑起来了, 有些不太好看的地方, 有思路完善不过目前没有心思优化了 希望这个ahk示例对大家有帮助 配置于 贪吃蛇.开始() 部分可以改动 虚荣 2020/12/19 */ #SingleInstance, force 贪吃蛇程序入口: 贪吃蛇.开始() exitapp 贪吃蛇GuiClose: exitapp return 贪吃蛇键回调(游戏循环, 操作朝向) { ;msgbox, % 操作朝向 游戏循环.最后操作蛇朝向 := 操作朝向 } class 贪吃蛇 { 开始() { ;~ 地图.重建(块尺寸, 块间距, 块横数, 块纵数, 色值_背景, 色值_空地) this.地图.重建(15, 1, 20, 20, 0xECF8CA, 0xCCE7BA) ;~ 小蛇.初始化(地图, 初始蛇长, 蛇身色, 蛇头色) this.小蛇.初始化(this.地图, 3, 0x87CDA8, 0x80AAA8) ;~ 食物.初始化(地图, 食物色) this.食物.初始化(this.地图, 0xD29864) ;~ 游戏循环.设定鼠标监听(贪吃蛇, 上键, 下键, 左键, 右键) this.游戏循环.设定鼠标监听(this, "up", "down", "left", "right") this.游戏循环.设定刷新频率(300) this.游戏循环.启动(this, this.地图, this.小蛇, this.食物) } 失败(errmsg) { msgbox, % ("游戏结束, 附加信息:`n") (errmsg) } class 游戏循环 { static 最后方向逻辑单元 static 刷新频率 static 最后操作蛇朝向 := "" 启动(贪吃蛇, 地图, 小蛇, 食物) { 上一时间 := A_TickCount loop { If (A_TickCount - 上一时间 > this.刷新频率) { 蛇头将至坐标 := 小蛇.移动朝向(this.最后操作蛇朝向) ;msgbox, % (A_LineNumber) ":" 蛇头将至坐标.横 "-" 蛇头将至坐标.纵 蛇步入占位物 := 地图.取坐标占位物名称(蛇头将至坐标) ;~ 失败条件 ---------------------------- if (蛇步入占位物 = 地图.边界占位名) { ;print("小蛇撞墙了") 贪吃蛇.失败("小蛇撞墙了") break } else if (蛇步入占位物 = 食物.占位名) { ;print("小蛇前进一格_并长大") 小蛇.前进一格_并长大(地图, 蛇头将至坐标) ;msgbox, % isobject(食物) 食物.随机生成(地图) } ;~ 其他条件 ---------------------------- else if (蛇步入占位物 = 地图.空块占位名) { ;print("小蛇前进一格_不长大") 小蛇.前进一格_不长大(地图, 蛇头将至坐标) } else if (蛇步入占位物 = 小蛇.占位名) { ;print("小蛇撞到自己了") 贪吃蛇.失败("小蛇撞到自己了") break } 上一时间 := A_TickCount } } return } 设定刷新频率(刷新频率) { this.刷新频率 := 刷新频率 } 设定鼠标监听(贪吃蛇, 上键, 下键, 左键, 右键) { 操作朝向组 := { (上键) : "上", (下键) : "下", (左键) : "左", (右键) : "右" } ;msgbox, % obj_dbg1(操作朝向组) for 此键, 操作朝向 in 操作朝向组 { ;msgbox, % 此键 "--" 操作朝向 贪吃蛇键回调 := func("贪吃蛇键回调").bind(this, 操作朝向) hotkey, % 此键, %贪吃蛇键回调% } } } class 地图 { static 块 ;~ static 空块占位名 := "空块" ;~ 块_已占 := {} static 边界占位名 := "边界" static 画布_句柄, 画布_设备上下文 static 块尺寸, 块间距, 块横数, 块纵数 static 宽, 高 static 背景色画刷 static 空块色画刷 ;----------------------------------- 重建(块尺寸, 块间距, 块横数, 块纵数, 色值_背景, 色值_空地) { this.块 := [] this.块尺寸 := 块尺寸 this.块间距 := 块间距 this.宽 := (块尺寸 + 块间距) * 块横数 - 块间距 this.高 := (块尺寸 + 块间距) * 块纵数 - 块间距 this.块横数 := 块横数 this.块纵数 := 块纵数 this.画布_句柄 := 0x0 this.画布_设备上下文 := 0x0 this.空块色画刷 := 0x0 ;-------------------------------- ;~ 创建画布 Gui, 贪吃蛇:Destroy Gui, 贪吃蛇:+hwnd画布_句柄 +toolwindow +AlwaysOnTop Gui, 贪吃蛇:Show, % " x10 " . "w" this.宽 . " " . "h" this.高 . " " this.画布_句柄 := 画布_句柄 this.画布_设备上下文:=Dllcall("GetDC" , "UInt", this.画布_句柄 , "Uint") ;~ 获取窗口dc指针 ;---------------------------- ;~ 设置空画笔, 让矩形无描边 ;~hPenOld:= Dllcall("SelectObject" , "Ptr", this.画布_设备上下文 ;, "Ptr", hdcMem , "Ptr", DllCall("GetStockObject" , "int", 0x8 ;~ NULL_PEN , "uint") , "UInt") ;---------------------------- ;~ 设置背景色画刷颜色 this.背景色画刷:=DllCall("CreateSolidBrush" , "Uint", this.翻译RGB色(色值_背景) , "Uint") ;~ hBrushOld:= Dllcall("SelectObject" , "Ptr", this.画布_设备上下文 ;, "Ptr", hdcMem , "Ptr", this.背景色画刷 , "UInt") Dllcall("Rectangle" , "Ptr", this.画布_设备上下文 , "Int", 1 , "Int", 1 , "Int", this.宽 , "Int", this.高 , "UInt") ;---------------------------- ;~ 设置背景色画刷颜色 this.空块色画刷:=DllCall("CreateSolidBrush" , "Uint", this.翻译RGB色(色值_空地) , "Uint") ;~ hBrushOld:= Dllcall("SelectObject" , "Ptr", this.画布_设备上下文 ;, "Ptr", hdcMem , "Ptr", this.空块色画刷 , "UInt") ;-------------------------------- ;~ 创建空白地 loop, % 块横数 { 横 := A_Index this.块[横] := [] loop, % 块纵数 { 纵 := A_Index this.设置块颜色(画刷句柄, 横, 纵, this.空块占位名) } } } 设置块颜色(画刷句柄, 横, 纵, 占位物) { static 前一句柄 := "" this.块[横][纵] := {"占位物": 占位物} if not (画刷句柄 = 前一句柄) Dllcall("SelectObject" , "Ptr", this.画布_设备上下文 ;, "Ptr", hdcMem , "Ptr", 画刷句柄 , "UInt") 左上横 := (横 - 1) * (this.块尺寸 + this.块间距) 左上纵 := (纵 - 1) * (this.块尺寸 + this.块间距) 右下横 := 左上横 + this.块尺寸 右下纵 := 左上纵 + this.块尺寸 Dllcall("Rectangle" , "Ptr", this.画布_设备上下文 , "Int", 左上横 , "Int", 左上纵 , "Int", 右下横 , "Int", 右下纵 , "UInt") } 取坐标占位物名称(蛇头将至) { 横 := 蛇头将至.横 纵 := 蛇头将至.纵 if (0) or (横 > this.块横数) or (纵 > this.块纵数) or (横 < 1) or (纵 < 1) return this.边界占位名 else { ;msgbox, % (A_LineNumber) ":" obj_dbg1(this["块"]) return this["块"][横][纵]["占位物"] } } 翻译RGB色(color, retHex := true) { return retHex ? format("0x{1:x}",((color & 0xff) << 16) + ((color >> 8 & 0xff) << 8) + (color >> 16 & 0xff)) : ((color & 0xff) << 16) + ((color >> 8 & 0xff) << 8) + (color >> 16 & 0xff) } } class 小蛇 { static 占位名 := "小蛇蛇" static 当前方向 static 蛇头, 蛇尾 static 蛇头画刷, 蛇身画刷 static 蛇长 class 蛇段 { 前一段 := "" 后一段 := "" __new(坐标) { this.坐标 := 坐标 } } 初始化(地图, 初始蛇长, 蛇身色, 蛇头色) { this.蛇长 := (初始蛇长 < 2) ? 2 : 初始蛇长 this.蛇身画刷:=DllCall("CreateSolidBrush" , "Uint", 地图.翻译RGB色(蛇身色) , "Uint") this.蛇头画刷:=DllCall("CreateSolidBrush" , "Uint", 地图.翻译RGB色(蛇头色) , "Uint") random, 横, 1, % 地图.块横数 random, 纵, 1, % 地图.块纵数 this.蛇头 := new this.蛇段({"横": 横, "纵": 纵}) ;MsgBox, % "造蛇" 横 "-" 纵 this.蛇头.前一段 := "" 地图.设置块颜色(this.蛇头画刷, 横, 纵, this.占位名) 当前段 := this.蛇头 loop, % 初始蛇长 - 1 { loop { ;print("造蛇中:" A_Index) random, 随机增值, 1, 4 增值 := [[0, -1], [0, 1], [1, 0], [-1, 0]][随机增值] 横 := 当前段.坐标.横 + 增值[1] 纵 := 当前段.坐标.纵 + 增值[2] ;msgbox, % 地图["块", 横, 纵, "占位物"] } until ( ( 地图["块", 横, 纵, "占位物"] == 地图.空块占位名 ) and (not 横 > 地图.块横数) and (not 横 < 1) and (not 纵 > 地图.块纵数) and (not 纵 < 0) ) 当前段.后一段 := new this.蛇段({"横": 横, "纵": 纵}) 当前段.后一段.前一段 := 当前段 当前段 := 当前段.后一段 this.蛇尾 := 当前段 地图.设置块颜色(this.蛇身画刷, 横, 纵, this.占位名) } ;msgbox, % obj_dbg1(this.蛇尾.坐标) } 调试蛇链表() { 输出文本 := "" 甲 := this.蛇头 loop { if not 甲 break 输出文本 .= "节:" 甲.坐标.横 "-" 甲.坐标.纵 "`n" 甲 := 甲.后一段 } return 输出文本 } 移动朝向(方向) { ;~ 返回下一坐标 static 朝向 := { ("上") : {"横增值": 0, "纵增值":-1} , ("下") : {"横增值": 0, "纵增值": 1} , ("左") : {"横增值": -1, "纵增值": 0} , ("右") : {"横增值": 1, "纵增值": 0} } if (方向 = "") { 增值逻辑 := this.取蛇头朝前逻辑() 蛇头将至坐标 := { "横":this.蛇头.坐标.横 + 增值逻辑["横增值"] , "纵":this.蛇头.坐标.纵 + 增值逻辑["纵增值"]} } else { 增值逻辑 := 朝向[方向] 蛇头将至坐标 := { "横" : this.蛇头.坐标.横 + 增值逻辑.横增值 , "纵" : this.蛇头.坐标.纵 + 增值逻辑.纵增值 } if ( (蛇头将至坐标.横 = this.蛇头.后一段.坐标.横) && (蛇头将至坐标.纵 = this.蛇头.后一段.坐标.纵) ) { 增值逻辑 := this.取蛇头朝前逻辑() 蛇头将至坐标 := { "横":this.蛇头.坐标.横 + 增值逻辑["横增值"] , "纵":this.蛇头.坐标.纵 + 增值逻辑["纵增值"]} } } ;msgbox, % (A_LineNumber) ":" 蛇头将至坐标.横 "-" 蛇头将至坐标.纵 return 蛇头将至坐标 } 取蛇头朝前逻辑() { 首横 := this.蛇头.坐标.横 首纵 := this.蛇头.坐标.纵 次横 := this.蛇头.后一段.坐标.横 次纵 := this.蛇头.后一段.坐标.纵 if (首横 = 次横 && 首纵 = 次纵) 增值逻辑 := {"横增值": 1, "纵增值": 0} else if (首横 = 次横) 增值逻辑 := {"横增值": 0, "纵增值": 首纵 - 次纵} else if (首纵 = 次纵) 增值逻辑 := {"横增值": 首横 - 次横, "纵增值": 0} else 增值逻辑 := {"横增值": 1, "纵增值": 0} return 增值逻辑 } 前进一格_并长大(地图, 蛇头将至坐标) { this.蛇长 += 1 地图.设置块颜色(this.蛇头画刷, 蛇头将至坐标.横, 蛇头将至坐标.纵, this.占位名) 地图.设置块颜色(this.蛇身画刷, this.蛇头.坐标.横, this.蛇头.坐标.纵, this.占位名) ;~ 蛇头与次段中间插入 临时段 := this.蛇头.后一段 this.蛇头.后一段 := new this.蛇段({"横": this.蛇头.坐标.横, "纵": this.蛇头.坐标.纵}) this.蛇头.坐标 := {"横": 蛇头将至坐标.横, "纵": 蛇头将至坐标.纵} this.蛇头.后一段.前一段 := this.蛇头 this.蛇头.后一段.后一段 := 临时段 临时段.前一段 := this.蛇头.后一段 } 前进一格_不长大(地图, 蛇头将至坐标) { 地图.设置块颜色(this.蛇身画刷, this.蛇头.坐标.横, this.蛇头.坐标.纵, this.占位名) 地图.设置块颜色(this.蛇头画刷, 蛇头将至坐标.横, 蛇头将至坐标.纵, this.占位名) 地图.设置块颜色(地图.空块色画刷, this.蛇尾.坐标.横, this.蛇尾.坐标.纵, 地图.空块占位名) ;~ 原来蛇头位置用新段填充 临时段 := this.蛇头.后一段 this.蛇头.后一段 := new this.蛇段({"横": this.蛇头.坐标.横, "纵": this.蛇头.坐标.纵}) this.蛇头.坐标 := {"横": 蛇头将至坐标.横, "纵": 蛇头将至坐标.纵} this.蛇头.后一段.前一段 := this.蛇头 this.蛇头.后一段.后一段 := 临时段 临时段.前一段 := this.蛇头.后一段 ;~ 原来蛇尾位置空 this.蛇尾 := this.蛇尾.前一段 this.蛇尾.后一段 := "" ;msgbox, % "移动-不长大:`n" this.调试蛇链表() "`n" obj_dbg1(this.蛇尾.坐标) } } class 食物 { static 占位名 := "好吃的" static 食物色画刷 static 当前坐标 初始化(地图, 食物色) { this.食物色画刷:=DllCall("CreateSolidBrush" , "Uint", 地图.翻译RGB色(食物色) , "Uint") this.随机生成(地图) } 随机生成(地图) { loop { random, 横, 1, % 地图.块横数 random, 纵, 1, % 地图.块纵数 } until ( 地图["块", 横, 纵, "占位物"] = 地图.空块占位名 ) and (not 横 > 地图.块横数) and (not 纵 > 地图.块纵数) and (not 横 < 1) and (not 纵 < 0) ;msgbox, % this.食物色画刷 "-" 横 "-" 纵 "-" this.占位名 地图.设置块颜色(this.食物色画刷, 横, 纵, this.占位名) this.当前坐标 := {"横": 横, "纵": 纵} } } } print(msg) { DBG_GUI.print(msg) } class DBG_GUI { static hwnd := "" init() { local x, y, w := 500, h := 150 local sFont := "微软雅黑" Gui, dbgls: Font, , % sFont Gui, dbgls: destroy Gui, dbgls: +AlwaysOnTop +toolwindow +hwnd@main Gui, dbgls: Add, ListBox, w%w% h%h% hwnd@lb x := (A_ScreenWidth - w) / 2 y := A_ScreenHeight - h - 100 gui, dbgls: Show, Hide x%x% y%y%, 列表debug this.hwnd := @main this.lb := @lb this.Msgs := [] } show() { gui, dbgls: Show } hide() { gui, dbgls: hide } print(msg) { local i, v, ex static times := 0 ex := A_DetectHiddenWindows DetectHiddenWindows, on ;~ 不存在该窗口则重建 if not (this.hwnd && winexist("ahk_id " this.hwnd)) this.init() ;~ 未显示该窗口则显示 DetectHiddenWindows, off if not winexist("ahk_id " this.hwnd) this.show() DetectHiddenWindows, % ex times += 1 if (this.Msgs.count() > 200) { this.Msgs.removeat(1, 50) this.Msgs.push(msg) GuiControl, , % this.lb, % " " GuiControl, , % this.lb, % "|" For i, v in this.Msgs GuiControl, , % this.lb, % times ": " v "||" } else { this.Msgs.push(msg) GuiControl, , % this.lb, % times ": " msg "||" } } } obj_dbg1(obj) { ret := "" if IsObject(obj) { ret .= "{" for key, var in obj ret .= key . " :" . obj_dbg1(var) . ", " if (key <> "") ret := SubStr(ret, 1, -2) ret .= "}" } else { if obj is number ret := obj else if (obj = "") ret = "" else ret := """" obj """" } return ret }
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。
评论(0)