⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sokoban.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <event.h>#include "sokoban.h"char *LEasy = "/sys/games/lib/sokoban/levels/easy.slc";char *LHard = "/sys/games/lib/sokoban/levels/hard.slc";char *levelfile;char		*GRImage = "/sys/games/lib/sokoban/images/right.bit";char		*GLImage = "/sys/games/lib/sokoban/images/left.bit";char		*WallImage = "/sys/games/lib/sokoban/images/wall.bit";char		*EmptyImage = "/sys/games/lib/sokoban/images/empty.bit";char		*CargoImage = "/sys/games/lib/sokoban/images/cargo.bit";char		*GoalCargoImage = "/sys/games/lib/sokoban/images/goalcargo.bit";char		*GoalImage = "/sys/games/lib/sokoban/images/goal.bit";char		*WinImage = "/sys/games/lib/sokoban/images/win.bit";char *buttons[] = {	"restart",	"easy",	"hard",	"noanimate", /* this menu string initialized in main */	"exit",	0};char **levelnames;Menu menu = {	buttons,};Menu lmenu ={	levelnames,};voidbuildmenu(void){	int i;	if (levelnames != nil) {		for(i=0; levelnames[i] != 0; i++)			free(levelnames[i]);	}	levelnames = realloc(levelnames, sizeof(char*)*(numlevels+1));	if (levelnames == nil)		sysfatal("cannot allocate levelnames");	for(i=0; i < numlevels; i++)		levelnames[i] = genlevels(i);	levelnames[numlevels] = 0;	lmenu.item = levelnames;}Image *eallocimage(Rectangle r, int repl, uint color){	Image *tmp;	tmp = allocimage(display, r, screen->chan, repl, color);	if(tmp == nil)		sysfatal("cannot allocate buffer image: %r");	return tmp;}Image *eloadfile(char *path){	Image *img;	int fd;	fd = open(path, OREAD);	if(fd < 0) {		fprint(2, "cannot open image file %s: %r\n", path);		exits("image");	}	img = readimage(display, fd, 0);	if(img == nil)		sysfatal("cannot load image: %r");	close(fd);		return img;}voidallocimages(void){	Rectangle one = Rect(0, 0, 1, 1);		bg		= eallocimage(one, 1, DDarkyellow);	text 		= eallocimage(one, 1, DBluegreen);	gright = eloadfile(GRImage);	gleft = eloadfile(GLImage);	wall = eloadfile(WallImage);	empty = eloadfile(EmptyImage);	empty->repl = 1;	goalcargo = eloadfile(GoalCargoImage);	cargo = eloadfile(CargoImage);	goal = eloadfile(GoalImage);	win = eloadfile(WinImage);}intkey2move(int key){	int k = 0;	switch(key) {	case 61454:		k = Up;		break;	case 63488:		k = Down;		break;	case 61457:		k = Left;		break;	case 61458:		k = Right;		break;	}	return k;}static Route*mouse2route(Mouse m){	Point p, q;	Route *r;	p = subpt(m.xy, screen->r.min);	p.x /= BoardX;	p.y /= BoardY;	q = subpt(p, level.glenda);	// fprint(2, "x=%d y=%d\n", q.x, q.y);	if (q.x == 0 && q.y ==  0)		return nil;	if (q.x == 0 || q.y ==  0) {		if (q.x < 0)			r = extend(nil, Left, -q.x, Pt(level.glenda.x, p.y));		else if (q.x > 0)			r = extend(nil, Right, q.x, Pt(level.glenda.x, p.y));		else if (q.y < 0)			r = extend(nil, Up, -q.y, level.glenda);		else if (q.y > 0)			r = extend(nil, Down, q.y, level.glenda);		else			r = nil;		if (r != nil && isvalid(level.glenda, r, validpush))			return r;		freeroute(r);	}	return findroute(level.glenda, p);}char *genlevels(int i){		if(i >= numlevels)		return 0;	return smprint("level %d", i+1);}intfinished(void){	int x, y;	for(x = 0; x < MazeX; x++)		for(y = 0; y < MazeY; y++)			if(level.board[x][y] == Goal)				return 0;	return 1;}voideresized(int new){	Point p;	if(new && getwindow(display, Refnone) < 0)		sysfatal("can't reattach to window");		p = Pt(Dx(screen->r), Dy(screen->r));	if(!new || !eqpt(p, boardsize(level.max))) {		drawlevel();	}	drawscreen();}void main(int argc, char **argv){	Mouse m;	Event ev;	int e;	Route *r;	int timer;	Animation a;	int animate;	if(argc == 2) 		levelfile = argv[1];	else		levelfile = LEasy;			if(! loadlevels(levelfile)) {		fprint(2, "usage: %s [levelfile]\n", argv[0]);		exits("usage");	}	buildmenu();	animate = 0;	buttons[3] = animate ? "noanimate" : "animate";	if(initdraw(nil, nil, "sokoban") < 0)		sysfatal("initdraw failed: %r");	einit(Emouse|Ekeyboard);	timer = etimer(0, 200);	initanimation(&a);	allocimages();	glenda = gright;	eresized(0);	for(;;) {		e = event(&ev);		switch(e) {		case Emouse:			m = ev.mouse;			if(m.buttons&1) {				stopanimation(&a);				r = mouse2route(m);				if (r)					setupanimation(&a, r);				if (! animate) {					while(onestep(&a))						;					drawscreen();				}			}			if(m.buttons&2) {				int l;				/* levels start from 1 */				lmenu.lasthit = level.index;				l=emenuhit(2, &m, &lmenu);				if(l>=0){					stopanimation(&a);					level = levels[l];					drawlevel();					drawscreen();				}			}			if(m.buttons&4)				switch(emenuhit(3, &m, &menu)) {				case 0:					stopanimation(&a);					level = levels[level.index];					drawlevel();					drawscreen();					break;				case 1:					stopanimation(&a);					loadlevels(LEasy);					buildmenu();					drawlevel();					drawscreen();					break;				case 2:					stopanimation(&a);					loadlevels(LHard);					buildmenu();					drawlevel();					drawscreen();					break;				case 3:					animate = !animate;					buttons[3] = animate ? "noanimate" : "animate";					break;				case 4:					exits(nil);				}			break;		case Ekeyboard:			if(level.done)				break;			stopanimation(&a);			switch(ev.kbdc) {			case 127:			case 'q':			case 'Q':				exits(nil);			case 'n':			case 'N':				if(level.index < numlevels - 1) {					level = levels[++level.index];					drawlevel();					drawscreen();				}				break;			case 'p':			case 'P':				if(level.index > 0) {					level = levels[--level.index];					drawlevel();					drawscreen();				}				break;			case 'r':			case 'R':				level = levels[level.index];				drawlevel();				drawscreen();				break;			case 61454:			case 63488:			case 61457:			case 61458:			case ' ':				move(key2move(ev.kbdc));				drawscreen();				break;			default:				// fprint(2, "key: %d]\n", e.kbdc);				break;			}			break;		default:			if (e == timer) {				if (animate)					onestep(&a);				else					while(onestep(&a))						;				drawscreen();			}			break;		}		if(finished()) {			level.done = 1;			drawwin();			drawscreen();			sleep(3000);			if(level.index < numlevels - 1) {				level = levels[++level.index];				drawlevel();				drawscreen();			}		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -