Loading…
-
用Delphi开发A片扫描器
Posted on 2011-05-14
这里,来讲一个用小创意干大事(俗称小炮打恐龙)的故事。
这个故事的结局是我们可以开发一个能找出电脑中所有A片的程序,这是个集合了影像分析、画面色块分层、人工智能等复杂算法的复杂的玩意。
好吧,其实这个程序只是简单读了下文件头而已(喂喂,那位拿板砖的同学请把板砖放下)。
我们假设一般人会把A片的扩展名改掉(例如改成txt、bmp等格式。曾经的realplayer年代有人会把rmvb格式的A片改成avi格式,现在由于暴风射手之流的出现导致这种方法不灵了),于是我们只有扫描一下文件的头部数据判断这个文件是不是一个影像文件,然后再判断这个文件的扩展名是不是一个影像文件的扩展名,如果不是自然就很可能是A片了(如果是的话应该就是阿凡达这类的电影了,你总不能说人家是A片吧)。
先送上队列遍历文件的代码(递归算法在这里更容易理解,但实际上很容易超栈溢出):
function EnumFileInQueue(path:PChar):Longint;stdcall; var searchRec:TSearchRec; found:Integer; tmpStr:String; curDir:PChar; dirs:TQueue; begin Result:=0;//查找结果(文件数) dirs:=TQueue.Create;//创建目录队列 dirs.Push(path);//将起始搜索路径入队 curDir:=dirs.Pop;//出队 while (curDir<> nil) do begin tmpStr:=StrPas(curDir)+'\*.*'; found:=FindFirst(tmpStr,faAnyFile,searchRec); while found=0 do begin if (searchRec.Attr and faDirectory)<>0 then begin if (searchRec.Name <> '.') and (searchRec.Name <> '..') then begin tmpStr:=StrPas(curDir)+'\'+searchRec.Name; dirs.Push(StrNew(PChar(tmpStr))); end; end //如果找到的是个文件 else begin Result:=Result+1; //form1.Label2.Caption := StrPas(curDir)+'\'; //form1.Label1.Caption :=(StrPas(curDir)+'\'+searchRec.Name); if isA(StrPas(curDir)+'\'+searchRec.Name) then begin Form1.Memo1.Lines.Add(StrPas(curDir)+'\'+searchRec.Name); //form1.Button2.Click; end; end; found:=FindNext(searchRec); end; if dirs.Count > 0 then curDir:=dirs.Pop else curDir:=nil; end; dirs.Free; FindClose(searchRec); end;然后是获得文件头部信息的代码:
Function GetFileBegin(const Filename: String): String; Var i: integer; Source: tfilestream; s2, s3, s, s4, s5: String; Buf: Array[0..MaxBuf-1] Of byte; Begin result:=''; Try Source:=tfilestream.Create(Filename, fmOpenRead Or fmShareDenyNone); If Source.Size<10 Then Exit; Source.Seek(0, sofrombeginning); Try Source.Read(Buf, SizeOf(Buf)); For i:=0 To MaxBuf-1 Do s:=s+IntToHex(Buf[i], 2); Source.Read(Buf, SizeOf(Buf)); For i:=0 To MaxBuf-1 Do s2:=s2+IntToHex(Buf[i], 2); Source.Read(Buf, SizeOf(Buf)); For i:=0 To MaxBuf-1 Do s3:=s3+IntToStr(Buf[i]); Source.Read(Buf, SizeOf(Buf)); For i:=0 To MaxBuf-1 Do s4:=s4+IntToStr(Buf[i]); Source.Read(Buf, SizeOf(Buf)); For i:=0 To MaxBuf-1 Do s5:=s5+IntToStr(Buf[i]); s:=s+s2+s3+s4+s5; result:=s; Finally Source.Free; End; Except result:=''; End; End;当用这个函数检测文件时,返回一个由字母和数字组成的字符串,代表着文件头信息。
接下来是判断是否是A片的函数:
function Determine(const FileName: String): boolean; var sbegin,stmp : string; begin Result := false; stmp :=ExtractFileExt(FileName); if((stmp='.rm')or(stmp='.rmvb')or(stmp='.mpq')or(stmp='.avi')or(stmp='.rm')or(stmp='.mpg')) then exit(false); if(GetFileSize(FileName) < 10242880) then exit(false); sbegin := GetFileBegin(FileName); if((pos('52494646', sbegin)=1) or (pos('2E524D', sbegin)=1) ) then exit(true); end;GetFileSize是我自己写的函数,可以获得文件大小,如果文件小于10242880字节就跳过检测(小于10MB的A片?)。
52494646和2E524D是rmvb和avi的头部信息,是使用上面的GetFileBegin函数算出来的,可以根据需要自己添加。
好了,一切已经完成。把程序编译出来拷到U盘里给朋友的电脑扫描一下吧(被拍不要找我…)。真简单,但真不和谐。
前些日子在微软技术部例会上听cxc大牛讲到一个类似的例子:如何找出电影的高潮部分呢?答案:用程序找出电影音量最大的部分就行了。——很简单,当然这个比较和谐。
-
Lua在游戏开发中的应用
Posted on 2010-05-18
前些日子我一直忙于开发微软技术俱乐部的AI比赛平台,在这个过程中总结了一些Lua在C#项目中的应用方法。
Lua 是一个小巧的脚本语言。该语言的设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua脚本可以很容易地被其它语言调用,也可以反过来调用其它语言的函数,这使得Lua在应用程序中可以被广泛应用。
在C#中使用Lua十分简单,我们先要下载LuaInterface:
LuaInterface is a library for integration between the Lua language and Microsoft .NET platform’s Common Language Runtime (CLR). Lua scripts can use it to instantiate CLR objects, access properties, call methods, and even handle events with Lua functions.
从"LuaInterface":http://luaforge.net/projects/luainterface/ 网站上可以下载到这个库。在你的项目中引用LuaInterface.dll后就可以开始了。
下面用一个电子宠物程序的代码演示一下使用方法:
//... /// <summary> /// Lua虚拟机 /// </summary> private static Lua luaVM = null; /// <summary> /// 宠物的构造函数 /// </summary> public Pet(PetForm _petForm, string _petName, string _petPath) { petState = new PetState(); petForm = _petForm; petName = _petName; //构造Lua虚拟机以解析宠物AI luaVM = new Lua(); //注册提供给宠物AI的API函数 Type tThis = this.GetType(); luaVM.RegisterFunction("PetDo", this, tThis.GetMethod("LuaPetDo")); luaVM.RegisterFunction("PetDoFrame", this, tThis.GetMethod("LuaPetDoFrame")); luaVM.RegisterFunction("Sleep", this, tThis.GetMethod("LuaSleep")); //载入AI文件 luaVM.DoFile(System.AppDomain.CurrentDomain.BaseDirectory + _petPath + "\\ai.lua"); }其中RegisterFunction作用是注册C#代码中的一个public(最新版本的LuaInterface支持private)函数来供Lua脚本使用,其中无需关心参数的个数以及类型。
PetDo("Sleep");执行DoFile后会调用Lua脚本,后者则调用C#中的PetDo函数完成指定动作。