linux下C实现贪吃蛇

闲着没事,又刚学了AIO,就想试试写个贪吃蛇。
但后来也没时间做修改和优化了。写之前其实也没怎么想好该怎么写, 写的蛮丑陋的随便看看吧
编译时需要连接curses和rt库,就在连接时加上-lcurses -lrt就好了

main.c文件如下

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#include "greedysnack.h"

int main(){
	Set_Win();
	Start_Game();
	getch();
	Closed_Win();
	return 0;
}

greedysnack.h 如下

#ifndef _GREEDYSNACK_H_
#define _GREEDYSNACK_H_

#define BOARD_WIDTH		42
#define BOARD_HIEGTH	22
#define H_BOARDER		'-'
#define V_BOARDER		'|'
#define C_BOARDER		'+'
#define FRUIT 			'$'
#define L_BODY			'<'
#define R_BODY			'>'
#define U_BODY			'^'
#define D_BODY			'v'
#define INIT_LEN		5

#define Get_Head(_sn) ((_sn)->sn->next)
#define Get_Tail(_sn) (Get_Head(_sn)->next)

enum {
	LEFT = 0,
	DOWN,
	UP, 
	RIGHT,
};

enum {
	EMPTY = 0,
	E_BODY,
	E_FRUIT,
};

typedef struct snack_node{
	int x, y;
	char ch;
	struct snack_node* next;
}snack_node, *p_snack_node;

typedef struct snack{
	int len;
	int direction;
	p_snack_node head;
}snack, *p_snack;

void Set_Win();
void Closed_Win();
void Draw_Background();
int Move(p_snack);
void Create_Snack(p_snack_node);
void Start_Game();
void Game_Over(p_snack);
int Getch();
void Print_Snack(p_snack);
void Init_Snack(p_snack);
void Growth(p_snack);
void Gener_Fruit(p_snack);

#endif

greedysnack.c 文件如下

#include "greedysnack.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#include <string.h>
#include <errno.h>
#include <aio.h>
#include <time.h>
#include <signal.h>

#define BUFSIZE 10

#define DEBUG 0

struct aiocb cb;
int dx[] = {-1,0,0,1};
int dy[] = {0,1,-1,0};
char n2ch[] = {L_BODY, D_BODY, U_BODY, R_BODY};

char play_board[BOARD_WIDTH][BOARD_HIEGTH]; 

double Select_Level() {
	int lv = 0;
	double speed = 0;
	mvaddstr(LINES/2, COLS/2, "PLEASE SELECT THE LEVEL (0~9): ");
	refresh();
	scanw("%d", &lv);
	clear();
	speed = 1.0+(9.0-lv)/9.0;
	speed *= 1e5;
	return speed;
}

void Start_Game() {
	srand((int) time(0));

	int x0 = ( COLS - BOARD_WIDTH )/2, y0 = ( LINES -BOARD_HIEGTH )/2;
	int new_dirc = 0;
	char *buf = (char *)cb.aio_buf;
	int ret = 0;
	struct snack snk;
	double speed;

	speed = Select_Level();
	Draw_Background();
	memset(play_board, EMPTY, sizeof(play_board));
	Init_Snack(&snk);
	Gener_Fruit(&snk);

	move(y0, x0);
	while(aio_read(&cb) != -1) {
		while(aio_error(&cb) == EINPROGRESS) {
			fprintf(stderr, "dirction %d\n", snk.direction);
			if( Move(&snk)){
				refresh();
				usleep(speed);
			}
			else{
				Game_Over(&snk);
				return;
			}
		}

		if((ret = aio_return(&cb)) > 0){
			switch(buf[0]){
				case 'q':
					mvaddstr(y0+1, x0+1, "Bye~~~");
					refresh();
					return;
				case 'a':
					new_dirc = LEFT;
					break;
				case 's':
					new_dirc = DOWN;
					break;
				case 'd':
					new_dirc = RIGHT;
					break;
				case 'w':
					new_dirc = UP;
					break;
				default:
					break;
			}
			if(new_dirc + snk.direction != 3) {
				snk.direction = new_dirc;
			}
			bzero(buf, sizeof(*buf)*BUFSIZE);
		}
	}
}

void Game_Over(p_snack sn) {
	p_snack_node cur = sn->head;
	p_snack_node nxt = cur->next;
	while(nxt != sn->head) {
		free(cur);
		cur = nxt;
		nxt = cur->next;
	}
	free(cur);
	mvaddstr(LINES/2, COLS/2, "Game Over");
}

