貪吃蛇
效果示範:
操作說明:
-
、W
、S
、A
控制 上 、下、左、右 方向,D
暫停,按下任意鍵繼續空格
- 每吃掉一個食物長度加1,界面下方顯示目前長度
- 蛇頭撞到自身或邊界後顯示
2秒(時間可更改),任意鍵退出game over!
- 由于上下字元間隔與左右字元間隔不一緻,縱向移動時移動速度會超過橫向移動速度。
- 畫面顯示:遊戲畫面資訊存入二維數組:數組下标映射遊戲中位置坐标,數組元素的值(0,1…)分别表示遊戲場景中不同的對象(空白處,蛇頭…),周遊數組根據不同的值輸出遊戲畫面。每次輸出前将光标調至首行首列處,覆寫之前的輸出畫面,達到重新整理遊戲畫面的效果。
- 小蛇移動與成長:根據方向變量的值(1,2,3,4)來向某一方向(上,下,左,右)持續前進,當方向按鍵按下時,修改方向變量的值以改變方向。蛇頭對應的數組元素的數值為1,從頭到尾,數值遞增(2,3,4,5…),每次更新畫面,使數組中大于0的數組元素(蛇頭蛇身)的值加一,蛇頭的值變為2,根據行進方向在新方向上生成新的蛇頭(數值為1),未吃到食物的情況下,将蛇尾變為空白。即通過向目标方向生成一個新蛇頭,去掉蛇尾,來達到移動的效果,而吃掉食物時生成新蛇頭而不去掉蛇尾,使長度加一。
- 食物生成:當食物被吃掉後,随機生成一個處于空白處的坐标,改變該坐标的值為新的食物。
以下為帶注釋的完整源代碼:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define high 25 //畫布高
#define width 60 //畫布寬
#define border -1 //邊界
#define blank 0 //空白
#define head 1 //蛇頭
#define food -2 //食物
int canvas[high+1][width+1]; //畫布數組
int direction; //行進方向
int head_h,head_w; //蛇頭坐标
int tail_h,tail_w; //蛇尾坐标
int food_h,food_w; //食物坐标
int length; //貪吃蛇長度(包括蛇頭)
int Isover; //遊戲結束标志
void Startup(); //遊戲數值初始化
void Show(); //遊戲界面輸出
void UpdateInput(); //因輸入導緻的遊戲狀态更新
void UpdateNormal(); //與輸入無關的遊戲狀态更新
int main()
{
Startup();
while(Isover){
Show();
UpdateInput();
UpdateNormal();
}
printf("\ngame over!\n");
Sleep(2000);
system("pause");
return 0;
}
void Startup(){
/*設定邊界值*/
for(int i=0;i<=width;i++){
canvas[0][i]=border;
canvas[high][i]=border;
}
for(int i=0;i<=high;i++){
canvas[i][0]=border;
canvas[i][width]=border;
}
/*設定貪吃蛇初始位置*/
head_h=high/2;
head_w=width/2;
canvas[head_h][head_w]=head;
/*貪吃蛇初始長度*/
length=6;
for(int i=1;i<length;i++){ //設定蛇身,應與初始移動方向相反
canvas[head_h][head_w-i]=i+1;
}
/*設定初始方向*/
direction=4;
/*設定食物位置,随機出現*/
srand(time(NULL));
do{
food_h=rand()%high;
food_w=rand()%width;
}while(canvas[food_h][food_w]!=blank);
canvas[food_h][food_w]= food;
/*設定遊戲結束條件*/
Isover=1;
}
void Show(){
HideCursor(); //隐藏光标
gotoxy(1,1); //回調光标位置,重新整理畫面
for(int i=0;i<=high;i++){ //輸出遊戲界面
for(int j=0;j<=width;j++){
if(canvas[i][j] == border){ //邊界
printf("#");
}
else if(canvas[i][j] == head ){ //蛇頭
printf("@");
}
else if(canvas[i][j]== blank){ //空白處
printf(" ");
}
else if(canvas[i][j]== food){ //食物
printf("O");
}
else if(canvas[i][j]> 0){ //蛇身
printf("*");
}
}
printf("\n");
}
printf("\nLength of the snake:%2d",length);
}
void UpdateInput(){
char key_W=GetKeyState('W'), //監測 W 鍵是否按下
key_S=GetKeyState('S'), //監測 S 鍵是否按下
key_A=GetKeyState('A'), //監測 A 鍵是否按下
key_D=GetKeyState('D'), //監測 D 鍵是否按下
key_BS=GetKeyState(' '); //監測 空格 鍵是否按下
if(kbhit()){ //當有鍵按下時
if(key_BS<0){ //當按下 空格鍵 時,遊戲暫停
printf("\n遊戲暫停!");
system("pause");
system("cls");
}
if(key_W<0 && direction!=2){ //當按下 W 鍵,且原方向不為下時,上移
direction=1;
}
if(key_S<0 && direction!=1){ //當按下 S 鍵,且原方向不為上時,下移
direction=2;
}
if(key_A<0 && direction!=4){ //當按下 A 鍵,且原方向不為右時,左移
direction=3;
}
if(key_D<0 && direction!=3){ //當按下 D 鍵,且原方向不為左時,右移
direction=4;
}
}
}
void UpdateNormal(){
int max=0;
for(int i=1;i<high;i++){ //周遊畫布
for(int j=1;j<width;j++){
if(canvas[i][j] > 0){ //使蛇身的值自增
canvas[i][j]++;
if(canvas[i][j]>max){ //定位數值最大點,即蛇尾處
max=canvas[i][j];
tail_h=i;
tail_w=j;
}
}
}
}
switch(direction){ //蛇頭位置向目前方向移動
case 1:head_h--;break;
case 2:head_h++;break;
case 3:head_w--;break;
case 4:head_w++;break;
}
if(canvas[head_h][head_w] == blank){ //新蛇頭在空白處
canvas[head_h][head_w] = head;
canvas[tail_h][tail_w] = blank;
}
else if(canvas[head_h][head_w] == food){ //新蛇頭在食物處
length++;
canvas[head_h][head_w] = head;
do{ //随機出現食物,且食物隻能重新整理在空白處
food_h=rand()%high;
food_w=rand()%width;
}while(canvas[food_h][food_w]!=blank);
canvas[food_h][food_w]= food;
}
else{ //新蛇頭在邊界處或蛇身處
Isover=0;
}
}
void gotoxy(int x,int y){ //回調光标
COORD pos;
pos.X=x-1;
pos.Y=y-1;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
void HideCursor(){ //隐藏光标函數
CONSOLE_CURSOR_INFO cursor;
cursor.bVisible = FALSE;
cursor.dwSize = sizeof(cursor);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorInfo(handle, &cursor);
}
以上内容在觀看河海大學童晶老師的C語言遊戲課程的基礎上總結改進完成。