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

📄 snake.c

📁 linux下的一个小游戏贪吃蛇,用c语言写成.
💻 C
字号:
/*
	snake.c
	by Chenhongjiang
 */

#include <sys/types.h>
#include <unistd.h>
#include <curses.h>
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>


#define L 20
#define N 12
#define LEVEL 1
#define SNAKE_LONG 3
#define SNAKE_HEAD_N 3
#define SNAKE_HEAD_L 5

int head_n, head_l, rear_n, rear_l;
int food_n, food_l;
int snake_speed, per_level_time;
int level, score;
int is_game_over;
char snake_box[N+2][L+2];
char move_box[N+2][L+2];
char current_way;
char ch_score[6];
char one[6][6] =  {"  0","  0","  0","  0","  0"};
char two[6][6] =  {"00000","    0", "00000", "0", "00000"};
char three[6][6] = {"00000","    0","00000","    0","00000"};
char four[6][6] = {"0 0","0 0","00000","  0","  0"};
char five[6][6] = {"00000","0","00000","    0","00000"};
char six[6][6] = {"00000","0","00000","0   0","00000"};
char seven[6][6] = {"00000","    0","    0","    0","    0"};
char eight[6][6] = {"00000","0   0","00000","0   0","00000"};
char nine[6][6] = {"00000","0   0","00000","    0","00000"};
char zero[6][6] = {"00000","0   0","0   0","0   0","00000"};

void handler(int signo);
int snake_refresh(void);
int create_snake(int i, int j);
int create_food();
void initial();
unsigned char my_random(void);
void init_sigaction(void);
void init_time();
void snake_log();




int main(void)
{
	int ch, last_ch;	// in case snake run too quick
	int i, j, l, n;
	int snake_head, snake_rear;
  
	is_game_over = 1;
	level = LEVEL;
	score = 0;
	l = L + 2;
	n = N + 2;
	
	/* init move_box */
	for (i=0; i<n; i++)
		for (j=0; j<l; j++) {
			move_box[i][j] = 'l';
		}

	/* init snake_box */
	for (i=0; i<n; i++)
		for (j=0; j<l; j++) {
			if (i == 0 || j == 0) {
				snake_box[i][j] = 1;
			} else if (i == n-1 || j == l-1) {
				snake_box[i][j] = 1;
			} else {
				snake_box[i][j] = 0;
			}
		}

	head_n = SNAKE_HEAD_N;
	head_l = SNAKE_HEAD_L;
	rear_n = SNAKE_HEAD_N;
	rear_l = SNAKE_HEAD_L - SNAKE_LONG + 1;
	current_way = 'r';
	
	/* create a snke */
	create_snake(head_n, head_l);

	/* create a food ($ ^_^) */
	create_food();

	/* set time */
	snake_speed = 500000 - level*50000; 
	per_level_time = 0;
	init_sigaction();	/* SIGNAL */
	init_time();		/* SIGNAL */

	initial();
	snake_refresh();
	signal(SIGALRM, handler);
	last_ch = 'a';
	while (is_game_over) {
		ch = getch();
		if (last_ch == ch) {	/* in case input lot of the same key */
			continue;
		}
		switch (ch) {
				  case KEY_RIGHT:
							 if (current_way == 'l') { break;}
							 current_way = 'r';
							 snake_refresh();
							 break;
				  case KEY_DOWN:
							 if (current_way == 'u') { break;}
							 current_way = 'd';
							 snake_refresh();
							 break;
				  case KEY_LEFT:
							 if (current_way == 'r') { break;}
							 current_way = 'l';
							 snake_refresh();
							 break;
				  case KEY_UP:
							 if (current_way == 'd') { break;}
							 current_way = 'u';
							 snake_refresh();
							 break;
				  default:
							 break;
		}	
		last_ch = ch;
		sleep(1);
	}
	endwin();
	snake_log();		/* log to score.txt */
	exit(1);
}

void handler(int signo)
{
	per_level_time += snake_speed/100000;
	if (per_level_time >= 300) {		/* 10 is 1 sec */
		if (level <= 9) {
			level += 1;
			snake_speed = 500000 - level*50000; 
			init_sigaction();	/* SIGNAL */
			init_time();		/* SIGNAL */
			per_level_time = 0;
		}
	} 

	if (current_way == 'r') {
		snake_right();
	} else if (current_way == 'd') {
		snake_down();
	} else if (current_way == 'l') {
		snake_left();
	} else if (current_way == 'u') {
		snake_up();
	}
	snake_refresh();
	mvprintw(20, 20, "Level: %d\n", level);
}

void init_sigaction(void)
{
	struct sigaction act;
	act.sa_handler=handler;
	act.sa_flags=0;
	sigemptyset(&act.sa_mask);
	sigaction(SIGPROF,&act,NULL);
}

