闲着没事,又刚学了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();
}