贪吃蛇实验报告

贪吃蛇实验报告

第一次写博客。
这是中山大学软件工程导论的项目之一,对初学者可能有点难度,分享出来做参考。
使用的C语言。
如果你喜欢的话可以使用,就这样,直接上代码。
智能蛇部分也发上来

#include 
#include 
#include 

//宏定义区
#define SNAKE_MAX_LENGTH 20
#define SNAKE_HEAD 'H'
#define SNAKE_BODY 'X'
#define BLANK_CELL ' '
#define SNAKE_FOOD '$'
#define WALL_CELL '*'
#define	NEXT_PLACE (map[snakePlace[0][0]+addY][snakePlace[1][0]+addX])	//下一个位置的字符
#define PLACE(X) (map[snakePlace[0][X]][snakePlace[1][X]])				//当前位置的字符

//地图
char map[12][12] = {
	"************",
	"*XXXXH     *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"************"
};

//蛇的位置与长度
int snakePlace[2][SNAKE_MAX_LENGTH] = { {1,1,1,1,1},{5,4,3,2,1} };
int snakeLength = 5;

//移动与吞食,isFood==1则进行吞食
void snakeMove(int addX, int addY, int isFood);
//产生随机位置食物
void put_money(void);
//分支选择器,返回0则游戏结束,否则游戏继续
int judgeGameRun(int addX, int addY);
//显示
void output(void);
//游戏结束
void gameover(void);
//控制器
void operation(void);

int main() {
	put_money();
	output();
	operation();
	gameover();
	return 0;
}

//移动与吞食,isFood==1则进行吞食
void snakeMove(int addX, int addY, int isFood) {
	int temp1;

	//是否吞食
	if (!isFood)
		PLACE(snakeLength - 1) = ' ';
	else {
		snakeLength++;
	}

	//非头部移动与坐标变化
	PLACE(0) = SNAKE_BODY;
	for (temp1 = snakeLength - 1;temp1 > 0;temp1--) {
		snakePlace[0][temp1] = snakePlace[0][temp1 - 1];
		snakePlace[1][temp1] = snakePlace[1][temp1 - 1];
	}

	//头部移动与坐标变化
	snakePlace[0][0] += addY;
	snakePlace[1][0] += addX;
	PLACE(0) = SNAKE_HEAD;

}

//产生随机位置食物
void put_money(void) {
	int x, y;
	do {
		x = 1 + (int)(10.0*rand() / (RAND_MAX + 1.0));
		y = 1 + (int)(10.0*rand() / (RAND_MAX + 1.0));
	} while (map[y][x] != BLANK_CELL);
	map[y][x] = SNAKE_FOOD;
}

//分支选择器,返回0则游戏结束,否则游戏继续
int judgeGameRun(int addX, int addY) {
	//失败条件
	if ((NEXT_PLACE == WALL_CELL) || (NEXT_PLACE == SNAKE_BODY)) {
		printf("You fail!\n");
		return 0;
	}

	//移动与吞食
	if (NEXT_PLACE == SNAKE_FOOD) {
		//进行吞食

		//获胜条件
		if (snakeLength >= SNAKE_MAX_LENGTH) {
			printf("The snake is full.\nYou win!\n");
			return 0;
		}

		snakeMove(addX, addY, 1);
		put_money();
	}
	else //不进行吞食
		snakeMove(addX, addY, 0);

	return 1;
}

//显示
void output(void) {
	// system("clear"); linux
	system("cls");//windos
	printf("------------------------贪吃蛇-------------------------\n");
	int temp1, temp2;
	for (temp1 = 0;temp1 < 12;temp1++) {
		for (temp2 = 0;temp2 < 12;temp2++) {
			printf("%c", map[temp1][temp2]);
		}
		printf("\n");
	}
}

//游戏结束
void gameover(void) {
	printf("Game Over\n");
}

//控制器
void operation(void) {
	srand((int)time(0));
	char op;
	int addX, addY;
	addX = addY = 0;

	while (1) {
		//得到操作码
		printf("Please input the operation(WASD/wasd): ");
		scanf("%c", &op);
		setbuf(stdin, NULL);

		//解码
		switch (op)
		{
		case 'a':
		case 'A':
			addX = -1;
			addY = 0;
			break;
		case 'd':
		case 'D':
			addX = 1;
			addY = 0;
			break;
		case 'w':
		case 'W':
			addX = 0;
			addY = -1;
			break;
		case 's':
		case 'S':
			addX = 0;
			addY = 1;
			break;
		default:
			addX = addY = 0;
			break;
		}
		if (addX == 0 && addY == 0)
			continue;

		//进入分支
		if (!judgeGameRun(addX, addY)) {
			break;
		}
		output();
	}
}

linux下智能蛇的代码实现

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

static struct termios ori_attr, cur_attr;

static __inline 
int tty_reset(void)
{
        if (tcsetattr(STDIN_FILENO, TCSANOW, &ori_attr) != 0)
                return -1;

        return 0;
}


static __inline
int tty_set(void)
{
        
        if ( tcgetattr(STDIN_FILENO, &ori_attr) )
                return -1;
        
        memcpy(&cur_attr, &ori_attr, sizeof(cur_attr) );
        cur_attr.c_lflag &= ~ICANON;
//        cur_attr.c_lflag |= ECHO;
        cur_attr.c_lflag &= ~ECHO;
        cur_attr.c_cc[VMIN] = 1;
        cur_attr.c_cc[VTIME] = 0;

        if (tcsetattr(STDIN_FILENO, TCSANOW, &cur_attr) != 0)
                return -1;

        return 0;
}

static __inline
int kbhit(void) 
{
                   
        fd_set rfds;
        struct timeval tv;
        int retval;

        /* Watch stdin (fd 0) to see when it has input. */
        FD_ZERO(&rfds);
        FD_SET(0, &rfds);
        /* Wait up to five seconds. */
        tv.tv_sec  = 0;
        tv.tv_usec = 0;

        retval = select(1, &rfds, NULL, NULL, &tv);
        /* Don't rely on the value of tv now! */

        if (retval == -1) {
                perror("select()");
                return 0;
        } else if (retval)
                return 1;
        /* FD_ISSET(0, &rfds) will be true. */
        else
                return 0;
        return 0;
}

//将你的 snake 代码放在这里

#define SNAKE_MAX_LENGTH 20
#define SNAKE_HEAD 'H'
#define SNAKE_BODY 'X'
#define BLANK_CELL ' '
#define SNAKE_FOOD '$'
#define WALL_CELL '*'
#define	NEXT_PLACE (map[snakePlace[0][0]+addY][snakePlace[1][0]+addX])	
#define PLACE(X) (map[snakePlace[0][X]][snakePlace[1][X]])			

char map[12][12] = {
	"************",
	"*XXXXH     *",
	"*          *",
	"*    *     *",
	"* *  *  *  *",
	"*    *     *",
	"* **   **  *",
	"*    *     *",
	"* *  *  *  *",
	"*    *     *",
	"*          *",
	"************"
};

int snakePlace[2][SNAKE_MAX_LENGTH] = { {1,1,1,1,1},{5,4,3,2,1} };
int snakeLength = 5;
int foodPlace[2] = {0,0};
void snakeMove(int addX, int addY, int isFood) {
	int temp1;

	if (!isFood)
		PLACE(snakeLength - 1) = ' ';
	else {
		snakeLength++;
	}

	PLACE(0) = SNAKE_BODY;
	for (temp1 = snakeLength - 1;temp1 > 0;temp1--) {
		snakePlace[0][temp1] = snakePlace[0][temp1 - 1];
		snakePlace[1][temp1] = snakePlace[1][temp1 - 1];
	}

	snakePlace[0][0] += addY;
	snakePlace[1][0] += addX;
	PLACE(0) = SNAKE_HEAD;

}

void put_money() {
	int x, y;
	do {
		x = 1 + (int)(10.0*rand() / (RAND_MAX + 1.0));
		y = 1 + (int)(10.0*rand() / (RAND_MAX + 1.0));
	} while (map[y][x] != BLANK_CELL);
	map[y][x] = SNAKE_FOOD;
	foodPlace[0] = y;
	foodPlace[1] = x;
}