int Move(p_snack sn) {
	int x0 = ( COLS - BOARD_WIDTH )/2, y0 = ( LINES -BOARD_HIEGTH )/2;
	int dirction = sn->direction;
	int new_x, new_y;
	p_snack_node head = sn->head;
	p_snack_node tail = head->next;

	p_snack_node new_body = (p_snack_node) malloc(sizeof(snack_node));
	bzero(new_body, sizeof(snack_node));
	new_body->ch = n2ch[dirction];
	new_x = head->x + dx[dirction];
	new_y = head->y + dy[dirction];
	if(new_x <= x0 || new_x >= x0 + BOARD_WIDTH-1 ||
			new_y <= y0 || new_y >= y0 + BOARD_HIEGTH-1) {
		free(new_body);
		return 0;
	}
	else if(play_board[new_x-x0][new_y-y0] == E_BODY) {
		free(new_body);
		return 0;
	}
	else if(play_board[new_x-x0][new_y-y0] == E_FRUIT) {
		play_board[new_x-x0][new_y-y0] = E_BODY;
		Growth(sn);
		new_body->x = new_x;
		new_body->y = new_y;
		new_body->next = tail;
		head->next = new_body;
		sn->head = new_body;
		mvaddch(new_body->y, new_body->x, new_body->ch);
		Gener_Fruit(sn);
	}
	else {
		play_board[new_x-x0][new_y-y0] = E_BODY;
		new_body->x = new_x;
		new_body->y = new_y;
		new_body->next = tail->next;
		head->next = new_body;
		sn->head = new_body;
		mvaddch(new_body->y, new_body->x, new_body->ch);
		mvaddch(tail->y, tail->x, ' ');
		play_board[tail->x-x0][tail->y-y0] = EMPTY;
		free(tail);
	}
	
	return 1;
}

void Set_Aio_Read() {
	static char sbuf[BUFSIZE] = "";
	bzero(&cb, sizeof(cb));
	cb.aio_fildes = 0;
	cb.aio_buf = sbuf;
	cb.aio_nbytes = BUFSIZE;
	cb.aio_offset = 0;
}

void Set_Win() {
	initscr();
	curs_set(0);
	keypad(stdscr, TRUE);
	cbreak();

	Set_Aio_Read();
	return;
}

void Closed_Win() {
	endwin();
	return;
}

void Draw_Background() {
	int x0 = ( COLS - BOARD_WIDTH )/2, y0 = ( LINES -BOARD_HIEGTH )/2;
	mvaddch(y0, x0, C_BOARDER);
	mvaddch(y0+BOARD_HIEGTH-1, x0, C_BOARDER);
	mvaddch(y0, x0+BOARD_WIDTH-1, C_BOARDER);
	mvaddch(y0+BOARD_HIEGTH-1, x0+BOARD_WIDTH-1, C_BOARDER);
	move(y0, x0+1);
	hline(H_BOARDER, BOARD_WIDTH-2);
	move(y0+1, x0);
	vline(V_BOARDER, BOARD_HIEGTH-2);
	move(y0+1, x0+BOARD_WIDTH-1);
	vline(V_BOARDER, BOARD_HIEGTH-2);
	move(y0+BOARD_HIEGTH-1, x0+1);
	hline(H_BOARDER, BOARD_WIDTH-2);
	refresh();
	return;
}

void Init_Snack(p_snack snk) {
	int x0 = ( COLS - BOARD_WIDTH )/2, y0 = ( LINES -BOARD_HIEGTH )/2;
	int h_x = COLS/2, h_y = LINES/2;
	bzero(snk, sizeof(snack));
	snk->direction = RIGHT;
	snk->len = INIT_LEN;
	snk->head = (p_snack_node) malloc(sizeof(snack_node));
	p_snack_node tail = NULL;
	p_snack_node new_node = NULL;

	p_snack_node head = snk->head;
	tail = head;
	head->x = h_x;
	head->y = h_y;
	head->ch = '>';
	head->next = tail;

	for(int i = 1; i < snk->len; i++){
		head = snk->head;
		tail = head->next;
		new_node = (p_snack_node) malloc(sizeof(snack_node));
		new_node->x = h_x-i;
		new_node->y = h_y;
		new_node->ch = '>';
		new_node->next = tail;
		head->next = new_node;
	}

	p_snack_node p_cur = snk->head;
	for(int i = 0; i < snk->len; i++) {
		play_board[p_cur->x-x0][p_cur->y-y0] = E_BODY;
		mvaddch(p_cur->y, p_cur->x, p_cur->ch);
		p_cur = p_cur->next;
	}
	refresh();
}