void init_time()
{
	struct itimerval value;
	value.it_value.tv_sec=0;
	value.it_value.tv_usec=snake_speed;
	value.it_interval=value.it_value;
	setitimer(ITIMER_REAL,&value,NULL);
}

int snake_refresh(void)
{
	int x, y;
	int  i, j, l, n;
	int score_len, length;
	l = L + 2;
	n = N + 2;

	x = 5, y = 5;
	for (i=0; i<n; i++)
		for (j=0; j<l; j++) {
			if (snake_box[i][j] == 0) {
				mvprintw(x, y, " ");
			} else if (snake_box[i][j] == 1) {
				mvprintw(x, y, "@ ");
			} else if (snake_box[i][j] == 2) {	/* food */
				mvprintw(x, y, "$");
			}
			y+=2;
			if (j == l-1) {
				mvprintw(x, y, "\n");
				x++;
				y = 5;
			}
		}
	x = 6; y = 50;
	mvprintw(x++, y, "00000 00000 00000 00000 00000\n");
	mvprintw(x++, y, "0     0     0   0 0   0 0   \n");
	mvprintw(x++, y, "00000 0     0   0 00000 00000\n");
	mvprintw(x++, y, "    0 0     0   0 0  0  0   \n");
	mvprintw(x, y  , "00000 00000 00000 0   0 00000\n");

	attron(A_BOLD);		 
	sprintf(ch_score, "%d", score);
	score_len = strlen(ch_score);
	i = 0;
	n = 0;
	length = 0;
	x = 60;
	y = 13;
	while (i < score_len) {
		if (ch_score[i] == '0') 
			while (n<=4) {
				mvprintw(y, x+length, "%s", *(zero+n));
				n++;
				y++;
			}
		if (ch_score[i] == '1') 
			while (n<=4) {
				mvprintw(y, x+length, "%s", *(one+n));
				n++;
				y++;
			}
		if (ch_score[i] == '2') 
			while (n<=4) {
				mvprintw(y, x+length, "%s", *(two+n));
				n++;
				y++;
			}
		if (ch_score[i] == '3') 
			while (n<=4) {
				mvprintw(y, x+length, "%s", *(three+n));
				n++;
				y++;
			}
		if (ch_score[i] == '4') 
			while (n<=4) {
				mvprintw(y, x+length, "%s", *(four+n));
				n++;
				y++;
			}
		if (ch_score[i] == '5') 
			while (n<=4) {
				mvprintw(y, x+length, "%s", *(five+n));
				n++;
				y++;
			}
		if (ch_score[i] == '6') 
			while (n<=4) {
				mvprintw(y, x+length, "%s", *(six+n));
				n++;
				y++;
			}
		if (ch_score[i] == '7') 
			while (n<=4) {
				mvprintw(y, x+length, "%s", *(seven+n));
				n++;
				y++;
			}
		if (ch_score[i] == '8') 
			while (n<=4) {
				mvprintw(y, x+length, "%s", *(eight+n));
				n++;
				y++;
			}
		if (ch_score[i] == '9') 
			while (n<=4) {
				mvprintw(y, x+length, "%s", *(nine+n));
				n++;
				y++;
			}
		n = 0;
		y = 13;
		i++;
		length += 6;
	}
	attroff(A_BOLD);
	refresh();
}

int create_snake(int i, int j)
{
	int m;

	for (m=SNAKE_LONG-1; m>=0; m--) {
		snake_box[i][j-m] = 1;
		move_box[i][j-m] = 'r';
	}
}
int create_food(void)
{
	int tmp_n, tmp_l;
	do {	
		tmp_n = random_food(1, N-2);
		tmp_l = random_food(1, L-2);
	} while (snake_box[tmp_n][tmp_l] != 0);
	food_n = tmp_n;
	food_l = tmp_l;
	snake_box[food_n][food_l] = 2;
}

void initial()                       /* .... curses ..               */
{
	initscr();
	cbreak();
	nl();
	noecho();
	curs_set(0); // set off _
	intrflush(stdscr,FALSE);
	keypad(stdscr,TRUE);
	refresh();
}

int snake_right()
{
	current_way = 'r';
	if (snake_box[head_n][head_l+1] == 1) {
		is_game_over = 0;
		return(0);
	}
	if (snake_box[head_n][head_l+1] == 2) {	// food
		snake_box[head_n][head_l+1] = 1;
		move_box[head_n][head_l] = 'r';
		head_l++;
		score += level*2;
		create_food();
		return(1);
	}
	
	snake_box[rear_n][rear_l] = 0;
	snake_box[head_n][head_l+1] = 1;
	move_box[head_n][head_l] = 'r';
	head_l++;	// head + 1
	
	if (move_box[rear_n][rear_l] == 'r') {
		rear_l++;
	} else if (move_box[rear_n][rear_l] == 'd') {
		rear_n++;
	} else if (move_box[rear_n][rear_l] == 'l') {
		rear_l--;
	} else if (move_box[rear_n][rear_l] == 'u') {
		rear_n--;
	}
}

int snake_down()
{
	current_way = 'd';
	if (snake_box[head_n+1][head_l] == 1) {
		is_game_over = 0;
		return(0);
	}
	if (snake_box[head_n+1][head_l] == 2) {	// food
		snake_box[head_n+1][head_l] = 1;
		move_box[head_n][head_l] = 'd';
		head_n++;
		score += level*2;
		create_food();
		return(1);
	}
	snake_box[rear_n][rear_l] = 0;
	snake_box[head_n+1][head_l] = 1;
	move_box[head_n][head_l] = 'd';

	head_n++;
	if (move_box[rear_n][rear_l] == 'r') {
		rear_l++;
	} else if (move_box[rear_n][rear_l] == 'd') {
		rear_n++;
	} else if (move_box[rear_n][rear_l] == 'l') {
		rear_l--;
	} else if (move_box[rear_n][rear_l] == 'u') {
		rear_n--;
	}
}

int snake_left()
{
	current_way = 'l';
	if (snake_box[head_n][head_l-1] == 1) {
		is_game_over = 0;
		return(0);
	}
	if (snake_box[head_n][head_l-1] == 2) {	// food
		snake_box[head_n][head_l-1] = 1;
		move_box[head_n][head_l] = 'l';
		head_l--;
		score += level*2;
		create_food();
		return(1);
	}
	snake_box[rear_n][rear_l] = 0;
	snake_box[head_n][head_l-1] = 1;
	move_box[head_n][head_l] = 'l';

	head_l--;
	if (move_box[rear_n][rear_l] == 'r') {
		rear_l++;
	} else if (move_box[rear_n][rear_l] == 'd') {
		rear_n++;
	} else if (move_box[rear_n][rear_l] == 'l') {
		rear_l--;
	} else if (move_box[rear_n][rear_l] == 'u') {
		rear_n--;
	}
}

int snake_up()
{
	current_way = 'u';
	if (snake_box[head_n-1][head_l] == 1) {
		is_game_over = 0;
		return(0);
	}
	
	if (snake_box[head_n-1][head_l] == 2) {	// food
		snake_box[head_n-1][head_l] = 1;
		move_box[head_n][head_l] = 'u';
		head_n--;
		score += level*2;
		create_food();
		return(1);
	}
	snake_box[rear_n][rear_l] = 0;
	snake_box[head_n-1][head_l] = 1;
	move_box[head_n][head_l] = 'u';

	head_n--;
	if (move_box[rear_n][rear_l] == 'r') {
		rear_l++;
	} else if (move_box[rear_n][rear_l] == 'd') {
		rear_n++;
	} else if (move_box[rear_n][rear_l] == 'l') {
		rear_l--;
	} else if (move_box[rear_n][rear_l] == 'u') {
		rear_n--;
	}
}

unsigned char my_random(void)
{
	static int seeded;
	unsigned int uint_res;
	unsigned char c1, c2, c3, c4;
	if (!seeded)
	{
		struct timeval tv;
		int retval = gettimeofday(&tv, NULL);
		if (retval != 0)
		{
			perror("gettimeofday");
			exit(0);
		}
		srand((unsigned)tv.tv_usec);
		seeded = 1;
	}
	uint_res = rand();
	c1 = uint_res & 0x000000ff;
	c2 = (uint_res >> 8) & 0x000000ff;
	c3 = (uint_res >> 16) & 0x000000ff;
	c4 = (uint_res >> 24) & 0x000000ff;
	return c1 ^ c2 ^ c3 ^ c4;    
}

int random_food(int min, int max)
{
	int scaled_value;
	int value = my_random();
	value <<= 8;
	value != my_random();
	scaled_value = (double)min;
	scaled_value += ((double)value / (double)65536)*
			  ((double)max - min + 1);
	value = (unsigned short)scaled_value;
	return(value);
}

void snake_log()
{
	int openfd;
	char buf[128];
	struct timeval tv;
	struct tm* ptm;
	int retval = gettimeofday(&tv, NULL);
	
	ptm = (struct tm*)localtime(&tv, NULL);
	if ((openfd= open("score.txt", O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|
						 S_IWUSR | S_IRGRP |
						 S_IWGRP | S_IROTH)) == -1) {
		perror("snake log error");
		exit(0);
	}
	strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S   ", ptm);
	write(openfd, buf, strlen(buf));
	sprintf(buf, "%s\n", ch_score);
	write(openfd, buf, strlen(buf));

	
}

⌨️ 快捷键说明

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