whitefirer[PG] 越长大越孤单…

22八/151

围住神经猫的python实现

最近写了一个围住神经猫的算法代码,原谅我用的python,真的太方便了- -。。。

也不要问我为什么没有用网上的现成的代码,因为我看别人写的js或者c++代码总感觉没有自己写思路清楚。

核心代码是下面这块:

def GetCatPath(self): #主函数
	data = copy.deepcopy(self.map)
	#data = self.map
	self.result='' #结果存放处
	#方向定义
	#dirs = [[-1,0,'L'],[0,-1,'U'],[1,0,'R'],[0,1,'D']]
	#dirs2 = [[-1,0,'L'],[0,-1,'U'],[1,-1,'E'],[1,0,'R'],[1,1,'V'],[0,1,'D']]#%2=0
	#dirs1 = [[-1,0,'L'],[-1,-1,'Q'],[0,-1,'U'],[1,0,'R'],[0,1,'D'],[-1,1,'Z']]
	def move(path,x,y,field): #移动函数
		pathlen = len(path)
		resultlen = len(self.result)
		if pathlen >= resultlen and resultlen != 0:#这个条件很重要,当此时查找的路线已经比之前的长时就没必要查找了
			return
		field[y][x] = pathlen + 1 #把自己变成1, 防止无限递归
		if x in [0, 8] or y in [0, 8]: #如果到终点了
			if resultlen > pathlen or resultlen == 0:
				self.result = path#将路径放入结果
				return
		dirs = self.dirs1
		if y in self.quickmodlist:#发现比取模快上那么点
			dirs = self.dirs2
		for d in dirs: #检查六个方向
			if y+d[1] in range(0, 9) and x+d[0] in range(0, 9):
				if field[y+d[1]][x+d[0]] > pathlen+1 or field[y+d[1]][x+d[0]] == 0: #如果某个方向为0
					move(path+d[2],x+d[0],y+d[1],field) #递归
	move('',self.catpos[0],self.catpos[1],data) #调用移动函数, 此时路径为空
	self.waysmap = data
	#self.PrintMap()
	#print ''
	#self.PrintWaysMap()
	return self.result

原理很简单,递归查找可能的路线,注意返回条件(如路线超过了前面的则返回或者是找到了新的路线),这将直接决定你搜索的时间,原则是找到最短路径,这里可以加上通路数。
另外假设从0行开始,围住神经猫地图有个特性就是能取2的模为1的行都可以向右上,右下走,而为0的则可以向左上,左下走,所以要用行数判断具体的行走方向。

被围住不代表胜利,无路可走才是胜利,所以这里要加上被围时的算法:

def shuffle(self, dataList):
	l = len(dataList)
	for i in xrange(l):
		j = random.randint(i,l-1)
		dataList[j],dataList[i] = dataList[i],dataList[j]
			
def GetRandomWays(self, col, row):
	if col in [0, self.col-1] or row in [0, self.row-1]:
		return col, row
	dirs = self.dirs1
	if row in self.quickmodlist:
		dirs = self.dirs2
	randomlist = []
	
	ways = 0
	for d in dirs: #检查六个方向
		if self.IsFree(col+d[0], row+d[1]):
			#tempway = self.GetWays(col+d[0], row+d[1])
			#if tempway > ways:
			#	ways = tempway
			#	randomlist = [(col+d[0], row+d[1])]
			#elif tempway == ways:
				randomlist.append((col+d[0], row+d[1]))

	self.shuffle(randomlist)
	if len(randomlist):
		if len(randomlist) > 1 and (self.oldpos[0], self.oldpos[1]) in randomlist:
			randomlist.remove((self.oldpos[0], self.oldpos[1]))
		return randomlist[0][0],  randomlist[0][1]
			
	return -2,-2

排除掉自己之前的位置,当然,实在无路可走则走之前的位置,这里说的无路可走是指通路相等的情况。
这个算法实现起来并不难,但有很多细节需要注意。

github:https://github.com/whitefirer/catgame/ 中的catgame2.py

18七/150

大到暴雨跟大雨转暴雨的区别

坑爹,我才发现百度回的天气大雨转暴雨并不包括大到暴雨的情况,大雨转暴雨是指现在下的是大雨取前面的,大到暴雨是指现在下的是暴雨,取后面的,今天打开看到天气图片又是空的,无奈在字典里又把这几种情况映射进去了- -

5五/150

一个桌面天气应用的实现

先上最终结果图:

desktopweather

说说怎么实现

其实代码什么的,经过这么多年经历也知道了,技术什么的并不是那么的重要,重要的一是idea,二是资金与平台,所以代码放在手里还不如共享出来交流提高技术呢。

而且这个代码只要有思路实现起来也并不是那么困难,虽然中间会遇到些问题,但问题解决解决就行嘛。起因是一个盆友问我能不能帮他实现一个桌面天气那样的功能,我说没问题一个周末就能搞定,很多人可能觉得一个周末能搞定是不是原来就有代码或者是说笑呢,我之所以说一个周末能搞定实际是我想了下实现框架,并没有那么复杂。

首先数据网上已经有很多API了,雅虎的,百度的,新浪的,中国气象网的。。。总之很多,拿过来用就是。这里我选择了百度LBS API。

其次界面,我们可以用DuiLib,自己造轮子虽然是个办法,未免本末倒置,要记住这里并不我们自己写UI库练技术(喂喂,写游戏的UI编辑还不够累吗,封装了多少控件,这种事做几次就够了),而是尽量用比较方便好用的方法快速为朋友实现功能,而且DuiLib已经基本能满足我们这个需求了。

再者有了数据跟界面,我们需要的是数据传输,方法很多,我们也可以自己实现(socket谁不会嘛),但缺点很明显无法应付太多的复杂情况,这里我选择了libcurl,一个很成熟的库,很多商业化的代码里都有用到。

最后一步就是数据解析然后显示在界面上了,这里几个问题是,数据的编码,我指的是文本编码,这里没有太多好办法,我写了个类来处理这些情况,另外一个就是数据格式,api过来的数据可以是xml跟json两种,这里我选择用jsoncpp来解json,之前考虑过cjson,但发现其实jsoncpp更好用。这里当然可以自己实现,还记得上次写的fireplayer解歌词吗,其实没太大区别,上次的解歌词,用了个链表管理了所有时间跟歌词的关系,状态机解出value,这次要自己实现最多换个map,但用过python后就会发现这种序列化的东西直接就能拿来用,在c++里这么费力的事,人家很容易就搞定了,所以,专业的事让专业的库来做,不要强行造轮子,有些事做几次就好了,不到万不得已,没必要。至于图片,呵呵,从百度天气拉的。

说这么多,实际实现也会遇到一些困难的,比如duilib我之前没用过呀,没关系,第一天就先干这事,边看代码边实现几个demo,熟悉下它的用法与原理,最后把资源当一个皮肤打包起来用了- -。libcurl当然也会遇到些问题,慢慢来,先调通,编码什么的也可以解决的,记得一定要打日志或者调试断点,看看收到的到底是什么,jsoncpp也一样,很关系一点是配置好环境。第一天就做这些事了。值得注意的是我为了减少dll,编译时配置,修改了一些库文件,最终只用带一个libcurl.dll就行。

第二天当然是具体实现与调试了,其中自定位是个麻烦事- -,自己看代码体会吧,其它的都很简单,一些判断,但要注意一些特殊情况。麻烦的是将一个个资源跟天气对应上,我曾笑谈,雨夹雪转雷阵雨伴有冰雹这种奇葩天气说不定都会传过来。最终代码量也就一两千行的样子。所以一个周末实现不是梦。当然如果全部造轮子那需要的时间就更长了。建议如果你是学生的话,还是老老实实每个模块自己实现一个对等的功能,像我这种实现过的就不是很有必要了,毕竟最后我要得到的是一个商业化的结果。

有一天雷阵雨转阵雨发现一个BUG

修正了一个BUG,我一开始想用strtok通过“转”字来切出第一个天气作为图片的依据,但实际上那个参数是切字符串的字符集,这里应该用wcstok来切汉字。至于为什么是雷阵雨转阵雨时发现的BUG,是因为阵的第一个字节是d7,转的第一个字节也是d7,如果没有遇到d7开头的汉字,看上去就没有问题,截图如下:

4五/150

如何用python画心

知乎了提了个问题如何用C画心,于是各大神各显神勇,我于是写了个用python在画板上画心,虽然没有Milo Yip 大神那么牛B哄哄的代码,但胜在简单,博君一笑罢了。。

 

画心

# -*- coding: gbk -*-
from ctypes import *
from time import sleep
import os, math
advapi32 = windll.LoadLibrary('advapi32.dll')
user32 = windll.LoadLibrary('user32.dll')

def DrawTo(x1, y1, x2, y2):
	user32.SetCursorPos(int(x1), int(y1))
	user32.mouse_event(0x0002, 0, 0, 0, 0)
	user32.SetCursorPos(int(x2), int(y2))
	user32.mouse_event(0x0004, 0, 0, 0, 0)
	sleep(0.01)
	
def MoveTo(x, y):
	user32.SetCursorPos(int(x), int(y))

def DrawRotateEllipse(x, y, r1, r2, ll, rl, a, starta, enda):
	sina = math.sin(a);
	cosa = math.cos(a);
	nx,ny = 0,0
	ox,oy = 0,0
	for i in range(starta, enda+1):
		xorig =  r1 * math.cos((i) * (math.pi/180));
		yorig =  r2 * math.sin((i) * (math.pi/180));
		if nx != 0 and ny != 0:
			ox = nx
			oy = ny
		nx = x + xorig * cosa + yorig * sina;
		ny = y + yorig * cosa - xorig * sina;
		if(0==i) or (nx<ll) or (nx>rl):
			MoveTo(nx, ny)
		else:
			DrawTo(ox, oy, nx, ny)
			

os.startfile("mspaint")
sleep(0.5)
user32.ShowWindow(user32.GetForegroundWindow(), 3)
sleep(0.5)

x = 300.0
y = 200.0
DrawRotateEllipse(x, y+160, y/3, y*2/3, 0, x, math.pi/4, 0, 360);
DrawRotateEllipse(x, y+160, y/3, y*2/3, x, x*2 , -math.pi/4, 91, 360);
DrawRotateEllipse(x, y+160, y/3, y*2/3, x, x*2 , -math.pi/4, 0, 90);#因为在WIN7以上系统画图框更高,加个偏移
好了,现在你可以假装是自己在电脑上徒手画心形了- -

好了,现在你可以假装是自己在电脑上徒手画心形了- -

6六/140

[换个标题]论如何为生活娱乐写代码

今天早上打开百度来,发现Ta改版成有背景图片的了(还是早就变了?只是我没用贴登陆?),十分不爽,于是写了一个脚本来拉背景定时设成壁纸:

# -*- coding: gbk -*-
import os
import urllib
import time,random
from PIL import Image #注意这里变了
from ctypes import *
advapi32 = windll.LoadLibrary('advapi32.dll')
user32 = windll.LoadLibrary('user32.dll')
STORE_DIR = 'F:/Pictures/'
DOWLOAD_URL = 'http://1.su.bdimg.com/skin/'#我会告诉你还有个路径是skin_zoom吗

def setBMPWallpaper(imagepath):
	k = c_long(0)
	advapi32.RegOpenKeyA(0x80000001,"Control Panel\\Desktop", byref(k))
	#print k
	advapi32.RegSetValueExA(k, "TileWallpaper", 0, 1, "0", 1)
	advapi32.RegSetValueExA(k, "Wallpaper", 0, 1, imagepath, len(imagepath))
	user32.SystemParametersInfoA(0x0014,imagepath, None,1+2)
	advapi32.RegCloseKey(k)

def convent2BMP(picFile):
	bmpImage = Image.open(picFile)
	print '设置壁纸' + picFile
	newPath = STORE_DIR + 'today_wall_pic.bmp'
	try:
		bmpImage.save(newPath, "BMP")
	except IOError:
		 print '文件被占用了'
	return newPath

