重构一个贪吃蛇游戏(linux c++)

Filed under: Ubuntu | 1 Comment »
Posted on

最近读dave_cn[原创]分享自己写的一个贪吃蛇的游戏(Linux) ,C程序写的,就想着用C++重写一下,把面向对象的思想也引入进来。

这里感谢dave_cn,重构后应该有40%的代码是重用的,省了不少功夫。

程序继续采用了ncurses.h库,关于ncurses猛击这里。不知道在window下有没有类似的库(查了一下,可以用conio.h在类dos窗口下实现,有空实现一个window版)。

第一次在linux下用c++写东西,碰到的问题比较多,好歹都解决了,这里也一并做记号。

snake

需求比较简单,直接上UML图

uml

Screen 类 主要负责定时刷新
Snake类    footprintx,footprinty  由于蛇移动实际就是重绘窗口,所以需要把它走过的痕迹擦掉(用空字符代替*即可),只记录一步痕迹
                list  蛇的身体,采用了双链表,关于双链表猛击这里,代码中调用 dlinkedList.h
                bodyReshape()  每一步移动时,其实就是蛇身体各部位坐标的移动,bodyReshape修改各部位坐标
                eraseFootPrint() 擦除痕迹
                isClapseArea() 是否走到边界
                isSpiralDead() 是否头部碰到身体
                lifeProbing()  生命迹象探测,就是看看是不是还活着
                move()   移动,在移动的过程会做一些工作,详见时序图
                receivingNavi() 接受键盘控制蛇头移动方向
                selfGeneration() 吃到Block后,身体张长
LivingArea类 蛇的活动区域
                 Block 障碍物,由于一次只有一个障碍,所以LivingArea和Block是1对1的
                 blockChecking() 检测障碍物
                 isEattingPhase() 是否是吃Block的时刻,当蛇头和Block的坐标相同,即认为是isEattingPhase=true
                 isDigestPhase() 未用
                 eraseBlock() 将isBlockExisted置为false
                 generateBlock() 生成Block
再看一下时序图

sequence

