本節需用到的知識點:

(1)結構體知識

(1)蛇運動軌跡的判定

怎樣檢測蛇是否碰到圍牆或事物呢,so easy,只要判定蛇頭的位置是否與圍牆或食物的位置重合,用C語言來表述就是

if(snake_x==food_x&&snake_y==food_y) //蛇頭與食物位置重合

if(snake_x==0||snake_x==19||snake_y==0||snake_y==39) //蛇頭位置與四周牆體重合

我們可以再單獨寫一個函數,檢測發生碰撞後,再執行相應的語句

void ishit()
{
if(snake_x==food_x&&snake_y==food_y)//判斷蛇頭位置是否與食物位置相重合
{
//如果隨機生成的食物位置與圍牆或蛇體或牆體重合,則循環再次隨機生成食物位置
while(map[food_x][food_y]!=0)
{
food_x=rand()%19+1; //隨機在1-19的位置產生食物
food_y=rand()%39+1; //隨機在1-39的位置產生食物
}
map[food_x][food_y]=4; //在地圖上顯示食物
}
if(snake_x==0||snake_x==19||snake_y==0||snake_y==39)//判斷蛇頭位置是否與牆的位置重合
{
system("pause"); //暫停程序
exit(0); //退出程序
}
}

但是隨後新的問題又誕生了,蛇吃了食物是應該變長了,為解決此問題,我們需要定義一個結構體數組來表示蛇的身體

struct Snake
{
int x; //每節蛇的x坐標
int y; //每節蛇的y坐標
}snake[800];

同時我們再聲明一個整型變數,既可以表示得分,又可以表示蛇的長度,蛇每吃一個食物得一分,加長一節

下面咱們討論一下蛇怎樣沿著一定的軌跡運動的問題,假設蛇身總共為6節,分別是snake[0]到snake[5],向前移動的示意圖如下:

由此可以看出,先前移動一次,只需要將數組中前一個的值賦給後一個值即可,知道了此規律,我們就可以繼續向下編寫了,主要部分如下

for(int i=score;i>0;i--)
{
snake[i].x=snake[i-1].x;
snake[i].y=snake[i-1].y;
map[snake[i].x][snake[i].y]=3;
}

因為加入了結構體部分,重新定義了關於蛇的結構體數組,所以程序內整改部分叫多,下面將完成程序寫出:

#include <stdio.h>
#include<Windows.h>
#include<conio.h>
struct Snake
{
int x; //每節蛇的x坐標
int y; //每節蛇的y坐標
}snake[800];

int map[20][40]; //二維數組map[][],用來表示遊戲地圖
//為0時,表示空白,什麼都沒有
//為1時,表示上下圍牆
//為2時,表示左右圍牆
//為3時,表示蛇
//為4時,表示食物

int direction=1; //1表示向上,程序開始默認向上
//2表示向下
//3表示向左
//4表示向右
int food_x=15,food_y=6; //食物位置
int score=0; //遊戲得分

void clear()
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);//獲取標準輸出設備句柄
COORD coord; //定義游標位置結構體,其中包含x y坐標兩個變數
coord.X=0; //x=0屏幕最上方
coord.Y=0; //y=0屏幕最左邊
SetConsoleCursorPosition(handle,coord);//將游標位置移至屏幕左上角
}

void show() //顯示界面
{
for(int i=0;i<20;i++) //列印地圖
{
for(int j=0;j<40;j++)
switch(map[i][j])
{
case 0: printf(" ");break; //0代表空格,什麼也不列印
case 1: printf("-");break; //1代表上下圍牆
case 2: printf("|");break; //2代表左右圍牆
case 3: printf("@");break; //3代表蛇身用@表示
case 4: printf("$");break; //4代表食物用$表示
}
printf("
");
}
printf("遊戲得分: %d",score);
}

void init() //初始化地圖
{
int i,j;
for(i=0;i<20;i++)
for(j=0;j<40;j++)
map[i][j]=0; //初始化二維數組,全部置為0

for(i=0;i<20;i++)
for(j=0;j<40;j++)
{
if(i==0||i==19)
map[i][j]=1; //賦值上下圍牆 ----------
if(j==0||j==39)
map[i][j]=2; //賦值左右圍牆|||||||||||
}

snake[0].x=10;
snake[0].y=20;
map[snake[0].x][snake[0].y]=3; //利用變數在地圖中間初始化蛇身
map[food_x][food_y]=4; //初始化食物位置,隨便定義了一個位置
show();
}

void move() //響應鍵盤輸入,控制蛇的移動
{
map[snake[score].x][snake[score].y]=0;//將最後一節賦值為0

if(kbhit())
{
char c;
c=getch();
switch(c)
{
case w:direction=1; break; //按w鍵,蛇向上移動
case s:direction=2; break; //按s鍵,蛇向下移動
case a:direction=3; break; //按a鍵,蛇向左移動
case d:direction=4; break; //按d鍵,蛇向右移動
default: break;
}
}

for(int i=score;i>0;i--)
{
snake[i].x=snake[i-1].x;
snake[i].y=snake[i-1].y;
map[snake[i].x][snake[i].y]=3;
}

switch(direction) //根據direction值,改變蛇的坐標
{
case 1:snake[0].x--; break;
case 2:snake[0].x++; break;
case 3:snake[0].y--; break;
case 4:snake[0].y++; break;
default:break;
}

map[snake[0].x][snake[0].y]=3; //更新地圖,將蛇的新位置賦值為3
}

void ishit()
{
if(snake[0].x==food_x&&snake[0].y==food_y)//判斷蛇頭位置是否與食物位置相重合
{
score++; //得分加1
//如果隨機生成的食物位置與圍牆或蛇體或牆體重合,則循環再次隨機生成食物位置
while(map[food_x][food_y]!=0)
{
food_x=rand()%19+1; //隨機在1-19的位置產生食物
food_y=rand()%39+1; //隨機在1-39的位置產生食物
}
map[food_x][food_y]=4; //在地圖上顯示食物
}
//判斷蛇頭位置是否與牆的位置重合
if(snake[0].x==0||snake[0].x==19||snake[0].y==0||snake[0].y==39)
{
system("pause"); //暫停程序
exit(0); //退出程序
}
}

void main()
{
init();
while(1)
{
clear(); //調用自定義的清屏函數
move();
show();
ishit();
Sleep(200); //睡眠函數,使程序暫停0.1秒,防止運行太快
}
}

運行界面如下

不過此遊戲界面簡陋,給同學們看都拿不出手,下一步咱們要運用easyx庫的相關圖形函數,加入圖片,美化一下界面

推薦閱讀:

相关文章