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

📄 route.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include "sokoban.h"static int dirlist[] = { Up, Down, Left, Right, Up, Down, Left, Right, };static int ndir = 4;static Pointdir2point(int dir){	switch(dir) {	case Up:		return Pt(0, -1);	case Down:		return Pt(0, 1);	case Left:		return Pt(-1, 0);	case Right:		return Pt(1, 0);	}	return Pt(0,0);}intvalidpush(Point g, Step *s, Point *t){	int i;	Point m;	if (s == nil)		return 0;	m = dir2point(s->dir);	// first test for  Cargo next to us (in direction dir)	if (s->count > 0) {		g = addpt(g, m);		if (!ptinrect(g, Rpt(Pt(0,0), level.max)))			return 0;		switch (level.board[g.x][g.y]) {		case Wall:		case Empty:		case Goal:			return 0;		}	}	// then test for  enough free space for us _and_ Cargo	for (i=0; i < s->count; i++) {		g = addpt(g, m);		if (!ptinrect(g, Rpt(Pt(0,0), level.max)))			return 0;		switch (level.board[g.x][g.y]) {		case Wall:		case Cargo:		case GoalCargo:			return 0;		}	}	if (t != nil)		*t = g;	return 1;}intisvalid(Point s, Route* r, int (*isallowed)(Point, Step*, Point*)){	Point m;	Step *p;	if (r == nil)		return 0;	m = s;	for (p=r->step; p < r->step +r->nstep; p++)		if (! isallowed(m, p, &m))			return 0;	return 1;}static Walk*newwalk(void){	Walk *w;	w = malloc(sizeof(Walk));	if (w->route == nil)		sysfatal("cannot allocate walk");	memset(w, 0, sizeof(Walk));	return w;}static voidresetwalk(Walk *w){	Route **p;	if (w == nil || w->route == nil)		return;	for (p=w->route; p < w->route + w->nroute; p++)		freeroute(*p);	w->nroute = 0;}static voidfreewalk(Walk *w){	if (w == nil)		return;	resetwalk(w);	if(w->route)		free(w->route);	free(w);}static voidaddroute(Walk *w, Route *r){	if (w == nil || r == nil)		return;	if (w->beyond < w->nroute+1) {		w->beyond = w->nroute+1;		w->route = realloc(w->route, sizeof(Route*)*w->beyond);	}	if (w->route == nil)		sysfatal("cannot allocate route in addroute");	w->route[w->nroute] = r;	w->nroute++;}voidfreeroute(Route *r){	if (r == nil)		return;	if (r->step != nil)		free(r->step);	free(r);}Route*extend(Route *rr, int dir, int count, Point dest){	Route *r;	r = malloc(sizeof(Route));	if (r == nil)		sysfatal("cannot allocate route in extend");	memset(r, 0, sizeof(Route));	r->dest = dest;	if (count > 0) {		r->nstep = 1;		if (rr != nil)			r->nstep += rr->nstep;		r->step = malloc(sizeof(Step)*r->nstep);		if (r->step == nil)			sysfatal("cannot allocate step in extend");		if (rr != nil)			memmove(r->step, rr->step, sizeof(Step)*rr->nstep);		r->step[r->nstep-1].dir = dir;		r->step[r->nstep-1].count = count;	}	return r;}static Step*laststep(Route*r){	if (r != nil && r->nstep > 0) {		return &r->step[r->nstep-1];	}	return nil;}static int*startwithdirfromroute(Route *r, int* dl, int n){	Step *s;	int *p;		if (r == nil || dl == nil)		return dl;	s =  laststep(r);	if (s == nil || s->count == 0)		return dl;	for (p=dl; p < dl + n; p++)		if (*p == s->dir)			break;	return p;}static Route*bfstrydir(Route *r, int dir, Visited *v){	Point m, p, n;	if (r == nil)		return nil;	m = r->dest;	p = dir2point(dir);	n = addpt(m, p);	if (ptinrect(n, Rpt(Pt(0,0), level.max)) &&	    v->board[n.x][n.y] == 0) {		v->board[n.x][n.y] = 1;		switch (level.board[n.x][n.y]) {		case Empty:		case Goal:			return extend(r, dir, 1, n);		}	}	return nil;}static Route*bfs(Point src, Point dst, Visited *v){	Walk *cur, *new, *tmp;	Route *r, **p;	int progress, *dirs, *dirp;	Point n;	if (v == nil)		return nil;	cur = newwalk();	new = newwalk();	v->board[src.x][src.y] = 1;	r = extend(nil, 0, 0, src);	if (eqpt(src, dst)) {		freewalk(cur);		freewalk(new);		return r;	}	addroute(cur, r);	progress = 1;	while (progress) {		progress = 0;		for (p=cur->route; p < cur->route + cur->nroute; p++) {			dirs = startwithdirfromroute(*p, dirlist, ndir);			for (dirp=dirs; dirp < dirs + ndir; dirp++) {				r = bfstrydir(*p, *dirp, v);				if (r != nil) {					progress = 1;					n = r->dest;					if (eqpt(n, dst)) {						freewalk(cur);						freewalk(new);						return(r);					}					addroute(new, r);				}			}		}		resetwalk(cur);		tmp = cur;		cur = new;		new = tmp;	}	freewalk(cur);	freewalk(new);	return nil;}Route*findroute(Point src, Point dst){	Visited v;	Route* r;	memset(&v, 0, sizeof(Visited));	r = bfs(src, dst, &v);	return r;}

⌨️ 快捷键说明

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