关于蛇的身体,原c程序采用的是一个倒置的首尾相连的链表,head->front指向snake的尾部
如: [a]<-[b]<-[c]<-[d]    a为head
       |                     ^     snake移动的时候,只用head指向d,
       `————– ‘     并且修改d的(y,x)为snake头移动到的位置.
这样的好处是在移动时(身体不增长时),只需要把不用的节点(即上面提到的痕迹)设为头节点,修改其坐标为头的坐标

重构的时候为了简单,用了双链表的源代码,简单的删除痕迹节点,增加新节点,效率不高,简单粗暴。

原c代码

void movesnake(struct TSnake *psnake)
{
 int hy = psnake->head->y;
 int hx = psnake->head->x;

 psnake->head = GetSnakeTail(psnake);

 switch (psnake->dir) {
 case DIR_UP:
     psnake->head->y = hy - 1;
     psnake->head->x = hx;
     break;

 case DIR_DOWN:
     psnake->head->y = hy + 1;
     psnake->head->x = hx;
     break;

 case DIR_LEFT:
     psnake->head->y = hy;
     psnake->head->x = hx - 1;
     break;

 case DIR_RIGHT:
     psnake->head->y = hy;
     psnake->head->x = hx + 1;
     break;

 default:
     break;
 }
}

重构后c++代码

void Snake::bodyReshape()
{
  SnakeNode t;
  list.pop_back(t);
  footprinty=t.y;
  footprintx=t.x;
  list.retrieve(0,t);
  switch (dir)
  {
   case DIR_UP:
     t.y = t.y - 1;
     t.x = t.x;
     break;

   case DIR_DOWN:
     t.y = t.y + 1;
     t.x = t.x;
     break;

   case DIR_LEFT:
     t.y = t.y;
     t.x = t.x - 1;
     break;

   case DIR_RIGHT:
     t.y = t.y;
     t.x = t.x + 1;
     break;

   default:
     break;
  }
  list.insert(0,t);

}

编译:

sudo g++ -o mySnake mySnake.cpp Screen.cpp LivingArea.cpp Snake.cpp SnakeNode.cpp Block.cpp –lncurses

源代码下载

Ubuntu 9.10 Server 配置Apache + WebDav 实现文档协同管理

Filed under: Ubuntu | 5 Comments »
Posted on

先来了解一下百度百科关于WebDav(Web-based Distributed Authoring and Versioning)的解释

一种基于 HTTP 1.1协议的通信协议.它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法,使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。

下面来看如何实现文档的协同管理

1安装软件及模块一览

  (1)Apache2.2.14  自己下载编译。未用ubuntu 9.10 server 下apt-get安装的apache2 是因为这个版本的apache2在启用ssl的时候总是报undefined symbol apr_ldap_ssl_init错误,此处我怀疑可能是ubuntu9.10 server的问题,我在虚拟机ubuntu 8.04 desktop下配置成功。

2 加载Dav Module

     在对Apache进行编译时已经开启了dav的设置(具体参见Ubuntu 9.10 Server 配置基于SSL的Subversion,svn需要webdav协议支持)

#sudo ./configure   –enable-dav –enable-dav-fs –enable-so
                    –enable-ssl –enable-maintainer-mode -prefix=/usr/local/apache2
                    –enable-mods-shared=all   

      注意enable-dav和enable-dav-fs是我们文档协同所需要的。我们可以通过    

cd /usr/local/apache2/bin
sudo ./httpd -l

      来查看已加载的Module。另外自主编译的方式无法通过修改httpd.conf,加入

LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so

      来完成,modules文件夹下也没有这两个so文件,启动apache后会报文件已加载,我搞了很长时间才明白这点。

3 配置WebDav

   在httpd.conf文件下 将#Include conf/extra/httpd-dav.conf的注释去掉,我们来看一下httpd-dav.conf的配置

DavLockDB “/usr/local/apache2/var/DavLock”

Alias /uploads “/usr/local/apache2/uploads”

<Directory “/usr/local/apache2/uploads”>
    Dav On
    Options Indexes FollowSymLinks
    Order Allow,Deny
    Allow from all

    AuthType Basic
    AuthName DAV-upload
    Require valid-user
    # You can use the htpasswd program to create the password database:
    #   htpasswd -c “/usr/local/apache2/user.passwd” DAV-upload admin
    AuthUserFile “/svn/authfile”
    <Limit GET OPTIONS PUT POST DELETE PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK>
    </Limit>
</Directory>

注意一定是Allow from all 另外我使用了Basic的验证方法,要求用户验证;这里Subversion和WebDav使用的是同样的用户文件;Options Indexes FollowSymLinks允许我们在浏览器访问时遍历文件。

4 权限

   #cd /usr/local/apache2
   #sudo mkdir uploads
   #sudo chown www-data:www-data uploads
   #sudo chmod 777 uploads
   以上创建上传目录并设置权限为可读可写  www-data为ubuntu的用户和组

   另外可能需要手动创建 DavLockDB
   #cd /usr/local/apache2
   #sudo mkdir var
   #cd var
   #sudo vim DavLock
   #cd ..
   #cd ..
   #sudo chown www-data:www-data uploads
   #sudo chmod -R 777 var/

5 WebDav客户端

  分别使用了XP和Vista自带的web folder

   使用方法,在XP的资源管理器下选择增加网上邻居(Vista为添加一个网络位置)输入http://your ip or sitename/uploads  并输入用户名和密码。然后再word里就可以直接对文件进行增加修改了,而且当一个用户在更改的时候,其他用户只能只读访问。

   webfolder

当一个用户打开某文件,会加一个只读锁,其他的用户打开该文件时提示

conflict

最后附上fiddler抓到的http包,(webdav协议是http协议的扩展,所以可以观察到)

HTTP/1.1 207 Multi-Status
Date: Tue, 01 Jun 2010 08:30:34 GMT
Server: Apache/2.2.14 (Unix) mod_ssl/2.2.14 OpenSSL/0.9.8g DAV/2 SVN/1.6.2
Content-Length: 966
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/xml; charset=”utf-8″

<?xml version=”1.0″ encoding=”utf-8″?>
<D:multistatus xmlns:D=”DAV:”>
<D:response xmlns:lp1=”DAV:” xmlns:lp3=”http://subversion.tigris.org/xmlns/dav/” xmlns:lp2=”http://apache.org/dav/props/”>
<D:href>/uploads/blackjack/Post.doc</D:href>
<D:propstat>
<D:prop>
<lp1:resourcetype/>
<lp1:creationdate>2010-06-01T06:11:10Z</lp1:creationdate>
<lp1:getcontentlength>46080</lp1:getcontentlength>
<lp1:getlastmodified>Tue, 01 Jun 2010 06:11:10 GMT</lp1:getlastmodified>
<lp1:getetag>”23a06-b400-487f1d6fea216″</lp1:getetag>
<lp2:executable>F</lp2:executable>
<D:supportedlock>
<D:lockentry>
<D:lockscope><D:exclusive/></D:lockscope>
<D:locktype><D:write/></D:locktype>
</D:lockentry>
<D:lockentry>
<D:lockscope><D:shared/></D:lockscope>
<D:locktype><D:write/></D:locktype>
</D:lockentry>
</D:supportedlock>
<D:lockdiscovery/>
<D:getcontenttype>application/msword</D:getcontenttype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
</D:multistatus>

Ubuntu 9.10 Server 配置基于SSL的Subversion

Filed under: Ubuntu | 5 Comments »
Posted on

1 配置准备

  Ubuntu 9.10 Server 英文版。服务器版还是以稳定高效为主,也没有安装图形界面,另外主要是通过putty.exe远程访问。没有采用中文版的原因是,在shell下,中文字体可能没有安装总显示乱码,拜过谷哥大神,未解决。

2 安装软件及模块一览

  (1)Apache2.2.14  自己下载编译。未用ubuntu 9.10 server 下apt-get安装的apache2 是因为这个版本的apache2在启用ssl的时候总是报undefined symbol apr_ldap_ssl_init错误,此处我怀疑可能是ubuntu9.10 server的问题,我在虚拟机ubuntu 8.04 desktop下配置成功。

  (2)OpenSSL 通过apt-get install openssl 安装即可

  (3)Subversion 自己编译下载。很不幸,我无法使用ubuntu的subversion来成功配置SSL。

3 Ubuntu & Linux  

鉴于大家可能对不同发行版的linux不太了解,我简单介绍一下,并比较apache2的Ubuntu版本和自主安装的安装及配置文件路径

   以下摘自Wiki

     One can distinguish between commercially backed distributions, such as Fedora (Red Hat), openSUSE (Novell), Ubuntu (Canonical Ltd.), and Mandriva Linux (Mandriva) and entirely community-driven distributions such as Debian and Gentoo, though there are other distributions that are driven neither by a corporation nor a community, perhaps most famously Slackware.

简单翻译一下,就是说linux有商业支持的发行版如Fedora,openSUSE,Ubuntu和社区推动的版本如Debian和Gentoo。另外Ubuntu本身又是基于Debian的,这点大家应该清楚。

   

  Ubuntu Apache2 自主安装Apache2
安装目录 /etc/apache2 指定路径
例如:
/usr/local/apache2
应用程序 /etc/sbin/apache2
/etc/lib/apache2
/usr/local/apache2/bin/httpd
服务 /etc/init.d/apache2  restart /usr/local/apache2/bin/httpd –k restart 
(不知还有没有别的方式?)
配置文件 /etc/apache2/apache2.conf
/etc/apache2/httpd.conf (通常为空)
/etc/apache2/ports.conf
/etc/apache2/mods_available/
/etc/apache2/sites_available/
apache2.conf负责调用其他的配置文件
/usr/local/apache2/conf/httpd.conf
/usr/local/apache2/conf/extra/
httpd.conf负责调用extra文件夹下的配置文件

4 自主安装Apache2

#sudo wget http://apache.etoak.com/httpd/httpd-2.2.14.tar.gz
#sudo tar -zxvf httpd-2.2.14.tar.gz    
#cd httpd-2.2.14               
#sudo ./configure   –enable-dav –enable-dav-fs –enable-so   –enable-ssl –enable-maintainer-mode -prefix=/usr/local/apache2   –enable-mods-shared=all   
#sudo make                         
#sudo make install

   注意./configure 时确保enable-dav和enable-ssl,其中dav模块是通过apache2存储文件的基础。
5 安装OpenSSL

#sudo apt-get install openssl

6 安装Subversion

# sudo apt-get install build-essential openssl ssh expat libxyssl-dev libssl-dev   
# sudo apt-get remove subversion   
# sudo dpkg –purge subversion   
# wget http://subversion.tigris.org/downloads/subversion-1.6.2.tar.gz
# wget http://subversion.tigris.org/downloads/subversion-deps-1.6.2.tar.gz
# tar xvfz subversion-1.6.2.tar.gz   
# tar xvfz subversion-deps-1.6.2.tar.gz   
# cd subversion-1.6.2/neon/   
# ./configure –prefix=/usr/local –with-ssl –with-pic  
# make   
# sudo make install      
# ./configure –prefix=/usr/local –with-ssl –with-neon=/usr/local   
# make   
# sudo make install  

  注意:首先移除ubuntu自带的subversion,随后进行编译安装。其中subversion-deps-1.6.2.tar.gz是Subversion客户端使用的Neon库,它不仅仅可以用来验证服务器证书,也可以必要时提供客户端证书,因此也要安装上

7 配置http访问subversion

  参考了主题:ubuntu下安装svn提供HTTP版本管理服务Install Subversion with Web Access on Ubuntu

(1)#sudo svnadmin create /svn  

   可以看一下/svn下是不是增加了些文件 
(2)#sudo vim /usr/local/apache2/conf/httpd.conf

   增加 
   <Location /svn>
     DAV svn
     SVNPath /svn
     AuthzSVNAccessFile /svn/conf/authz
     AuthType Basic
     AuthName "Subversion.Tracker"
     AuthUserFile /svn/conf/passwd     Require valid-user
   </Location>

    这部分应该也可以放置到 conf/extra/httpd_dav.conf文件中,然后将httpd.conf中的 include conf/extra/httpd_dav.conf 注释去掉,不过奇怪的是httpd_dav.conf文件中的示例使用<Directory>而不是<Location>,我未作尝试。

(3)#sudo htpasswd -cm /svn/conf/passwd <username>
   增加一个用户名,可以打开passwd文件查看是否创建成功
   同时在Ubuntu上创建同名用户和相同密码  (此处待验证,网络上有的文章没有强调这一点
   sudo useradd <username>
   sudo passwd <password>

(4)#sudo chown www-data:www-data  -R /svn 

    将/svn的所有者和所在的组更改为www-data(ubuntu下apache2的账户)

    #sudo chmod –R g+ws /svn

(5)#sudo /usr/local/apache2/bin/httpd –k restart

    看看http://localhost/svn 是否可以访问了

8 配置ssl访问subversion

  参考了Linux SVN+Apache+SSL 安装配置Apache SSL配置

openssl genrsa -des3 -out ca.key 1024
//按提示输入密码:****
chmod 400 ca.key
//生成证书
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
//按提示分别输入如下内容:
//Country Name: CN
//State or Province Name:
//Locality Name:
//Organization Name:
//Organizational Unit Name:
//Common Name:
//Email Address: your email
chmod 400 ca.crt
openssl genrsa -des3 -out server.key 1024
//按提示输入密码:
chmod 400 server.key
openssl req -new -key server.key -out server.csr
//按提示分别输入如下内容:
//Country Name: CN
//State or Province Name:
//Locality Name:
//Organization Name:
//Organizational Unit Name:
//Common Name:
//Email Address: your email
(ca.crt 和server.csr 的Common Name不能一样)
openssl req -noout -text -in server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out  server.crt
chmod 400 server.crt

vim /usr/local/apache2/conf/httpd.conf
取消Include conf/extra/httpd-ssl.conf前的注释#

打开httpd-ssl.conf文件查看如下两行,确保前面生成的证书放置在该路径下

SSLCertificateFile "/usr/local/apache2/conf/server.crt"

SSLCertificateKeyFile "/usr/local/apache2/conf/server.key"

重启httpd服务

查看https://localhost/svn/  浏览器显示此网站的安全证书有问题,忽略它,输入用户名和密码,至此基于SSL的Subversion配置完成。

9 总结

  配置过程中应该了解ubuntu和其他linux发行版安装软件的不同,掌握make和make install。如碰到apache2不能启动,阅读错误提示以及查看日志(/usr/local/apache2/logs/error.log).

Ubuntu 8.04 安装 Bugzilla 3.2.2

Filed under: Featured, Ubuntu | 6 Comments »
Posted on

新的项目刚刚启动,虽说只有几个人七八条枪,但是也得装个正规军的样子,版本控制、Bug管理都得用上。以前项目用了个国产开源的Bug工具Bugfree,这次想换成强大的Bugzilla,先在虚拟机的Ubuntu安装一下,安装的过程及注意事项记录一下。

用apt-get install bugzilla 安装的版本是 bugzilla 2.22.1 debian,安装过程很简单,不过版本比较陈旧了,且无法升级到bugzilla 3 。从bugzilla论坛上了解到,2.22.1 debian版本是由ubuntu来维护的,其实可以算是bugzilla的一个分支,无法升级到bugzilla 3。这一点提醒在ubuntu下使用bugzilla的朋友,我是费了半天工夫才发现为什么无法把debian版本的2.22升级到bugzilla 3的。

我舍弃2.22.1 debian版本的一个重要原因是不支持Smtp authentication的邮件发送, 以前用bugfree,通过这个功能,我可以使用163的smtp服务器来发送邮件,小组成员能够及时地通过邮件了解bug情况。可是bugzilla提供的smtp却是不需要authentication的方式,这需要我们自己假设邮件服务器,有点郁闷。

bugzilla 3.2.2已经提供了smtp authentication的支持,3.2.2的安装不能通过apt-get install命令,可以参考源文件压缩包里的Quickstart。

下面是我采用的方式

bash$ cd /var/www  选择放置的位置
bash$ wget http://ftp.mozilla.org/pub/mozilla.org/webtools/bugzilla-3.2.2.tar.gz
(Output omitted 输出忽略)
bash$ tar xzvf bugzilla-3.2.2.tar.gz
bugzilla-3.2.2/
bugzilla-3.2.2/.cvsignore
(Output truncated 输出截断)
bash$ cd  /var/www/bugzilla-3.2.2/
bash$ sudo ./checksetup.pl

此时列出是否满足安装的前提,按照要求操作即可,可多次执行此命令,我这里只安装了必须的module,这也造成了我后面采用Smtp发送邮件的时候出现了一系列的问题;也可以选择全部安装,但是好像挺慢,而且我没有执行成功。
安装前提满足了,这是可以按照Quickstart来编辑文件夹下的localconfig文件,主要涉及文件访问权限组$webservergroup以及访问mysql的用户名和密码。
例:

$webservergroup = ‘www-data’;

# The DNS name of the host that the database server runs on.
$db_host = ‘localhost’;
# The name of the database
$db_name = ‘bugs’;

# Who we connect to the database as.

# The DNS name of the host that the database server runs on.
$db_host = ‘localhost’;
# The name of the database
$db_name = ‘bugs’;

# Who we connect to the database as.
$db_user = ‘bugs’;
$db_pass = ‘admin’;

然后创建用户名和数据库并赋予相应的权限

mysql -u root -p
Create database bugs;
GRANT SELECT, INSERT, UPDATE, DELETE, INDEX, ALTER, CREATE, LOCK TABLES,CREATE TEMPORARY TABLES, DROP, REFERENCES ON bugs.* TO bugs@localhost IDENTIFIED BY ‘admin’;
Flush privileges;

再次执行checksetup.pl 即可完成bugzilla的安装,不过要想正常的显示还需要配置一下apache2
在apache2的配置文件中(我是直接修改的/etc/apache2/sites-enabled下面的文件)加入

Alias /bugzilla1 “/var/www/bugzilla-3.2.2″
<Directory  “/var/www/bugzilla-3.2.2″>

Options +ExecCGI
AllowOverride Limit
DirectoryIndex index.cgi
AddHandler cgi-script .cgi
</Directory>

你可能注意到了,我这里虚拟目录设置成bugzilla1而不是bugzilla,我设置成bugzilla总是报找不到index.cgi的错误,可能是原来安装过2.22.1 debian的缘故,还请知道的朋友告知。

在浏览器中执行http://localhost/bugzilla1 此时可以看到bugzilla的首页。

接着配置smtp

mail_delivery_method : smtp
mailfrom                   : 设置成我的真实邮箱     例 me@163.com 可能有的mail server会验证邮箱的真实性以及是否属于该mail server
sendmailnow             : on
smtpserver               : 设置成smtp authentication服务器 例smtp.163.com
smtp_username        : 我的邮箱    例 me@163.com
smtp_password        : 密码
注意后两个parameters(选项)是2.22.1 debian所没有的。

但是接下来我在测试发送邮件的时候总是报

“The new value for smtp_username is invalid: Error requiring
Authen::SASL: ‘Can’t locate Authen/SASL.pm in @INC (@INC contains: .
lib c:/perl/site/lib c:/perl/lib) at (eval 84) line 3. ‘.”
这个错误要求我们安装Authen::SASL 可以回到checksetup.pl处按照提示安装,但是我在这里却出现了问题。
由于之前已经将bugzilla3.2.2文件夹的访问权限设置给了www-data组,现在无法进入到bugzilla3.2.2文件夹内执行任何操作,总报permissions access

采用 sudo –s –H 并输入密码,可以以root权限进入该文件夹操作,安装好Authen::SASL后,发送邮件功能ok。

回顾一下安装的过程,1是对apache默认目录设置以及perl语言环境支持的配置 2是对ubuntu下权限 两处不熟悉浪费了时间,这里记录下整个过程,已备查阅。

VMWare虚拟机Ubuntu上网配置搞定

Filed under: Ubuntu | 8 Comments »
Posted on

新入手的IBM T61预装Vista business系统,这几天又通过虚拟机安装了Ubuntu和XP,XP的网络连接方式使用桥接模式,配置如下
物理机Vista配置
ip 192.168.1.9
子网掩码 255.255.255.0
网关 192.168.1.1
dns 219.146.0.130

虚拟机XP配置
ip 192.168.1.11
子网掩码 255.255.255.0
网关 192.168.1.1
dns 219.146.0.130

使用桥接模式相当于Vista和Xp在同一个局域网下,虚拟机XP能够正常上网,但是非常奇怪的是我的Ubuntu按照这样的设置却怎么也不行,后来发现将Ubuntu的网络连接方式设为Nat方式,Ubuntu的网络设置为Roaming mode enabled,则可以正常上网。
现在正通过双显示器扩展的方式同时显示两个系统(Vista和Ubuntu),相当于同时使用两台电脑,爽死了。