C语言—贪吃蛇游戏

由于使用了一些库文件,上传了下载还需要积分,所以我会把所以代码都上传,方便日后复习结构设计的方向希望能有所作用,如果有什么缺点多谢点评

C语言—贪吃蛇游戏_第1张图片

首先是文件的划分

C语言—贪吃蛇游戏_第2张图片
需要注意的是,在函数命名的时候要注意清晰明了,还有就是注意模块的划分要清晰,该是哪个模块的任务就由哪个模块去做,不要混乱结果,打个比方,如蛇身的绘画,可以是snake模块的任务,但是在实际设计上,绘画并不是蛇本身的属性,他应该是view模块的任务,这样这是为了保证数据和操作相互隔离,分工明确。所以在整个程序中会有许多的函数去获得,snake和food的指针,这样看似麻烦。但却是在解决问题时得到了方便。
另外还有注意的是,在编写程序是要注意模块划分,尽可能减少全局变量的使用,如果非要用全局变量也要避免该变量被其他模块直接操作,这样就会使代码安全性提升。
当然在后面的程序中有一处变量我使用了extern int去共享,这个设计其实不太好,但是由于那几个窗口id属性是库函数调用的结果,所以我在这偷了个懒,希望大家不要学习

其次一点就是在跟新游戏数据时,这里采用了掩码的方式去比对,选择跟新的选项,这个技巧还是十分有用的

snake.h

我为了方便给头文件加了很多预编译,这是个极差的方式,请勿模仿。再此只是为了我调试的时候方便,是一个错误的做法
那么接下来整个程序还是分为四个模块,snake,food,view,main

#include 
#include 
#include 
#include 
#include
#include
#include 
#include "glConsole.h"

typedef struct body
{
	int x;
	int y;
	struct body *next;
}body;

typedef enum _tagDir
{
	Left,
	Right,
	Up,
	Down
} Movedir;

typedef struct Snake
{
	body* head;
	body* tail;
	Movedir movedir;
	Movedir newmovedir;//改变方向时,新的移动方向
	int     last_tx;                    // 存储蛇尾最后位置
	int     last_ty;
}Snake;

typedef struct _tagFood
{
	int x;
	int y;
} Food;

//snake
body *body_make(int x, int y, body *next);
Snake* snake_init();
void snake_release();
bool snake_death();
void snake_grow();
void snake_update();
Snake *retrn_snake_info();

//food
void food_make();
bool food_eat_hit();
Food return_food_info();

//view
void window_init();
void window_release();
void window_show_about();
void window_show_gameinfo(int score, int level, int speed);
void window_draw_wall();
void snake_draw();
void snake_tail_empty();
void food_draw();

snake.c

#include"snake.h"

extern int     about_window;         // 关于窗口ID
extern int     score_window;          // 成绩窗口ID
extern int     snake_window;          // 游戏窗口ID

Snake* snake = NULL;//蛇的全局变量


body *body_make(int x, int y, body *next)
{
	body *p = (body*)malloc(sizeof(body));
	p->x = x;
	p->y = y;
	p->next = next;
	return p;
}

Snake* snake_init()
{
	snake = (Snake*)malloc(sizeof(Snake));

	body *sn1 = body_make(17, 10, NULL);
	body *sn2 = body_make(18, 10, sn1);
	body *sn3 = body_make(19, 10, sn2);
	body *sn4 = body_make(20, 10, sn3);

	snake->head = sn4;
	snake->tail = sn1;

	snake->last_tx = sn1->x;
	snake->last_ty = sn1->y;

	snake->movedir = Right;
	snake->newmovedir = Right;

	return snake;
}

void snake_release()
{
	body *p = snake->head;
	while (p != NULL)
	{
		body *tmp = p->next;
		free(p);
		p = tmp;
	}
	free(snake);
}

