论坛首页 编程语言技术论坛

一个能在Telnet或SSH终端玩的贪食蛇小游戏

浏览 2160 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-10-23   最后修改:2009-10-03
//snake.h
#define SHM_KEY 1234

#define UP	119
#define DOWN	115
#define LEFT	 97
#define RIGHT	100
#define QUIT	122

#define direct	(*((int *)p_shm))
extern void *p_shm;
extern int v_speed;

extern void snake_init();
extern int snake_nextstep();

#include "snake.h"

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <curses.h>
#include <string.h>
#include <sys/types.h>

#define START_X 10
#define START_Y 10
#define INIT_SIZ 5
#define H_LEN	80	
#define V_LEN	35


int screen_arr[H_LEN * V_LEN];
int snake_len = 0;
extern int v_speed;

/* Snake Body Node */
typedef struct node{
	int pos_x;
	int pos_y;
	struct node *next;
	struct node *pre;
}BNode;

BNode *s_head, *s_end;

/************************************************
 *		functions declare
 ***********************************************/
extern void snake_init();

static void snake_display();
static inline void snake_feed();
static inline void snake_head_grow(int px, int py);
static inline void snake_tail_cut();

extern void snake_init()
{
	s_head = (BNode *)malloc(sizeof(BNode));
	s_head->pos_x = START_X;
	s_head->pos_y = START_Y;
	s_head->next = NULL;
	s_head->pre = NULL;
	s_end = s_head;
	screen_arr[START_X + START_Y * H_LEN] = 1;
	
	int i;
	for (i = 1; i < INIT_SIZ; i++) 
		snake_head_grow(START_X + i, START_Y);
	snake_feed();
	snake_display();
}

extern int snake_nextstep()
{
	int next_px = s_head->pos_x;
	int next_py = s_head->pos_y;

	switch (direct) {
		case UP: 	next_py--;	break;
		case RIGHT:	next_px++;	break;
		case DOWN:	next_py++;	break;
		case LEFT:	next_px--;	break;
	}

	int pos = next_px + next_py * H_LEN;

	/* grip itself */
	if (screen_arr[pos] == 1)
		return ERR;
	
	/* up against the wall */
	if (next_px < 0 || next_px >= H_LEN ||
	    next_py < 0 || next_py >= V_LEN)
		return ERR;
	
	int grow = 0;
	/* eat a food */
	if (screen_arr[pos] == 2) {
		grow = 1;
		snake_len++;
		snake_feed();
	}

	snake_head_grow(next_px, next_py);

	if (!grow) 
		snake_tail_cut();

	snake_display();
	return OK;
}

static void snake_display()
{
	printw("  			    Hungry Snake -- Enjoy it! :)\n");
	printw("  +---------------------------------------------"
                  "-----------------------------------+\n");
	
	int i, j;
	for (i = 0; i < V_LEN; i++){
		printw("  |");
		for(j = 0; j < H_LEN; j++) {
			int pos = i * H_LEN + j;
			printw("%c", screen_arr[pos] == 0 ? ' ' :
				    (screen_arr[pos] == 1) ? '#' : '$');
		}
		printw("|\n");
	}
	printw("  +---------------------------------------------"
                  "-----------------------------------+\n");
	printw("  Direction: %s\n", direct == UP ? "Up" : 
		(direct == DOWN ? "Down" : (direct == LEFT ? "Left" : "Right")));
	printw("  Scores: %d", snake_len);
	refresh();
}


/********************************************************
 *		 static functions
 ********************************************************/

static inline void snake_feed()
{
	int pos = rand() % (H_LEN * V_LEN);
	while (screen_arr[pos] == 1) 
		pos = rand() % (H_LEN * V_LEN);
	screen_arr[pos] = 2;
	v_speed -= 10;
}

static inline void snake_head_grow(int px, int py)
{
	BNode *p = (BNode *)malloc(sizeof(BNode));
	p->pos_x = px;
	p->pos_y = py;
	
	p->pre = NULL;
	p->next = s_head;
	s_head->pre = p;
	s_head = p;
	screen_arr[px + py * H_LEN] = 1;
}

static inline void snake_tail_cut()
{
	screen_arr[s_end->pos_x + s_end->pos_y * H_LEN] = 0;
	s_end = s_end->pre;
	free(s_end->next);
	s_end->next = NULL;
}

//usr_handler.c
#include "snake.h"

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <curses.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <time.h>

static void wait_user_handle();

void *p_shm = NULL;
int shmid = 0;;
int v_speed = 200;

int main(int argc, char *argv[])
{
	pid_t pid;
	initscr();
	if ((pid = fork()) == 0) {
		sleep(2);
		shmid =
		    shmget((key_t) SHM_KEY, sizeof(int), 0666 | IPC_CREAT);
		p_shm = shmat(shmid, (void *) 0, 0);
		struct timespec slp = { (time_t) 0, 1000000 * v_speed };
		snake_init();
		while (true) {
			if (direct == QUIT)
				break;
			clear();
			snake_nextstep();	/* sleep specified nanoseconds and continue to run. */
			slp.tv_nsec = 1000000 * v_speed;
			nanosleep(&slp, NULL);
		}
		shmdt(p_shm);
	} else {		/* create shared memory by parent process. */
		shmid =
		    shmget((key_t) SHM_KEY, sizeof(int), 0666 | IPC_CREAT);
		if (shmid == -1) {
			printw("shmget failed!\n");
			exit(EXIT_FAILURE);
		}
		p_shm = shmat(shmid, (void *) 0, 0);
		wait_user_handle();
		waitpid(pid, NULL, 0);	/* destroy shared memory by parent process. */
		shmdt(p_shm);
		shmctl(shmid, IPC_RMID, 0);
		endwin();
	} exit(EXIT_SUCCESS);
} 

static void wait_user_handle()
{
	int i;
	int run = true;

	int UP_DOWN = UP + DOWN;
	int LEFT_RIGHT = LEFT + RIGHT;
	int sum;
	while (run) {
		noecho();
		i = getch();
		echo();
		switch (i) {
		case UP:
		case DOWN:
		case LEFT:
		case RIGHT:
			sum = i + direct;
			if(sum != UP_DOWN && sum != LEFT_RIGHT)
				direct = i;
			break;
		case QUIT:
			run = false;
			direct = i;
			break;
		}
	}
}
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics