419

The only way to learn a new programming language is by writing programs in it.

Subscribe to RSS feed

Posts tagged with "c"

贪食蛇 -- 基本完成! -- 欢迎试玩!

,

我的贪食蛇终于到了能玩的阶段了,不容易呀!

这个贪食蛇与其它蛇不同的地方是,在游戏进行过程中可以按“2”加快速度,按“1”减慢速度,吃东西时的速度越快得分越多!可以按空格键停止,但是会扣一点儿分。

如果不想编译,可以下载这个编译好的程序snake012.out也可以下载源文件snake012.c用gcc编译时用加-lncurses参数。


有几个问题:

1,纵向移动时蛇身变得特别长。

2,按下任意键不松开可使蛇快速前进。这个很不好,利用这个特性游戏就不好玩了,但我想了很久也不知道该怎样解决这个问题。

3,rand()的使用方法还是不解理,不能有效地控制食物出现的位置,这个也很烦。

这几个问题我想了很久,很烦了不想想了,打算找别人写的贪食蛇参考。

random number

,

写贪食蛇要用到rand(),这个我还不会用,找到以下有用资料。
http://zhidao.baidu.com/question/4856192.html
http://yanyu.bokee.com/
http://noshape.blogchina.com/
man rand

实际操作时发现了问题,
int myrand(int m, double n)
{
  srand((int) time(0));
  return m+(int) (n*rand()/(RAND_MAX+1.0));
}
刚开始我是这样声明的
int myrand(int m, int n)

这样的话每次都返回相同的数,把 int n 改成 double n 就可以产生每次不同的数了。奇怪。

调用时也有些小问题
  y = myrand(INIT_LEN+1, row-9.0);

这里的row是用ncurses的函数求出的终端高度,我这里row=24。问题是,用 row-9.0,得出的y值还是会超过15,甚至达到23。奇怪。

NCURSES --> 贪食蛇

,

想写一个贪食蛇,所以要学curses,在linux里应该是ncurses吧。

ncurses FAQ

Writing Programs with NCURSES

NCURSES Programming HOWTO (HTML)-最新

NCURSES Programming HOWTO(中文版)-较新

curses 库介绍之一
curses 库介绍之二

这些资料再加上man ncurses估计足够了。

Playlist Generator! -- 播放列表生成器

, ,

我喜欢用mpg321或mplayer来听歌。听同一个文件夹里的歌是很方便的,比如要听 /mnt/songs/chinese/ 里的歌可以用这个命令
mpg321 -Z /mnt/songs/chinese/*

但是我的 chinese 文件夹里还有很多以歌手名字命名的子文件夹,上面那个命令无法听到子文件夹里的歌。

所以我早就想编一个可以生成播放清单的程序,把子文件夹的歌曲也包括在内。

现在学了K&R的第八章,发现里面那个打印目录的例子就是我想要的Playlist Generator!只要把
printf("%8ld %s\n", stbuf.st_size, name);
改成
printf("%s\n", name);
就可以了!

这样就可以把songs文件夹(包括子文件夹)的全部歌曲生成一个播放清单了。
./a.out /mnt/songs/ > allsongs.list

可是它把全部文件,包括 .txt 等不是歌曲的文件也放进清单里了,所以我又修改一下,只把歌曲(.mp3 .wma .ogg等后缀的文件)放进清单。

修改后的完整程序如下:
/* K&R section 8.6 */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

void plist(char *);
void dirwalk(char *, void (*fcn)(char *));

/* print file size */
main(int argc, char **argv)
{
  if (argc == 1)/* default: current directory */
    plist(".");
  else
    while (--argc > 0)
      plist(*++argv);
  return 0;
}

void plist(char *name)
{
  struct stat stbuf;
  char *nsuffix = name+strlen(name)-4;

  if (stat(name, &stbuf) == -1) {
    fprintf(stderr, "plist: can't access %s\n", name);
    return;
  }
  if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
    dirwalk(name, plist);
  if (strcmp(nsuffix, ".mp3") == 0
      || strcmp(nsuffix, ".wma") == 0
      || strcmp(nsuffix, ".ogg") == 0)
    printf("%s\n", name);
}

#define MAX_PATH 1024

void dirwalk(char *dir, void (*fcn)(char *))
{
  struct dirent *dp;
  DIR *dfd;
  char name[MAX_PATH];

  if ((dfd = opendir(dir)) == NULL) {
    fprintf(stderr, "dirwalk: can't open %s\n", dir);
    return;
  }
  while ((dp = readdir(dfd)) != NULL) {
    if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
      continue;
    if (strlen(dir)+strlen(dp->d_name)+2 > sizeof(name))
      fprintf(stderr, "dirwalk: name %s/%s too long\n", dir, dp->d_name);
    else {
      sprintf(name, "%s/%s", dir, dp->d_name);
      (*fcn)(name);
      }
  }
  closedir(dfd);
}

如果你也喜欢用 mpg321 等命令行程序来听歌,这个小程序一定可以带给你一点点方便:)

用system calls提升程序效率

, ,

K&R的 exercise 8-1 要求用system calls重写 cat 程序,并比较两者的速度。

我比较了一下,用system calls写的果然快很多!打印速度差别十分明显。

这里给出这两个程序的源码。kr163.ckre8-1.c
测试方法,
首先编译两个程序,指定不同的文件名
gcc -o cat1.out kr163.c
gcc -o cat2.out kre8-1.c

然后准备两个比较长的文本文件。为什么是两个而不是一个?因为我发现Linux很聪明,同一个文件短时间内重复打印时,就算是效率再低的程序也可以变得很高效,所以测试时要两个文件轮着用。
ls -lR ./ > home1.test
cp home1.test home2.test

然后就可以开始测试了,
./cat2.out home1.test
./cat1.out home2.test

cat1.out的速度明显比较慢,而cat2.out的速度已经和系统自带的cat没什么差别了。