void snake_update()
{
	snake->movedir = snake->newmovedir;

	snake->last_tx = snake->tail->x;
	snake->last_ty = snake->tail->y;

	body *prev = snake->head;
	body *curr = snake->head->next;

	int x = prev->x;
	int y = prev->y;
	while (curr != NULL)
	{
		int xx = curr->x;
		int yy = curr->y;

		curr->x = x;
		curr->y = y;

		prev = curr;
		curr = curr->next;

		x = xx;
		y = yy;
	}

	int xxx = 0;
	int yyy = 0;

	switch (snake->movedir)
	{
	case Left:xxx = -1; break;
	case Right:xxx = 1; break;
	case Up:yyy = -1; break;
	case Down:yyy = 1;  break;
	default:break;
	}
	snake->head->x += xxx;
	snake->head->y += yyy;
}

void snake_grow()
{
	body *p = (body*)malloc(sizeof(body));
	p->x = snake->last_tx;
	p->y = snake->last_ty;
	snake->tail->next = p;
	p->next = NULL;

	snake->tail = p;
}

bool snake_death()
{
	int x, y, w, h;
	glmxConsole_GetWindowRect(snake_window, &x, &y, &w, &h);

	if (snake->head->x == w || snake->head->x == 1 || snake->head->y == 0 || snake->head->y == h )
		return true;

	body *p = snake->head->next;
	while (p->next != NULL)
	{
		if (snake->head->x == p->x&&snake->head->y == p->y)
			return true;
		else p = p->next;
	}

	return false;
}

Snake *retrn_snake_info()
{
	assert(snake!=NULL);
	return snake;
}


food.c

#include"snake.h"

extern int     about_window;         // 关于窗口ID
extern int     score_window;          // 成绩窗口ID
extern int     snake_window;          // 游戏窗口ID

Food food;

void food_make()
{
	int x, y, w, h;
	glmxConsole_GetWindowRect(snake_window, &x, &y, &w, &h);
	food.x= rand() % (w-1) + 1;
	food.y= rand() % (h-1) + 1;
}

bool food_eat_hit()
{
	Snake *snake = retrn_snake_info();
	if (food.x == snake->head->x&&food.y == snake->head->y)
		return true;
	else return false;
}

Food return_food_info()
{
	return food;
}

view.c

#include"snake.h"

int     about_window = -1;          // 关于窗口ID
int     score_window = -1;          // 成绩窗口ID
int     snake_window = -1;          // 游戏窗口ID

void window_init()
{
	int main_window;
	int bottom_window1;

	main_window = glmxConsole_CreateWindow(60, 30, "Snake");
	glmxConsole_SplitWindow(main_window, 3, WND_SPLIT_HORIZONTAL, '=', 9, &about_window, &bottom_window1);
	glmxConsole_SplitWindow(bottom_window1, 2, WND_SPLIT_HORIZONTAL, '=', 9, &score_window, &snake_window);
}

void window_release()
{
}

void window_show_about()
{
	glmxConsole_WndDrawFormatText(about_window, 0, 0, 12, "Snake Ver1.0", TEXT_ALIGN_CENTER);
	glmxConsole_WndDrawFormatText(about_window, 0, 2, 12, "GLimix Studio - ZYF", TEXT_ALIGN_CENTER);
}

void window_show_gameinfo(int score,int level,int speed)
{
	char buffer[32];
	sprintf_s(buffer, 32, "SCORE: %d", score);
	glmxConsole_WndDrawFormatText(score_window, 0, 0, 6, buffer, TEXT_ALIGN_LEFT);

	sprintf_s(buffer, 32, "LEVEL: %d", level);
	glmxConsole_WndDrawFormatText(score_window, 0, 1, 6, buffer, TEXT_ALIGN_LEFT);

	sprintf_s(buffer, 32, "SPEED: %d", speed);
	glmxConsole_WndDrawFormatText(score_window, 0, 1, 8, buffer, TEXT_ALIGN_RIGHT);
}

void window_draw_wall()
{
	int x, y, w, h;
	glmxConsole_GetWindowRect(snake_window, &x, &y, &w, &h);
	for (int i = 0; i < w; i++)
	{
		glmxConsole_WndDrawTextEx(snake_window, i, 0, 82, " ");
		glmxConsole_WndDrawTextEx(snake_window, i, h, 82, " ");
	}
	for (int i = 0; i < h; i++)
	{
		glmxConsole_WndDrawTextEx(snake_window, 0, i, 82, " ");
		glmxConsole_WndDrawTextEx(snake_window, w, i, 82, " ");
	}

}

void snake_draw()
{
	Snake *snake = retrn_snake_info();
	body *p = snake->head;
	while (p->next != NULL)
	{
		if (p == snake->head)
			glmxConsole_WndDrawTextEx(snake_window, p->x, p->y, 8, "@");
		else
			glmxConsole_WndDrawTextEx(snake_window, p->x, p->y, 8, "=");

		p = p->next;
	}
	glmxConsole_WndDrawTextEx(snake_window, p->x, p->y, 8, "-");
}

void snake_tail_empty()
{
	Snake *snake = retrn_snake_info();
	glmxConsole_WndDrawTextEx(snake_window, snake->last_tx, snake->last_ty, 8, " ");
}

void food_draw()
{
	Food food = return_food_info();
	glmxConsole_WndDrawTextEx(snake_window, food.x, food.y, 4, "*");
}

main.c

#include"snake.h"
extern int     about_window;         // 关于窗口ID
extern int     score_window;          // 成绩窗口ID
extern int     snake_window;          // 游戏窗口ID

//更新掩码
#define update_none  0x00
#define update_score 0x01
#define update_all   0x08

void update_info(int *score, int *level, int *speed, int update)
{
	switch (update)
	{
	case update_none:break;
	case update_score:*score += 1;break;
	case update_all:
		*score += 1;
		*level += 1;
		*speed += 1;
		break;
	}
}

int main()
{
	system("cls");
	glmxConsole_Init();

	window_init();
	int score = 0;
	int level = 1;
	int speed = 1;
	window_show_about();
	window_show_gameinfo(score, level, speed);
	window_draw_wall();
	
	Snake *snake = NULL;
	snake=snake_init();
	snake_draw();

	int time_count = 20;//画面更新计时器

	int time = 10;

	int update;
	bool food_existence = false;

	for (;;)
	{
		snake_death();

		if (time_count-- == 0)
		{
			snake_update();
			snake_tail_empty();
			snake_draw();
			glmxConsole_SetCursorPosition(59, 29);
			if (food_eat_hit())
			{
				update_info(&score, &level, &speed, update_score);
				window_show_gameinfo(score, level, speed);
				if (score % 5 == 0)
				{
					update_info(&score, &level, &speed, update_all);
					if (time != 0)
					{
						time -= 1;
					}
					
				}
				food_existence = false;
				snake_grow();
			}

			if (!food_existence)
			{
				food_make();
				food_draw();
				food_existence = true;
			}

			if (snake_death())
			{
				glmxConsole_WndDrawTextEx(snake_window, 25,8, 2, "GAME OVER \n");
				break;

			}


			time_count = 20;
		}

		if (kbhit())
		{
			char move = getch();
			switch (move)
			{
			case 'w':
			case 'W':
				if (snake->movedir != Down)
					snake->newmovedir = Up;
				break;
			case 's':
			case 'S':
				if (snake->movedir != Up)
					snake->newmovedir = Down;
				break;
			case 'd':
			case 'D':
				if (snake->movedir != Left)
					snake->newmovedir = Right;
				break;
			case 'a':
			case 'A':
				if (snake->movedir != Right)
					snake->newmovedir = Left;
				break;
			}
		}


		Sleep(time);

	}
	getch();

	snake_release();

	window_release();

	glmxConsole_Release();

	return 0;
}

你可能感兴趣的:(C语言项目(学生))