由于使用了一些库文件,上传了下载还需要积分,所以我会把所以代码都上传,方便日后复习结构设计的方向希望能有所作用,如果有什么缺点多谢点评
需要注意的是,在函数命名的时候要注意清晰明了,还有就是注意模块的划分要清晰,该是哪个模块的任务就由哪个模块去做,不要混乱结果,打个比方,如蛇身的绘画,可以是snake模块的任务,但是在实际设计上,绘画并不是蛇本身的属性,他应该是view模块的任务,这样这是为了保证数据和操作相互隔离,分工明确。所以在整个程序中会有许多的函数去获得,snake和food的指针,这样看似麻烦。但却是在解决问题时得到了方便。
另外还有注意的是,在编写程序是要注意模块划分,尽可能减少全局变量的使用,如果非要用全局变量也要避免该变量被其他模块直接操作,这样就会使代码安全性提升。
当然在后面的程序中有一处变量我使用了extern int去共享,这个设计其实不太好,但是由于那几个窗口id属性是库函数调用的结果,所以我在这偷了个懒,希望大家不要学习
其次一点就是在跟新游戏数据时,这里采用了掩码的方式去比对,选择跟新的选项,这个技巧还是十分有用的
我为了方便给头文件加了很多预编译,这是个极差的方式,请勿模仿。再此只是为了我调试的时候方便,是一个错误的做法
那么接下来整个程序还是分为四个模块,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();
#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;
}
#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;
}
#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, "*");
}
#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;
}