char whereGoNext(int Hx,int Hy,int Fx,int Fy) {
	// 用数组movable[3]={“a”,”d”,”w”,”s”} 记录可走的方向
	char movable[4]={'a','d','w','s'};
	int distance[4]={0,0,0,0};
	// 用数组distance[3]={0,0,0,0} 记录离食物的距离
	// 分别计算蛇头周边四个位置到食物的距离。H头的位置,F食物位置
	//     例如:假设输入”a” 则distance[0] = |Fx – (Hx-1)| + |Fy – Hy|
	//           如果 Hx-1,Hy 位置不是Blank,则 distance[0] = 9999
	// 选择distance中存最小距离的下标p,注意最小距离不能是9999
	int minum = 9999;
	int p = 0;
	distance[0] = fabs(Fx - (Hx-1)) + fabs(Fy - Hy);
	if(map[Hy][Hx-1] == WALL_CELL||map[Hy][Hx-1]==SNAKE_BODY)
		distance[0] = 9999;
	if(minum>distance[0]){
		minum = distance[0];
		p = 0;
	}
	distance[1] = fabs(Fx - (Hx+1)) + fabs(Fy - Hy);
	if(map[Hy][Hx+1] == WALL_CELL||map[Hy][Hx+1]==SNAKE_BODY)
		distance[1] = 9999;
	if(minum>distance[1]){
		minum = distance[1];
		p = 1;
	}
	distance[2] = fabs(Fx - (Hx)) + fabs(Fy - (Hy-1));
	if(map[Hy-1][Hx] == WALL_CELL||map[Hy-1][Hx]==SNAKE_BODY)
		distance[2] = 9999;
	if(minum>distance[2]){
		minum = distance[2];
		p = 2;
	}
	distance[3] = fabs(Fx - (Hx)) + fabs(Fy - (Hy+1));
	if(map[Hy+1][Hx] == WALL_CELL||map[Hy+1][Hx]==SNAKE_BODY)
		distance[3] = 9999;
	if(minum>distance[3]){
		minum = distance[3];
		 p = 3;
	}
	return movable[p];
	// 返回 movable[p]
	}

int judgeGameRun(int addX, int addY) {
	if ((NEXT_PLACE == WALL_CELL) || (NEXT_PLACE == SNAKE_BODY)) {
		printf("You fail!\n");
		return 0;
	}

	if (NEXT_PLACE == SNAKE_FOOD) {
		if (snakeLength >= SNAKE_MAX_LENGTH) {
			printf("The snake is full.\nYou win!\n");
			return 0;
		}

		snakeMove(addX, addY, 1);
		put_money();
	}
	else 
		snakeMove(addX, addY, 0);

	return 1;
}

void output(void) {
	system("clear"); //linux
	//system("cls");//windos
	printf("------------------------Snake-------------------------\n");
	int temp1, temp2;
	for (temp1 = 0;temp1 < 12;temp1++) {
		for (temp2 = 0;temp2 < 12;temp2++) {
			printf("%c", map[temp1][temp2]);
		}
		printf("\n");
	}
}

void gameover(void) {
	printf("Game Over\n");
}

void operation(void) {
	srand((int)time(0));
	char op;
	int addX, addY;
	addX = addY = 0;

	while (1) {
		//printf("Please input the operation(WASD/wasd): ");
		//do{
			//op = getchar();
		//}while(op=='\n');
		//setbuf(stdin, NULL);
		//fflush(stdin);
		long t=time(NULL);
		     
	        while(t==time(NULL))
			;//等待1秒
		op = whereGoNext(snakePlace[1][0],snakePlace[0][0],foodPlace[1],foodPlace[0]);
		switch (op)
		{
		case 'a':
		case 'A':
			addX = -1;
			addY = 0;
			break;
		case 'd':
		case 'D':
			addX = 1;
			addY = 0;
			break;
		case 'w':
		case 'W':
			addX = 0;
			addY = -1;
			break;
		case 's':
		case 'S':
			addX = 0;
			addY = 1;
			break;
		default:
			addX = addY = 0;
			break;
		}
		if (addX == 0 && addY == 0)
			continue;

		if (!judgeGameRun(addX, addY)) {
			break;
		}
		output();
	}
}



int main()
{
        //设置终端进入非缓冲状态
        int tty_set_flag;
        tty_set_flag = tty_set();

        //将你的 snake 代码放在这里
	put_money();
	output();
	operation();
	gameover();

        printf("pressed `q` to quit!\n");
        while(1) {

                if( kbhit() ) {
                        const int key = getchar();
                        printf("%c pressed\n", key);
                        if(key == 'q')
                                break;
                } else {
                       ;// fprintf(stderr, "\n");
                }
        }

        //恢复终端设置
        if(tty_set_flag == 0) 
                tty_reset();
        return 0;
}

之前经常来CSDN找作业的代码,以后我也会尽量把自己完成的代码分享一下哈哈。

你可能感兴趣的:(贪吃蛇实验报告)