void Growth(p_snack snk){
	snk->len+=1;
}

void Gener_Fruit(p_snack sn) {
	int x0 = ( COLS - BOARD_WIDTH )/2, y0 = ( LINES -BOARD_HIEGTH )/2;
	int n = random() % ((BOARD_WIDTH-2)*(BOARD_HIEGTH-2) - sn->len);
	int x = n % (BOARD_WIDTH-2) + 1, y = n/(BOARD_WIDTH-2) + 1;
	while(play_board[x][y] != EMPTY) {
		n++;
		x = n % (BOARD_WIDTH-2) + 1, y = n/(BOARD_WIDTH-2) + 1;
	}
	play_board[x][y] = E_FRUIT;
	mvaddch(y+y0, x+x0, FRUIT);
	refresh();
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Linux C语言实现贪吃蛇的基本步骤: 1. 定义蛇的结构体,包括蛇头、蛇身和蛇尾等信息。 2. 初始化蛇的位置和长度。 3. 定义食物的结构体,包括食物的位置和分值等信息。 4. 随机生成食物的位置。 5. 定义蛇的移动函数,包括蛇头的移动、蛇身的移动和蛇尾的删除等操作。 6. 定义蛇的死亡判断函数,包括蛇头是否撞墙和蛇头是否撞到蛇身等情况。 7. 定义游戏主循环,包括监听用户输入、移动蛇、判断蛇是否死亡、更新分数和重新生成食物等操作。 8. 在游戏结束后,清理蛇和食物的数据。 以下是一个简单的Linux C语言实现贪吃蛇的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <termios.h> #define ROW 20 #define COL 20 struct snake { int row; int col; struct snake *next; }; struct food { int row; int col; int score; }; struct snake *head = NULL; struct food food; void init_snake() { struct snake *p1 = (struct snake *)malloc(sizeof(struct snake)); p1->row = 5; p1->col = 5; p1->next = NULL; head = p1; struct snake *p2 = (struct snake *)malloc(sizeof(struct snake)); p2->row = 5; p2->col = 6; p2->next = NULL; p1->next = p2; } void init_food() { srand(time(NULL)); food.row = rand() % ROW; food.col = rand() % COL; food.score = 10; } void draw() { system("clear"); printf("score: %d\n", food.score); for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { if (i == food.row && j == food.col) { printf("*"); } else { struct snake *p = head; int flag = 0; while (p != NULL) { if (p->row == i && p->col == j) { printf("#"); flag = 1; break; } p = p->next; } if (flag == 0) { printf(" "); } } } printf("\n"); } } void add_snake_node(int row, int col) { struct snake *p = (struct snake *)malloc(sizeof(struct snake)); p->row = row; p->col = col; p->next = head; head = p; } void delete_snake_node() { struct snake *p = head; while (p->next->next != NULL) { p = p->next; } free(p->next); p->next = NULL; } void move_snake(int direction) { int row = head->row; int col = head->col; switch (direction) { case 1: row--; break; case 2: row++; break; case 3: col--; break; case 4: col++; break; default: break; } add_snake_node(row, col); if (row == food.row && col == food.col) { food.score += 10; init_food(); } else { delete_snake_node(); } } int snake_die() { if (head->row < 0 || head->row >= ROW || head->col < 0 || head->col >= COL) { return 1; } struct snake *p = head->next; while (p != NULL) { if (p->row == head->row && p->col == head->col) { return 1; } p = p->next; } return 0; } int getch() { struct termios tm, tm_old; int fd = STDIN_FILENO, c; if (tcgetattr(fd, &tm) < 0) { return -1; } tm_old = tm; cfmakeraw(&tm); if (tcsetattr(fd, TCSANOW, &tm) < 0) { return -1; } c = getchar(); if (tcsetattr(fd, TCSANOW, &tm_old) < 0) { return -1; } return c; } int main() { init_snake(); init_food(); int direction = 2; while (1) { draw(); int c = getch(); if (c == 'w' && direction != 2) { direction = 1; } else if (c == 's' && direction != 1) { direction = 2; } else if (c == 'a' && direction != 4) { direction = 3; } else if (c == 'd' && direction != 3) { direction = 4; } move_snake(direction); if (snake_die()) { printf("Game Over!\n"); break; } usleep(200000); } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值