def downLoadImage(url):
	if url.startswith("http"):
		picName = url[url.rfind("/") + 1:]
		picName = STORE_DIR + picName

		if os.path.exists(STORE_DIR):
			pass#我就不告诉你我要干嘛
		else:
			os.makedirs(STORE_DIR)
		if os.path.exists(picName):
			pass#我就不告诉你要我干嘛
		else: 
			print "" + url
			filename,msg = '',''
			filename,msg= urllib.urlretrieve(url, picName)
			#print filename,msg,msg.type
			if 'image' in msg.type:
				print "" + picName + " "
				return picName
			else:
				os.remove(picName)
				return ''
	else:
		print url + "非法地址"
	return ''

#我懒得写main了
i = 1
print '开始更新'
while len(downLoadImage(DOWLOAD_URL + '%d.jpg'%i)) > 0:
	i = i+1
print '更新完毕'
randomNum = random.randint(1, 149)
setBMPWallpaper(convent2BMP(STORE_DIR + '%d.jpg'%randomNum)
t = time.time()
while True:
	if time.time() - t > 20:
		t = time.time() randomNum = random.randint(1, 149)
		setBMPWallpaper(convent2BMP(STORE_DIR + '%d.jpg'%randomNum)))

不要控制台请改成pyw,不要CPU请自己打包,要效率请自己换成C/C++,要扩展请自己改成文件夹遍历添至列表,核心思想是标题,发表的目的是补好久没发文的空档,果然写代码的动力是娱乐,仅供娱乐。

------------------------------------------------------华丽的分割线--------------------------------------------------------------------

本以为折腾完毕,然后又想到可以在设壁纸的同时画点什么上去,于是又有了下面的东西:

     # -*- coding: gbk -*-
import os
import urllib
import time, random
from PIL import, ImageFont, ImageDraw
from ctypes import *
advapi32 = windll.LoadLibrary('advapi32.dll')
user32 = windll.LoadLibrary('user32.dll')
STORE_DIR = 'F:/Pictures/'
DOWLOAD_URL = 'http://1.su.bdimg.com/skin/'

def setBMPWallpaper(imagepath):
     k = c_long(0)
     advapi32.RegOpenKeyA(0x80000001,"Control Panel\\Desktop", byref(k))
     advapi32.RegSetValueExA(k, "TileWallpaper", 0, 1, "0", 1)
     advapi32.RegSetValueExA(k, "Wallpaper", 0, 1, imagepath, len(imagepath))
     user32.SystemParametersInfoA(0x0014,imagepath, None,1+2)
     advapi32.RegCloseKey(k)

def convent2BMP(picFile):
     bmpImage = Image.open(picFile)
     #bmpImage = bmpImage.rotate(45)
     SetDate(bmpImage)
     print '设置壁纸' + picFile
     newPath = STORE_DIR + 'temp_today_wall_pic.bmp'
     try:
          bmpImage.save(newPath, "BMP")
     except IOError:
          print '文件被占用了'
     return newPath

tipslist = [
     [(1000, 50), (0xff,0x2a,0), '莫等闲,\n白了少年头,\n空悲切!', '\n'],
     [(1000, 200), (0x11,0x2a,0xff), '山不在高,有仙则名。水不在深,有龙则灵。斯是陋室,惟吾德馨。苔痕上阶绿,草色入帘青。谈笑有鸿儒,往来无白丁。可以调素琴,阅金经。无丝竹之乱耳,无案牍之劳形。南阳诸葛庐,西蜀子云亭。孔子云:何陋之有?'.replace('。','。\n'), '\n'],
     [(1000, 100), (0x00,0xfa,0), '东方欲晓,莫道君行早。踏遍青山人未老,风景这边独好。'.replace('。','。\n'), '\n']
]

def SetDate(image):
     font = ImageFont.truetype('msyh.ttf',30) 

     draw = ImageDraw.Draw(image)
     n = random.randint(1, len(tipslist)) - 1
     if n < 0:
          n = 0
     tip = tipslist[n]
     x, y = tip[0]
     fontcolor =  tip[1]
     c = tip[3]
     strlist = tip[2].split(c)

     dy = 0
     for i in strlist:
          draw.text((1000,y+dy),unicode(i, 'gbk'),font=font,fill=fontcolor)
          dy += 35
     t = time.localtime()
     #draw.text((1000,30),u'%d年%d月%d日'%(t[0],t[1],t[2]),font=font,fill=fontcolor) 
     draw = ImageDraw.Draw(image) 
     del draw 

randomNum = random.randint(1, 149)
changeflag = True
setBMPWallpaper(convent2BMP(STORE_DIR + 'today_wall_pic.bmp'))

因为会产生"ImportError: The _imagingft C module is not installed"的问题,所以换成了Pillow,效果如下:

2三/140

感谢2013,展望2014

抱歉,也许你们会发现2013我没有发表过新文章了.今天有位童鞋提出了疑问,主要是2012年年末有不愉快的事情发生,具体情况只有少数朋友知道,我想也没必要让大家知道吧.其实博客空白的2013年是我工作以来最快乐的一年(你也可以当成是我快乐的闭关23333),谢谢.

2013年的博客我很多都是自存在EverNote里.

以这个为契机,我今年也就是2014年再次开始写博客吧.

 

欢迎大家再次围观或支持或反对我,谢谢!

 

4一/132

末日后第一个新年,Oh yeah!

 

最后给大家个新年福利~!:dweep

这是我之前一直在玩的游戏,很有趣的,可以练练你尚未开发的大脑哦,我发的所有关都已经打开了,大家努力通关吧~

 

再多嘴一句,我原来的百度链接已经改成了http://hi.baidu.com/whitefirer_。。。

19十一/120

偷天换日

娱乐下,哈哈~

import this

print this.d['V'] + ' ' + this.d['Y'] + this.d['B'] + this.d['I'] + this.d['R'] + ' ' + this.d['H']
18十一/1214

终于可以休息一下下了

如题 ,我离职了。

 

PS:为这份工作,好久没更新博客了,不好意思。。。

7八/1210

荣辱不惊,坐看成败

背景:某个异次元有着无数吐槽点的奥运会上(这个次元里,韩国取代了朝鲜,并在中国之上,美国则被风吹走了,俄罗斯辉煌不再),我们的飞人再次被上天抛弃,8年来不断坚持,曾几何时,见到他就会有必胜的信念,然而他身上承载了太多的压力,他本可以没遗憾,该拿的奖的都拿过了,但是为了这个国家却要忍受13亿人的期望或漫骂,激情与速度变成了沉重的负担。但是,今天再次的发生,或许他还会坚持体育,或许会转身别的,这将是他人生新的旅程!
周公恐惧流言日,王莽恭谦未篡时。即使是曹操也会有赤壁,即使是拿破仑也会有滑铁卢。但是人生如此,有何憾焉?!

享受吧,人生的精彩再于你的内涵,这就是真谛,荣辱不惊,坐看成败,下一秒,你就是传奇。
歌曲: 难说再见
 

附:

李宁退役:李宁在1984年的洛杉矶奥运会中取得了优异的成绩,这主要是在于1984年的洛杉矶奥运会,爱到了大多数东欧国家的抵制不参加,许多高手并没有来参加比赛,换句话说中国队在1984年还不具备这么强的夺金实力,在高手缺席的情况下,李宁获得了三金、二银、一铜的好成绩。而在1988年的汉城奥运会中,由于没有受到抵制,各参赛国都派出了强大的阵容,而此时的中国对李宁的呼声也很高,就像今年的刘翔一样,承担着很大的压力,导制比赛中发挥失常从鞍马上面掉下来,在吊环比赛中也出现了严重的错误,回国后国人并没有理解他,认为他是在丢中国人的脸,不配是体操王子,以及报纸舆论的压力,导制李宁心灰意冷,在1989年选择退役,投身健力宝公司,并在1990年辞职,选择下海经商,并有了我们现在所喜欢的李宁品牌,并且是国内第一家在香港成功上市的运动品牌。要想知道更加详细的内容你可以看看杨澜对李宁的访谈录。

详细李宁创业故事

第 1 页,共 3 页
1
2
3