备忘录模式
前序
相信玩游戏每个人都会,今天就来讲讲关于游戏进度的保存机制,也就是备忘录模式。
备忘录模式
在不破坏封装性的前提下,捕获一个对象的内部状态,兵在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
实现方式(UML类图)
实现代码
#include <stdio.h>
// 角色状态存信息
class RoleStateMemento
{
public:
int vit;
int atk;
int def;
int level;
int pass;
RoleStateMemento(int _vit, int _atk, int _def, int _level, int _pass) : vit(_vit), atk(_atk), def(_def), level(_level), pass(_pass){}
};
// 游戏角色
class GameRole : public RoleStateMemento
{
public:
GameRole() : RoleStateMemento(100, 100, 100, 1, 1) {}
RoleStateMemento* SaveState()
{
return new RoleStateMemento(vit, atk, def, level, pass);
}
void RecoveryState(RoleStateMemento* pMemento)
{
vit = pMemento->vit;
atk = pMemento->atk;
def = pMemento->def;
level = pMemento->level;
pass = pMemento->pass;
}
void Fight()
{
vit -= 20; // 第一关损失了20点血
pass++;
vit -= 40; // 第二关损失了40点血
level++; // 升级了
atk++;
def++;
pass++;
vit = 0; // 第三关直接被Boss干掉了
}
void StateDisplay()
{
printf("当前血量: %d\n", vit);
printf("当前攻击力: %d\n", atk);
printf("当前防御力: %d\n", def);
printf("当前等级: %d\n", level);
printf("当前关卡: %d\n\n", pass);
}
};
// 角色状态管理者
class RoleStateCaretaker
{
public:
RoleStateMemento* pMemento;
};
int main()
{
// 大战Boss前
GameRole* lixiaoyao = new GameRole();
// 保存进度
RoleStateCaretaker* stateAdmin = new RoleStateCaretaker();
stateAdmin->pMemento = lixiaoyao->SaveState();
// 大战Boss时,直接被干掉了
lixiaoyao->Fight();
lixiaoyao->StateDisplay();
// 恢复之前的进度
if(lixiaoyao->vit == 0)
{
lixiaoyao->RecoveryState(stateAdmin->pMemento);
lixiaoyao->StateDisplay();
}
delete stateAdmin->pMemento;
delete stateAdmin;
delete lixiaoyao;
return 0;
}
运行结果
所有文件打包下载
posted @
2011-11-13 23:48 lwch 阅读(2678) |
评论 (1) |
编辑 收藏
1. 无话可说的sudo apt-get install trac
2. 创建用户,sudo useradd -m username
3. 修改密码,sudo passwd username
4. 在/var/www中创建trac目录,sudo mkdir /var/www/trac
5. 修改trac权限,sudo chmod 777 /var/www/trac
6. 初始化trac目录,sudo trac-admin /var/www/trac initenv
7. 将user加入.htpasswd文件中,sudo passwd -c /var/www/trac/.htpasswd username(添加第一个用户时用这个命令,否则sudo passwd -b /var/www/trac/.htpasswd username password)
8. 为第一个用户添加TRAC_ADMIN权限,sudo trac-admin /var/www/trac permission add username
9. 修改trac的配置文件,sudo vim /var/www/trac/conf/trac.ini(可选)
10. 在后台启动trac服务,sudo tracd -d -p port --basic-auth="*",/var/www/trac/.htpasswd,/var/www/trac /var/www/trac
11. 修改Nginx配置,sudo vim /etc/nginx/sites-enabled/default
加入
1 location /trac {
2 auth_basic "trac";
3 auth_basic_user_file /var/www/war/trac/.htpasswd;
4 proxy_pass http://127.0.0.1:port;
5 }
这里使用代理的模式来将发出的http请求转发给port端口
12. 重启Nginx服务器,sudo /etc/init.d/nginx restart
13. 登录trac进入后台管理(如果在permissions里添加一个用户,则这个用户必须加到.htpasswd文件中)
可见trac的配置过程极其复杂
posted @
2011-09-30 00:03 lwch 阅读(2884) |
评论 (2) |
编辑 收藏
1.创建一个类继承自CCLayer
2.为这个类添加一个静态的show函数以创建出当前对象所对应的场景
1 void CMainFrameWork::show()
2 {
3 CCScene* scene = CCScene::node();
4 pMainFrameWork = new CMainFrameWork();
5 pMainFrameWork->init();
6 scene->addChild(pMainFrameWork);
7 CCScene* pScene = CCDirector::sharedDirector()->getRunningScene();
8 if(!pScene)
9 CCDirector::sharedDirector()->runWithScene(scene);
10 else
11 {
12 CCDirector::sharedDirector()->replaceScene(scene);
13 }
14 }
3.添加init函数用以对当前对象进行初始化
4.当然你也可以在继承下来的onEnter函数内写入你的初始化代码
以上为一个场景对象的实现过程
posted @
2011-08-18 22:34 lwch 阅读(2008) |
评论 (1) |
编辑 收藏
适配器模式
前序
姚明,大家都认识吧。在他刚去NBA的时候,什么都听不懂,必须在旁边配个翻译,否则就无法听懂教练在说什么。这也正符合了设计模式中的一种模式:适配器模式。
适配器模式
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
实现方式(UML类图)
实现代码
#include <stdio.h>
// 球员
class Player
{
public:
Player(char* _name) : name(_name){}
virtual void Attack()=0;
virtual void Defense()=0;
char* name;
};
// 前锋
class Forwards : public Player
{
public:
Forwards(char* name) : Player(name){}
virtual void Attack()
{
printf("前锋 %s 进攻\n", name);
}
virtual void Defense()
{
printf("前锋 %s 防守\n", name);
}
};
// 中锋
class Center : public Player
{
public:
Center(char* name) : Player(name){}
virtual void Attack()
{
printf("中锋 %s 进攻\n", name);
}
virtual void Defense()
{
printf("中锋 %s 防守\n", name);
}
};
// 后卫
class Guards : public Player
{
public:
Guards(char* name) : Player(name){}
virtual void Attack()
{
printf("后卫 %s 进攻\n", name);
}
virtual void Defense()
{
printf("后卫 %s 防守\n", name);
}
};
// 外籍中锋
class ForeignCenter
{
public:
void Attack()
{
printf("外籍中锋 %s 进攻\n", name);
}
void Defense()
{
printf("外籍中锋 %s 防守\n", name);
}
char* name;
};
// 翻译者
class Translator : public Player
{
public:
Translator(char* name) : Player(name)
{
wjzf.name = name;
}
virtual void Attack()
{
wjzf.Attack();
}
virtual void Defense()
{
wjzf.Defense();
}
protected:
ForeignCenter wjzf;
};
int main()
{
Player* b = new Forwards("巴蒂尔");
b->Attack();
Player* m = new Guards("麦克格雷迪");
m->Attack();
Player* ym = new Translator("姚明");
ym->Attack();
ym->Defense();
delete b;
delete m;
delete ym;
return 0;
}
运行结果
所有文件打包下载
posted @
2011-08-14 15:27 lwch 阅读(2679) |
评论 (4) |
编辑 收藏
周一
早晨来到公司,领到了电脑,于是安装了各种软件。到了中午上司给我安排工作了,说是要用Redis数据库做一个小练习,心想Redis是神马玩意,听都没听说过。于是各种Google,到它官网上下载下来了源码,PSCP将下载到的源码放到Linux里(我们这连Linux用的是Putty,不知道有没其他好用的软件没)。tar解包,make编译,看到提示make test什么的于是纠结了半天,后来发现make install就可以搞定。至此周一工作完毕。
周二
心想今天可以开始做练习了,于是继续在Google上找各种资料。后来发现telnet可以测试它的指令,于是cmd->telnet,“‘telnet’不是内部或外部命令”,无奈只好去添加Windows组件。安装好后继续telnet,果然连上了,然后简单的测试了一下Get,Set,LPush,RPush,LRange等命令,对其返回数据包的格式有了一些了解。然后从网上下载来一个Redis-Client的源码,发现是Linux下的,于是对其改造,改造期间产生的主要问题是Linux和Windows的Socket编程方面的,头文件和一些宏的不同,Google找到解决方法之后编译成功。十分高兴,然后测试了一下Set和Get指令,杯具发生了!!!返回的数据包根据它的处理方式,完全不正确(可能这个Client对应的是老版本的Redis)。于是继续分析各种命令及其返回结果,最后在下午5点多终于完成了第一个版本。至此周二工作完毕。
周三
早晨来到公司,叫我的上司来看了下昨天写的代码,然后他指出了一些编码上的问题,随后叫我自己写单元测试用例。于是把该分开的函数分开为若干的文件,编写测试用例(都怪我软测上课没认真听,反反复复写了好几个版本的测试用例),最后终于在下班前完成了。至此Redis部分的练习完成了,从中学到了如何在Linux里安装软件,如何将Windows里的文件传给远端的Linux,如何使用telnet命令,如何将Linux下关于网络的代码移植到Windows下等等。最后上司给了我一份300+页的关于Office-Plugin的文档,说明天开始做关于Office的练习,然后大致看了下wiki,了解了一下要求。至此周三工作完毕。
周四
早晨来到公司,上司给我详细的说明了一下要求,然后开始看那份文档(那份文档除了教你怎么创建工程,调试工程其他对Word内容的操作什么都没有),于是继续Google查找相关的资料,到了中午大致完成了wiki上的要求,然后给他看了一下,他提出一些建议和要求。无奈只好下午继续修改,最初设想是在Word里创建一个Pane来对Word中的表格进行操作,上司过来给他介绍了一下,他说这样不行,最好是所见所得模式,光标定在哪就可以在哪编辑。于是继续Google查资料,发现Word中可以创建OLE对象的ComboBox等,于是简单的写了点代码创建它。至此周四工作完毕。
周五
终于熬到周五了,各种疲惫啊,尤其是昨天看了一天资料,看的头晕乎乎的!!早上上司过来了解一下情况,我给他介绍了一下可以动态生成ComboBox,他看后表示创建出来的ComboBox会改变原来单元格的大小,于是把这部分给删掉了(汗那)。添加了一个保存功能,要求对表格内指定区域的数据保存到另一文件(神那!!真要这么做为什么不用Excel)。于是继续查资料,写出了第一个版本,测试后发现Word中文字和其他对象得分开处理,第一个版本中只能保存文字,无法保存图片等其他对象,继续查资料,发现了CopyAsPicture函数用于拷贝图片。最后简单了写了一些代码,终于完成了!还没给上司看过。至此周五工作完毕。
总结
在公司里学到了不少东西,包括Linux方面的和Windows方面的。我们每天下午吃完午饭就会组织培训,从中我学到了如何用samba来共享Linux的一个目录作为Windows的一个映射的磁盘(原来用PSCP实在不是什么简单的方法)。使我体会最大的是公司里没人会来教你,都得靠你自己去琢磨。
就写这么多了,文笔不行啊。。
posted @
2011-07-16 13:50 lwch 阅读(3613) |
评论 (7) |
编辑 收藏
我们先了看下Alt组合子的分析代码
1 virtual O Parser(I& input)
2 {
3 I temp = input;
4 if(O Result = left.Parser(input)) return Result;
5 input = temp;
6 if(O Result = right.Parser(input)) return Result;
7 input = temp;
8 O Result(GetMM());
9 return Result;
10 }
当left分析失败时会将原先的input值重新赋值给input,但此时并没有改变SymbolStack和StringStack,应此当第一次分析失败时SymbolStack和StringStack中会包含一些重复的值.当然其他组合子同样存在这个问题.
应此我为CParser_Input增加了两个成员变量保存此时的SymbolStack和StringStack的Size,当SymbolStack和StringStack Push的时候同时增加input相应的值.
最后重载CParser_Input的operator=赋值操作符,在其中根据原先的SymbolStack和StringStack的Size来弹出相应数量的重复值
1 CParser_Input& operator=(CParser_Input& _value)
2 {
3 LexerTokenList = _value.LexerTokenList;
4 index = _value.index;
5
6 if(_value.symbolCount < symbolCount && _value.symbolCount)
7 {
8 int Count = symbolCount - _value.symbolCount;
9 for(int i=0;i<Count;i++) SymbolStack.Pop();
10 }
11
12 if(_value.stringCount < stringCount && _value.stringCount)
13 {
14 int Count = stringCount - _value.stringCount;
15 for(int i=0;i<Count;i++) StringStack.Pop();
16 }
17
18 symbolCount = SymbolStack.Size();
19 stringCount = StringStack.Size();
20 return *this;
21 }
以此来解决SymbolStack和StringStack的同步问题.
posted @
2011-07-10 22:13 lwch 阅读(1118) |
评论 (0) |
编辑 收藏
1.首先我们需要一个结构来表示CPU所有的16位和8位寄存器(见Library\Struct\Register.h)
1 #pragma once
2 #include "..\Common\Base.h"
3
4 struct Register_16_Bit
5 {
6 // General Register
7 struct
8 {
9 BYTE AH; // 8Bit
10 BYTE AL; // 8Bit
11 }AX;
12 struct
13 {
14 BYTE BH; // 8Bit
15 BYTE BL; // 8Bit
16 }BX;
17 struct
18 {
19 BYTE CH; // 8Bit
20 BYTE CL; // 8Bit
21 }CX;
22 struct
23 {
24 BYTE DH; // 8Bit
25 BYTE DL; // 8Bit
26 }DX;
27
28 // Segment Register
29 USHORT CS;
30 USHORT DS;
31 USHORT SS;
32 USHORT ES;
33
34 // Special Register
35 USHORT IP;
36 USHORT SP;
37 USHORT BP;
38 USHORT SI;
39 USHORT DI;
40 struct
41 {
42 BYTE OF : 1;
43 BYTE DF : 1;
44 BYTE IF : 1;
45 BYTE TF : 1;
46 BYTE SF : 1;
47 BYTE ZF : 1;
48 BYTE AF : 1;
49 BYTE PF : 1;
50 BYTE CF : 1;
51 BYTE Reserve : 7;
52 }FR;
53
54 Register_16_Bit()
55 {
56 memset(this,0,sizeof(Register_16_Bit));
57 }
58 };
2.然后我们定义一个接口来抽象出分析过程(见Library\Disasm\DisasmContext.h)
1 #pragma once
2 #include "..\Common\Base.h"
3
4 class CDisasmContext
5 {
6 public:
7 virtual bool Disasm(BYTE*& ptr)=0;
8 protected:
9 enum OpCodeHeader;
10 };
Disasm函数用于对机器码进行分析并确定语义
OpCodeHeader是个枚举类型用于枚举每条指令的指令头(详情见8086指令手册)
3.我们定义一个Jmp类来对Jmp指令进行分析(见Library\Disasm\Jmp)
1 #pragma once
2 #include "..\DisasmContext.h"
3
4 class CJmp : public CDisasmContext
5 {
6 public:
7 virtual bool Disasm(BYTE*& ptr);
8 protected:
9 enum OpCodeHeader
10 {
11 JMP_SHORT = 0xEB, // 段内直接短跳
12 JMP_NEAR = 0xE9, // 段内直接跳
13 JMP_FAR = 0xEA, // 段间直接跳
14 JMP_IND = 0xFF, // 段内(外)间接跳
15 };
16
17 bool Jmp_Short(BYTE*& ptr);
18 bool Jmp_Near(BYTE*& ptr);
19 bool Jmp_Far(BYTE*& ptr);
20 };
其Disasm函数为
1 bool CJmp::Disasm(BYTE*& ptr)
2 {
3 if(Jmp_Short(ptr)) return true;
4 else if(Jmp_Near(ptr)) return true;
5 else if(Jmp_Far(ptr)) return true;
6 else return false;
7 }
4.我们同样定义一个CMov类来对Mov指令进行分析(见Library\Disasm\Mov)
5.最后我们定义一个CDisasm类来驱动整体框架(见Library\Disasm\Disasm.h)
1 class CDisasm
2 {
3 public:
4 bool Disasm(BYTE* ptr,int size);
5 protected:
6 CJmp Jmp;
7 CMov Mov;
8 };
其Disasm函数为(见Library\Disasm\Disasm.cpp)
1 bool CDisasm::Disasm(BYTE* ptr,int size)
2 {
3 BYTE* end = ptr + size;
4 while(ptr < end)
5 {
6 if(Jmp.Disasm(ptr));
7 else if(Mov.Disasm(ptr));
8 else return false;
9 }
10 return true;
11 }
具体的分析过程其实就是查表的过程,这里不一一列举出来了.
目前只翻译了部分Jmp和Mov指令,有兴趣的同学可以查表对其进行扩充.
所有代码及指令手册打包下载
posted @
2011-07-10 12:30 lwch 阅读(3807) |
评论 (9) |
编辑 收藏
摘要: 状态模式
“小菜,你们的加班没完没了了?”大鸟为晚上十点才到家的小菜打开了房门。
“嗨,没办法,公司的项目很急,所以要求要加班。”
“有这么急吗?这星期四天来你都在加班,有加班费吗?难道周末也要继续?”
“哪来什么加班费,周末估计是逃不了了。”小菜显然很疲惫,“经历把每个人每天的工作...
阅读全文
posted @
2011-07-03 22:05 lwch 阅读(2764) |
评论 (2) |
编辑 收藏
QLanguage开源项目地址:
http://qlanguage.codeplex.com1.AST的每个节点由2个域组成,这2个域分别表示当前节点的类型和附加信息。
2.AST的每个节点包含一个指向其子节点的顺序表。
3.AST的每个节点包含指向下一个节点的指针。
综上所述我们得到AST节点的代码:
1 class CSyntaxTreeNode
2 {
3 public:
4 CSyntaxTreeNode(int _type,int _value) : type(_type),value(_value){}
5
6 inline List<NAutoPtr<CSyntaxTreeNode>>& Child()
7 {
8 return child;
9 }
10
11 inline NAutoPtr<CSyntaxTreeNode> Next()
12 {
13 return next;
14 }
15
16 inline int& Type()
17 {
18 return type;
19 }
20
21 inline int& Value()
22 {
23 return value;
24 }
25 protected:
26 int type;
27 int value;
28 List<NAutoPtr<CSyntaxTreeNode>> child;
29 NAutoPtr<CSyntaxTreeNode> next;
30 };
然后我们给出了部分枚举来标识节点的类型:
1 // for type
2 enum TYPE
3 {
4 stNull,
5 stDeclare,
6 stFunction,
7 stParamterList,
8 stIf,
9 stDo,
10 stExp,
11 };
最后是一棵AST的整体结构:
1 class CParserAnalyze
2 {
3 public:
4 inline void Push(NAutoPtr<CSyntaxTreeNode>& Node)
5 {
6 SyntaxTreeStack.Push(Node);
7 }
8
9 inline NAutoPtr<CSyntaxTreeNode> Pop()
10 {
11 return SyntaxTreeStack.Pop();
12 }
13
14 inline NAutoPtr<CSyntaxTreeNode> Top()
15 {
16 return SyntaxTreeStack.Top();
17 }
18
19 inline NAutoPtr<CSyntaxTreeNode> Root()
20 {
21 return SyntaxTreeRoot;
22 }
23 protected:
24 NAutoPtr<CSyntaxTreeNode> SyntaxTreeRoot; // 语法树根节点
25 Stack<NAutoPtr<CSyntaxTreeNode>> SyntaxTreeStack; // 语法树栈
26 };
这里我们简单的分析一下分析过程:
以if语句为例,其组合子代码为:
1 if_desc = (str_if + exp_desc)[if_desc_first] +
2 (str_then + stmt_list)[if_desc_second] +
3 Parser_Combinator_Node::opt((str_else + stmt_list)[if_desc_third]) +
4 (str_end + str_if)[if_desc_fourth];
我们输入代码:
1 if a then
2 declare b as integer
3 end if
在做语法分析:
1.读入if a,a被归约为一条exp生成一个类型为exp的节点并压入AST的语法树栈。
2.if a被归约生成一个类型为stIf的节点并弹出栈顶的exp节点填充到新生成的stIf节点的第一个子节点。
3.读入then declare b as integer,integer被归约生成一个生类型为stDeclare的节点并压入语法树栈。
4.declare b as integer被归约为栈顶的stDeclare节点填充一个b标识符的子节点。
5.then declare b as integer被归约,首先弹出栈顶的stmt_list因为这里是stDeclare说明stmt_list有内容应此将栈顶的stIf的值域的最低位置为1。
6.else子句不存在。
7.整体被归约。
此时栈顶为stIf节点,其不包含next节点,有两个子节点分别为stExp和stDeclare。
分析过程如下图:
1.
2.
3.
4.
5.
6.
7.
posted @
2011-07-01 21:51 lwch 阅读(2168) |
评论 (2) |
编辑 收藏
1.类的定义
1 class a [inherit Object]
2 end class
2.类中可以包含(声明,函数,新类。其中除了class都含有public、private、protected和static属性)
1 class a
2 [public] declare a as string // 声明
3
4 [private] [static] function main() // 函数
5 end function
6
7 class b // 新类
8 end class
9 end class
3.变量声明
1 declare a as integer[,b as integer]
4.函数
1 function main([a as integer[,b as integer]])[as integer]
2 end function
5.stmt_list包含声明语句、if语句、do语句、while语句、for语句、switch语句和experience表达式
6.if语句
1 if experience then
2 stmt_list
3 [else stmt_list]
4 end if
7.do语句
1 do
2 stmt_list
3 while experience end
8.while语句
1 while experience do
2 stmt_list
3 end while
9.for语句
1 for stmt_list to experience by stmt_list do
2 stmt_list
3 next
10.switch语句
1 switch experience do
2 case experience:
3 [stmt_list]
4 [case experience:
5 [stmt_list]]
6 [default:
7 [stmt_list]]
8 end switch
11.experience表达式
1 函数调用语句
2 赋值语句
3 symbol
4 string
5 number
6 true
7 false
8 (+|-)experience
9 not experience
10 experience (&|||^|%) experience
11 experience (>|<|>=|<=|==|!=) experience
12 experience (+|-|*|/) experience
13 ++symbol
14 --symbol
15 symbol++
16 symbol--
12.函数调用语句
1 函数名(参数表)
13.赋值语句
1 变量=experience
组合子代码
1 program = *item;
2 item = declare_desc |
3 class_desc |
4 function_desc;
5 property_desc = str_public |
6 str_private |
7 str_protected;
8 declare_type = str_integer |
9 str_string |
10 str_bool |
11 str_real |
12 type_symbol;
13 paramter_desc_list = (type_symbol + str_as + declare_type) +
14 *(str_comma + type_symbol + str_as + declare_type);
15 paramter_value_list = exp_desc + *(str_comma + exp_desc);
16 declare_desc = str_declare + type_symbol + str_as + declare_type +
17 *(str_comma + type_symbol + str_as + declare_type);
18 class_desc = str_class + type_symbol +
19 Parser_Combinator_Node::opt(str_inherit + type_symbol +
20 *(str_comma + (type_symbol & Parser_Combinator_Node::not(str_class | str_function | property_desc | str_static)))
21 ) + *class_content_desc + str_end + str_class;
22 class_content_desc = (Parser_Combinator_Node::opt(property_desc) + Parser_Combinator_Node::opt(str_static) +
23 (declare_desc | function_desc)) |
24 class_desc;
25 function_desc = (str_function + type_symbol) +
26 (str_leftbracket + Parser_Combinator_Node::opt(paramter_desc_list) + str_rightbracket) +
27 Parser_Combinator_Node::opt(str_as + declare_type) +
28 stmt_list +
29 (str_end + str_function);
30 stmt_list = *(stmt & Parser_Combinator_Node::not(str_end));
31 stmt = declare_desc |
32 if_desc |
33 do_desc |
34 while_desc |
35 for_desc |
36 switch_desc |
37 exp_desc;
38 if_desc = (str_if + exp_desc) +
39 (str_then + stmt_list) +
40 Parser_Combinator_Node::opt(str_else + stmt_list) +
41 (str_end + str_if);
42 do_desc = (str_do + stmt_list) +
43 (str_while + exp_desc + str_end);
44 while_desc = str_while + exp_desc + str_do + stmt_list + str_end + str_while;
45 for_desc = str_for + stmt_list + str_to + exp_desc + str_by + stmt_list + str_do + stmt_list + str_next;
46 switch_desc = str_switch + exp_desc + str_do + case_list + str_end + str_switch;
47 case_list = *case_desc;
48 case_desc = (str_case + exp_desc + str_colon + stmt_list) |
49 (str_default + str_colon + stmt_list);
50 assign_desc = type_symbol + str_equal + exp_desc;
51 call_desc = type_symbol + str_leftbracket + Parser_Combinator_Node::opt(paramter_value_list) + str_rightbracket;
52 logic_desc = (str_not + compare_desc) |
53 (compare_desc + *((str_operator_and | str_operator_or | str_xor | str_mod) + compare_desc));
54 compare_desc = term_desc + *((str_bigger | str_smaller |
55 str_bigger_equal | str_smaller_equal |
56 str_equal_equal | str_not_equal) + term_desc);
57 term_desc = factor_desc + *((str_add | str_sub) + factor_desc);
58 factor_desc = self_desc + *((str_mul | str_div) + self_desc);
59 self_desc = (str_add_add + type_symbol) |
60 (str_sub_sub + type_symbol) |
61 (type_symbol + str_add_add) |
62 (type_symbol + str_sub_sub) |
63 value_desc;
64 value_desc = call_desc |
65 assign_desc |
66 type_symbol |
67 type_string |
68 type_number |
69 str_true |
70 str_false |
71 ((str_add | str_sub) + logic_desc) |
72 (str_leftbracket + logic_desc + str_rightbracket);
73 exp_desc = logic_desc;
如有任何补充将会在此文档更新。
posted @
2011-06-27 16:36 lwch 阅读(1123) |
评论 (0) |
编辑 收藏
摘要: 抽象工厂模式
前序
“这么晚才回来,都11点了。”大鸟看着刚推门而入的小菜问道。
“嗨,没办法呀,工作忙。”小菜叹气说道。
“怎么会这么忙,加班有点过头了呀。”
“都是换数据库惹的祸呗。”
“怎么了?”
“我本来写好了一个项目,是给一家企业做的电子商务网...
阅读全文
posted @
2011-06-26 22:19 lwch 阅读(3323) |
评论 (2) |
编辑 收藏
观察者模式
前序
小菜对大鸟说:“今天白天真的笑死人了,我们一同时在上班期间看股票行情,被老板当场看到,老板很生气,后果很严重呀。”
“最近股市这么火,也应该可以理解的,你们老板说不定也炒股票。”
“其实最近项目计划排的紧,是比较忙的。而最近的故事又特别火,所以很多人都在偷偷地通过网页看行情。老板市场会出门办事,于是打劫就可以轻松一些,看看行情,几个人聊聊买卖股票的心得什么的,但是一不小心,老板就会回来,让老板看到工作当中做这些总是不太好,你猜他们想到怎么办?”
“只能小心点,那能怎么办?”
“我们公司前台秘书是一个小美眉,她的名字叫童子喆,因为平时同事们买个饮料或零食什么的,都拿一份孝敬于她,所以关系比较好,现在他们就请小子喆帮忙,如果老板出门后回来,就一定要打个电话进来,大家也好马上各就各位,这样就不会被老板发现问题了。”
“你说的这件事的情形,是一个典型的观察者模式。”大鸟说,“你不妨把期间发生的事写成程序看看。”
观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
实现方式(UML类图)
实现代码
#include <stdio.h>
#include <list>
using namespace std;
class Observer;
// 通知者接口
class Subject
{
public:
virtual void Attach(Observer* observer)=0;
virtual void Detach(Observer* observer)=0;
virtual void Notify()=0;
virtual char*& SubjectState()=0;
};
// 抽象观察者
class Observer
{
public:
Observer(char* _name,Subject* _sub) : name(_name),sub(_sub){}
virtual void Update()=0;
protected:
char* name;
Subject* sub;
};
class Boss : public Subject
{
public:
// 增加
virtual void Attach(Observer* observer)
{
observers.push_back(observer);
}
// 减少
virtual void Detach(Observer* observer)
{
observers.remove(observer);
}
// 通知
virtual void Notify()
{
list<Observer*>::iterator iter;
for(iter=observers.begin();iter!=observers.end();iter++) (*iter)->Update();
}
// 老板状态
virtual char*& SubjectState()
{
return action;
}
protected:
list<Observer*> observers;
char* action;
};
class Secretary : public Subject
{
public:
// 增加
virtual void Attach(Observer* observer)
{
observers.push_back(observer);
}
// 减少
virtual void Detach(Observer* observer)
{
observers.remove(observer);
}
// 通知
virtual void Notify()
{
list<Observer*>::iterator iter;
for(iter=observers.begin();iter!=observers.end();iter++) (*iter)->Update();
}
// 前台秘书状态
virtual char*& SubjectState()
{
return action;
}
protected:
list<Observer*> observers;
char* action;
};
// 看股票的同事
class StockObserver : public Observer
{
public:
StockObserver(char* name,Subject* sub) : Observer(name,sub){}
virtual void Update()
{
printf("%s %s 关闭股票行情,继续工作!",sub->SubjectState(),name);
}
};
// 看NBA的同事
class NBAObserver : public Observer
{
public:
NBAObserver(char* name,Subject* sub) : Observer(name,sub){}
virtual void Update()
{
printf("%s %s 关闭NBA直播,继续工作!",sub->SubjectState(),name);
}
};
int main()
{
Boss* huhansan = new Boss();
// 看股票的同事
StockObserver* tongshi1 = new StockObserver("魏关姹",huhansan);
// 看NBA的同事
NBAObserver* tongshi2 = new NBAObserver("易管查",huhansan);
huhansan->Attach(tongshi1);
huhansan->Attach(tongshi2);
huhansan->Detach(tongshi1);
// 老板回来
huhansan->SubjectState() = "我胡汉三回来了!";
huhansan->Notify();
delete huhansan;
delete tongshi1;
delete tongshi2;
return 0;
}
运行结果
由于魏关姹没有被老板通知到,应此被老板逮了个正着,那是相当的杯具啊!
所有文件打包下载
posted @
2011-06-16 16:19 lwch 阅读(4325) |
评论 (8) |
编辑 收藏
CosmosKernel是一个开源项目,意在使C#可以开发操作系统。它首先将C#代码编译为IL中间件,然后交由IL2CPU将IL中间件编译为可执行代码。
下面是测试步骤:
1.下载
Userkit2.安装Userkit
3.启动VS2010并创建CosmosKernelTest项目
4.我们为其编写一个Process的结构表示一个进程
1 public class Process
2 {
3 protected string name;
4 protected Process next;
5
6 public Process(string name)
7 {
8 this.name = name;
9 }
10
11 public string Name
12 {
13 get
14 {
15 return name;
16 }
17 set
18 {
19 name = value;
20 }
21 }
22
23 public Process Next
24 {
25 get
26 {
27 return next;
28 }
29 set
30 {
31 next = value;
32 }
33 }
34 }
5.我们创建一个ProcessSchedule类来保存Process表以及进行进程调度
1 public class ProcessSchedule
2 {
3 protected Process Head = null;
4 protected Process Tail = null;
5 protected Process Current = null;
6
7 public void AddProcess(Process P)
8 {
9 if (Head == null) Head = Tail = Current = P;
10 else
11 {
12 P.Next = Head;
13 Tail.Next = P;
14 Tail = P;
15 }
16 }
17
18 public void Schedule()
19 {
20 Console.Write(Current.Name + " ");
21 Current = Current.Next;
22 }
23 }
6.我们修改Kernel.cs文件的代码来实现进程调度
1 public class Kernel : Sys.Kernel
2 {
3 protected ProcessSchedule ps = new ProcessSchedule();
4
5 protected override void BeforeRun()
6 {
7 Console.WriteLine("Cosmos booted successfully. Type a line of text to get it echoed back.");
8 Process ProcessA = new Process("ProcessA");
9 Process ProcessB = new Process("ProcessB");
10 Process ProcessC = new Process("ProcessC");
11 ps.AddProcess(ProcessA);
12 ps.AddProcess(ProcessB);
13 ps.AddProcess(ProcessC);
14 }
15
16 protected override void Run()
17 {
18 ps.Schedule();
19 }
20 }
7.选择编译为Release版本,并完成编译生成CosmosKernelTestBoot.iso光盘镜像文件
8.使用虚拟机调试这个操作系统,你会看到屏幕上3个进程在来回切换,但是速度非常快。于是我们为其添加一些循环来降低切换速度
1 for (int i = 0; i < 1000; i++)
2 for (int j = 0; j < 1000; j++)
3 for (int k = 0; k < 100; k++) ;
9.编译运行后可以看到运行结果
值得注意的是目前这个项目并不成熟,应此只能实现单任务的操作系统(即一个任务执行完成后再调度另一个任务)。 所有文件打包下载
posted @
2011-06-10 17:24 lwch 阅读(2070) |
评论 (8) |
编辑 收藏
建造者模式
前序
小菜和大鸟两人出去吃夜宵,大鸟要了份炒饭,小菜要了份炒面。炒完后大鸟看到炒面感觉不错,于是也叫了一份。大鸟尝后感觉淡而无味,于是便问小菜:“为什么你的炒面好吃,而我再要的炒面却没有放盐?这好吃不好吃是由谁决定的?”小菜答道:“当然是烧菜的人,他感觉好,就是一盘好面,要是心情不好,或者粗心大意,就是一盘垃圾。”“:)好,那再想想,老麦老肯他们的产品,味道是由什么决定的?”“我知道,那是由他们的工作流程决定的,由于他们制定了非常规范的工作流程,原料放多少,加热几分钟,都有严格规定,估计放多少盐都是用克来计量的。而这个工作流程是在所有的门店都必须要遵照执行的,所以我们吃到的东西不管在哪在什么时候味道都一样。这里我们要吃的食物都依赖工作流程。”
于是大鸟出题让小菜实现一个画小人的程序。
建造小人第一版
#include <stdio.h>
class Graphics
{
public:
void DrawEllipse(int x1,int y1,int x2,int y2)
{
printf("DrawEllipse %d,%d,%d,%d\n",x1,y1,x2,y2);
}
void DrawRectangle(int x1,int y1,int x2,int y2)
{
printf("DrawRectangle %d,%d,%d,%d\n",x1,y1,x2,y2);
}
void DrawLine(int x1,int y1,int x2,int y2)
{
printf("DrawLine %d,%d,%d,%d\n",x1,y1,x2,y2);
}
};
class PersonThinBuilder
{
public:
PersonThinBuilder(Graphics _g) : g(_g){}
void Build()
{
g.DrawEllipse(50,20,30,30);
g.DrawRectangle(60,50,10,50);
g.DrawLine(60,50,40,100);
g.DrawLine(70,50,90,100);
g.DrawLine(60,100,45,150);
g.DrawLine(70,100,85,150);
}
protected:
Graphics g;
};
class PersonFatBuilder
{
public:
PersonFatBuilder(Graphics _g) : g(_g){}
void Build()
{
g.DrawEllipse(50,20,30,30);
g.DrawEllipse(60,50,10,50);
g.DrawLine(60,50,40,100);
g.DrawLine(70,50,90,100);
g.DrawLine(60,100,45,150);
g.DrawLine(70,100,85,150);
}
protected:
Graphics g;
};
int main()
{
Graphics gThin,gFat;
PersonThinBuilder* ptb = new PersonThinBuilder(gThin);
ptb->Build();
PersonFatBuilder* pfb = new PersonFatBuilder(gFat);
pfb->Build();
delete ptb;
delete pfb;
return 0;
}
“炒面忘记放盐的问题依然没有解决。比如我们现在需要你加一个高个的小人,你会不会因为编程不注意,又让他缺胳膊少腿呢?”
“是呀,最好的办法是规定,凡是建造小人,都必须要有头和身体,以及两收两脚。”
建造者模式
将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
实现方式(UML类图)
实现代码
#include <stdio.h>
class Graphics
{
public:
void DrawEllipse(int x1,int y1,int x2,int y2)
{
printf("DrawEllipse %d,%d,%d,%d\n",x1,y1,x2,y2);
}
void DrawRectangle(int x1,int y1,int x2,int y2)
{
printf("DrawRectangle %d,%d,%d,%d\n",x1,y1,x2,y2);
}
void DrawLine(int x1,int y1,int x2,int y2)
{
printf("DrawLine %d,%d,%d,%d\n",x1,y1,x2,y2);
}
};
class PersonBuilder
{
public:
PersonBuilder(Graphics _g) : g(_g){}
virtual void BuildHead()=0;
virtual void BuildBody()=0;
virtual void BuildArmLeft()=0;
virtual void BuildArmRight()=0;
virtual void BuildLegLeft()=0;
virtual void BuildLegRight()=0;
protected:
Graphics g;
};
class PersonThinBuilder : public PersonBuilder
{
public:
PersonThinBuilder(Graphics g) : PersonBuilder(g){}
virtual void BuildHead()
{
g.DrawEllipse(50,20,30,30);
}
virtual void BuildBody()
{
g.DrawRectangle(60,50,10,50);
}
virtual void BuildArmLeft()
{
g.DrawLine(60,50,40,100);
}
virtual void BuildArmRight()
{
g.DrawLine(70,50,90,100);
}
virtual void BuildLegLeft()
{
g.DrawLine(60,100,45,150);
}
virtual void BuildLegRight()
{
g.DrawLine(70,100,85,150);
}
};
class PersonFatBuilder : public PersonBuilder
{
public:
PersonFatBuilder(Graphics g) : PersonBuilder(g){}
virtual void BuildHead()
{
g.DrawEllipse(50,20,30,30);
}
virtual void BuildBody()
{
g.DrawEllipse(60,50,10,50);
}
virtual void BuildArmLeft()
{
g.DrawLine(60,50,40,100);
}
virtual void BuildArmRight()
{
g.DrawLine(70,50,90,100);
}
virtual void BuildLegLeft()
{
g.DrawLine(60,100,45,150);
}
virtual void BuildLegRight()
{
g.DrawLine(70,100,85,150);
}
};
class PersonDirector
{
public:
PersonDirector(PersonBuilder* _pb) : pb(_pb){}
void CreatePerson()
{
pb->BuildHead();
pb->BuildBody();
pb->BuildArmLeft();
pb->BuildArmRight();
pb->BuildLegLeft();
pb->BuildLegRight();
}
protected:
PersonBuilder* pb;
};
int main()
{
Graphics gThin,gFat;
PersonThinBuilder* ptb = new PersonThinBuilder(gThin);
PersonDirector* pdThin = new PersonDirector(ptb);
pdThin->CreatePerson();
PersonFatBuilder* pfb = new PersonFatBuilder(gFat);
PersonDirector* pdFat = new PersonDirector(pfb);
pdFat->CreatePerson();
delete ptb;
delete pdThin;
delete pfb;
delete pdFat;
return 0;
}
运行结果
所有文件打包下载
posted @
2011-06-02 17:34 lwch 阅读(1836) |
评论 (1) |
编辑 收藏
摘要: 首先我们需要食物,蛇的节点,一条蛇三个结构
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> 1 class Food 2 { 3&...
阅读全文
posted @
2011-05-28 13:02 lwch 阅读(1731) |
评论 (0) |
编辑 收藏