在学习过程中作为练习做的一个小游戏,还有许多做得不好的地方,欢迎各位帮我指出来,共同进步!
部分思路在代码的注释中有体现。
这是代码部分:
#include <graphics.h>
#include <stdio.h>
#define Interval 20
#define Width 30
#define Height 30 //可以只定义Width,即一个正方形
#define Wall -1
#define Empty 0
#define Body 1
#define Head 2
#define Food 3
typedef struct Snake
{
int row;
int col;
}Snake;
int grid[600/Interval][600/Interval] = {0}; //记录蛇状态的二维数组
int speed = Interval;
int len = 3; //记录蛇的长度,默认是3(包括蛇头)
int dir = 3; //移动方向,默认向左
Snake snake[Width*Height]; //记录蛇的结构体数组
bool food_exsit = false; // 标记食物是否存在
Snake snake_food = {0}; //生成食物的坐标
enum Dir{
UP,RIGHT,DOWN,LEFT
};
int score = 0;
int vect[4][2] = {{0,-1},{1,0},{0,1},{-1,0}}; //方向向量,分别表示上、右、下、左
bool game_over = false; //游戏是否结束标志,false表示没有结束
int sleep_time = 0;
PIMAGE img;
void draw_Wall();
void init_game();
void init_snake();
void draw_snake();
void prod_food();
void move(int dir);
void begin_game();
void KeyEnevnt();
void eat_food();
void judge_border();
void inc_len(int dir);
void judge_gameover(int choice);
void draw_end();
void draw_welcome();
int choose();
void continue_game();
void init_grid();
int main()
{
initgraph(Interval*Width,Interval*Height);
// initgraph(800,800);
draw_welcome();
int ret = choose();
switch (int a = 0)
{
case 0:begin_game(); break;
case 1: continue_game(); break;
}
begin_game();
getch();
return 0;
}
void draw_welcome()
{
img = newimage(0,0);
getimage(img,"E:\\photo\\picture-9.jpg");
putimage(0,0,img);
char str[2][20] = {{"begin game"},{"continue game"}}; //继续游戏暂时没有实现
setfillcolor(GREEN);
setfontbkcolor(WHITE);
setfont(20,0,"楷体");
for(int i = 0;i < 2;i++)
{
ege_fillrect(Height/2*Interval-80,Width/2*Interval+ 120*i,200,100);
outtextxy(Height/2*Interval-20,Width/2*Interval+ 120*i+40,str[i]);
}
}
int choose()
{
mouse_msg msg;
int ret = -1;
bool flag = true;
draw_welcome();
for(;is_run() && flag;delay_fps(60))
{
if(mousemsg())
{
msg = getmouse();
if(msg.is_left() && msg.is_down())
{
for(int i = 0;i < 2;i++)
{
if(msg.x >= Height/2*Interval-80 && msg.x <= Height/2*Interval-80+200 && msg.y >= Width/2*Interval+ 120*i && msg.y <= Width/2*Interval+ 120*i+100)
{
ret = i;
flag = false;
break;
}
}
}
}
}
return ret;
}
void continue_game()
{
//用一个.txt文件记录上一次的数组值,再重新为当前数组赋值,有时间再做
;
}
void begin_game()
{
init_game();
for(;is_run();delay_fps(60))
{
cleardevice();
draw_snake();
if(food_exsit == false) //false表示食物被吃
{
inc_len(dir);
prod_food();
}
move(dir);
judge_gameover(0);
if(game_over)
draw_end();
eat_food();
KeyEnevnt();
Sleep(100);
}
}
void inc_len(int dir) //蛇的长度增加(在蛇移动的方向)
{
int x = vect[dir][0]; int y = vect[dir][1];
snake[len].row = snake[len-1].row+y;
snake[len].col = snake[len-1].col + x;
len++;
grid[snake[len-1].row][snake[len-1].col] = Body;
}
void judge_border() //判断蛇是否超出边界
{
bool flag = true;
if(snake[0].row < 1)
snake[0].row = Height - 2;//为什么要减2:让蛇头从倒数第二个格子出来
if(snake[0].row > Height-2) //这里的row,col表示蛇的数组坐标
snake[0].row = 1;
if(snake[0].col < 1)
snake[0].col = Width-2;
if(snake[0].col > Width-2)
snake[0].col = 1;
judge_gameover(0);
grid[snake[0].row][snake[0].col] = Head;
}
void eat_food()
{
if(snake[0].row == snake_food.row && snake[0].col == snake_food.col)
{
score += 10;
food_exsit = false;
}
}
void KeyEnevnt()
{
key_msg msg;
while(kbhit()) //在一个循环内进行按键的判断,比起用if判断按键的情况要好一些
{
msg = getkey();
int key = msg.key;
switch (key)
{
case 'w': case 'W':
if(dir != DOWN)
dir = UP; break;
case 'd': case 'D':
if(dir != LEFT)
dir = RIGHT; break;
case 's': case 'S':
if(dir != UP)
dir = DOWN; break;
case 'a': case 'A':
if(dir != RIGHT)
dir = LEFT; break;
}
}
}
void init_game()
{
//设置墙
for(int i = 0;i < Width;i++)
{
grid[i][0] = Wall;
grid[0][i] = Wall;
grid[i][Height-1] = Wall;
grid[Width-1][i] = Wall;
}
game_over = false;
food_exsit = false;
ege_enable_aa(true);
setbkcolor(EGERGB(116,206,222));
setcolor(GREEN);
init_snake();
prod_food();
len = 3;
init_grid();
score = 0;
}
void draw_Wall()
{
setfillcolor(YELLOW);
setcolor(BLACK);
for(int i = 0;i < Width;i++)
{
ege_fillrect(0,Interval*i,Interval,Interval*(i+1));
ege_fillrect(Interval*i,0,Interval*(i+1),Interval);
ege_fillrect(Interval*i,(Height-1)*Interval,Interval*(i+1),(Height)*Interval);
ege_fillrect((Width-1)*Interval,Interval*i,Width*Interval,Interval*(i+1));
line(i*Interval,0,i*Interval,(Width)*Interval);
line(0,i*Interval,(Width)*Interval,i*Interval);
}
}
//初始化蛇
void init_snake()
{
len = 3;
grid[Height/2][Width/2] = Head; //Height表示行,Width表示列
grid[Height/2][Width/2+1]= Body;
grid[Height/2+1][Width/2+1] = Body;
snake[0].row = Height/2; snake[0].col = Width/2;
snake[1].row = Height/2; snake[1].col = Width/2+1;
snake[2].row = Height/2+1; snake[2].col = Width/2+1;
}
//以表示格子的数组grid为基准绘图
void draw_snake()
{
draw_Wall();
setfillcolor(GREEN);
for(int row = 0;row < Height;row++)
{
for(int col=0;col < Width;col++)
{
if(grid[row][col] == Head)
{
// ege_rectangle(col*Interval,row*Interval,Interval,Interval);
ege_fillellipse(col*Interval,row*Interval,Interval,Interval); //注意坐标和row、col的关糄1�7
}
if(grid[row][col] == Body)
{
setcolor(BLUE);
ege_rectangle(col*Interval,row*Interval,Interval,Interval);
circle(col*Interval+10,row*Interval+10,10);
}
}
}
if(food_exsit)
{
setfillcolor(RED);
ege_fillellipse(snake_food.col*Interval,snake_food.row*Interval,Interval,Interval);
}
}
//随机生成食物
void prod_food()
{
randomize();
int row,col;
do{
col = random(Width);
row = random(Height);
}while(grid[row][col] != Empty); //避免食物生成在墙上或者蛇上
snake_food.row = row;
snake_food.col = col;
food_exsit = true;
}
//控制蛇的移动
void move(int dir)
{
int x = vect[dir][0];
int y = vect[dir][1];
grid[snake[len-1].row][snake[len-1].col] = Empty; //最后一节标记为空
for(int i = len-1;i > 0;i--) //从蛇尾开始,每个表示蛇体的结构体向前移动,蛇头再以表示dir的方向上增加
{ //宏观上看,蛇头就开始移动
snake[i] = snake[i-1];
}
snake[0].row += y; snake[0].col += x;
// grid[snake[0].row][snake[0].col] = Head;
for(int i = 1;i < len-1;i++)
{
grid[snake[i].row][snake[i].col] = Body;
}
// grid[snake[0].row][snake[0].col] = Head;
judge_border();
}
void judge_gameover(int choice) //choice表示选择游戏模式
{
if(choice == 0) //可以穿墙
{
if(grid[snake[0].row][snake[0].col] == Body) //蛇头和蛇身重合
game_over = true;
}
//不可以穿墙的,就是增加一个边界的判断条件
;
}
void draw_end() //游戏结束时的界面
{
cleardevice();
setbkcolor(EGERGB(116,206,222));
char str[3][30] = {{"game voer"},{"Press esc to exit"}};
sprintf(str[2],"score:%d",score);
setfont(40,0,"楷体");
for(int i = 0;i < 3;i++)
{
outtextxy(Height/2*Interval-70,Width/2*Interval+50*i,str[i]);
}
key_msg msg;
bool flag = true;
while(flag){
while(kbmsg){
msg = getkey();
if(msg.key == key_esc && msg.msg == key_msg_down)
flag = false;
}
}
printf("Exit succseefully\n");
// game_over = false;
init_game();
begin_game();
}
void init_grid(){ //初始化记录蛇状态的格子
for(int i = 0;i < Width;i++){
for(int j = 0;j < Height;j++){
grid[i][j] = 0;
}
}
}