文章目錄
- 1.效果展示
- 2.設計思路
- 2.1圖案顯示
- 2.2蛇頭的移動
- 2.3食物的生成
- 2.4蛇身體的生成與移動
- 2.5判斷是否撞墻和列印得分
- 3.完整代碼
1.效果展示

2.設計思路
2.1圖案顯示
利用二維陣列構建圖案,總共有墻壁,蛇頭,蛇身,食物,空白五種元素,因此只需要二維陣列中的元素有五種不同的值即可;


2.2蛇頭的移動
貪吃蛇是會自動移動的,我們首先讓蛇頭能自動移動,由于我們用陣列來表示元素在地圖中的位置,讓元素移動就是讓元素的坐標改變,
因此我們需要構建函式來完成蛇頭坐標的自動移動,同時需要對我們輸入的方向鍵做出判斷,改變移動的方向,

2.3食物的生成
食物的生成很簡單,只要種下一個亂數種子,然后給一個變數用來判斷是否生成食物即可,需要注意的是食物的坐標別越界

2.4蛇身體的生成與移動
蛇身體的計算:
首先,蛇身體的移動前必須產生身體即是否吃到食物,可以給一個變數當計數器來判斷有多少截身體;
蛇身體坐標的保存:
我們需要一個結構體陣列,結構體陣列的每個元素有兩個成員x和y值,這兩個值就代表我們的身體在二維陣列中的坐標,
即一個陣列成員就代表一截身體;
蛇身體坐標的獲得:
通過計數器來判斷是否有身體,當計數器不為0時,蛇就有了身體,第一截身體的坐標來源就是蛇頭吃到食物前的坐標;
同理,后面吃到的食物增加,計數器的數值變大,就代表我們的結構體陣列有多少個有效元素,然后給結構體陣列里面的成員進行賦值;
最后一截身體的陣列下標=計數器-1,后面的身體坐標就是前面的身體移動前的坐標,由于我們的頭是不斷移動的,并且可以直接獲得其坐標,所以從最后一截身體開始往前進行拷貝賦值;
由于我們的賦值特點,陣列(蛇身)從后往前進行覆寫式拷貝賦值,即完成了蛇身體的移動
沒有吃到食物時的細節:
沒有吃到食物時,蛇的身體長度是不變的,我們的身體坐標進行改變之后,在二維陣列中留下了一個隱患;


2.5判斷是否撞墻和列印得分
列印得分:得分即身體的長度即計數器的數值
判斷是否撞墻:判斷蛇頭的下一個位置在二維陣列中是不是1即是不是墻壁即可

3.完整代碼
#ifndef _SNAKE_H_
#define _SNAKE_H_
#include <stdio.h>
#include <windows.h>
#include <time.h>
#include <stdlib.h>
#include <conio.h>
#define MAX 500 //蛇身個數
#define ROW 20
#define LINE 20
typedef struct Body
{
int x;
int y;
}body;
void MapPrint(char arr[][LINE], int count);//地圖列印
void Move(int *row, int *line, char *move);//蛇頭移動函式,通過讀取輸入的鍵盤方向鍵來改變蛇頭方向
void GetCoordinate(int *row, int *line, char *move);//蛇頭自動移動,通過獲取的方向資訊,決定蛇頭往哪個方向自動移
void food(char arr[][LINE], int *x, int *y);//隨機生成一個食物
void JudgeFood(int food_x, int food_y, int row, int line, int *count);//判斷是否吃到食物
void GetBody(char arr[][LINE], body body[], int count, int temp_x, int temp_y);//蛇體坐標更新
int Judge(char arr[][LINE], int row, int line);//判斷是否撞墻
void Game();
#endif
#include "snake.h"
void gotoxy(int x, int y)//將游標移動到(x,y)位置
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos);
}
void MapPrint(char arr[][LINE],int count)
{
gotoxy(0, 0);
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < LINE; j++)
{
//第一行,最后一行,第一列,最后一列都是墻壁
if (arr[i][j]==1)
printf("■");
else if (arr[i][j] == 2)
printf("⊙");//蛇頭
else if (arr[i][j] == 3)
printf("¤");//列印食物¤
else if (arr[i][j] == 4)
printf("●");//列印身體●
else
printf(" ");//一個墻體占兩個空格
}
printf("\n");
}
printf(" \n");
printf(" 當前得分:%d\n", count);
printf(" \n");
}
void Move(int *row, int *line,char *move)//蛇頭移動函式,通過讀取輸入的鍵盤方向鍵來改變蛇頭方向
{
if (GetAsyncKeyState(VK_UP))//上
{
*move = 'w';
}
else if (GetAsyncKeyState(VK_DOWN))//下
{
*move = 's';
}
else if (GetAsyncKeyState(VK_LEFT))//左
{
*move = 'a';
}
else if (GetAsyncKeyState(VK_RIGHT))//右
{
*move = 'd';
}
GetCoordinate(row, line, move);//將獲得的方向鍵資訊傳輸過去
}
void GetCoordinate(int *row, int *line, char *move)//蛇頭自動移動,通過獲取的方向資訊,決定蛇頭往哪個方向自動移
{
if (*move == 'w')
(*row)--;
else if (*move == 's')
(*row)++;
else if (*move == 'a')
(*line)--;
else if (*move == 'd')
(*line)++;
}
void food(char arr[][LINE],int *x,int *y)//隨機生成一個食物
{
int flag = 0;
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < ROW; j++)
{
if (arr[i][j] == 3)//食物為3
flag = 1;
}
}
if (!flag)//沒有食物就生成食物
{
//食物不能在邊框上
*x = rand() % (ROW-2)+1;
*y = rand() % (LINE-2)+1;
}
}
void JudgeFood(int food_x,int food_y,int row,int line,int *count)//判斷是否吃到食物
{
if (food_x == row&&food_y == line)//吃到食物
{
(*count)++;//吃到食物身體個數+1
}
}
void GetBody(char arr[][LINE], body body[], int count, int temp_x, int temp_y)//蛇體坐標更新
{
//保留前一個蛇體的坐標
int befor_x = 0;
int befor_y = 0;
if (count > 0)//最少有一個蛇身
{
//記錄下最后一個蛇身的位置
befor_x = body[count - 1].x;
befor_y = body[count - 1].y;
}
int keep = count;//保存一份蛇體個數
while (count)//蛇體坐標覆寫,后面的覆寫前面的
{
if (count == 1)//只有一個蛇體時,為原來蛇頭位置
{
body[count - 1].x = temp_x;
body[count - 1].y = temp_y;
}
else
{
body[count - 1].x = body[count - 2].x;
body[count - 1].y = body[count - 2].y;
}
count--;
}
while (keep)//將對應的蛇體坐標賦值
{
arr[body[keep-1].x][body[keep-1].y] = 4;
keep--;
}
if (befor_x!=0)//最后一個蛇身的上一次所在位置清空
{
arr[befor_x][befor_y] = 0;
}
}
int Judge(char arr[][LINE],int row,int line)//判斷是否撞墻
{
if (arr[row][line] == 1)
{
printf(" --------------\n");
printf(" | 撞到墻壁 |\n");
printf(" | 游戲結束 |\n");
printf(" --------------\n");
system("pause");
return 0;
}
return 1;
}
void Game()
{
char arr[ROW][LINE]=
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ,1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
};//地圖
int row = 10, line = 10;//蛇頭起始位置
arr[row][10] = 2;
char move = 'w';//蛇頭開始往上移動
int food_x = 0, food_y = 0;//食物的x,y坐標
srand((unsigned)time(NULL));//亂數種子
//保留一份蛇頭移動前坐標
int temp_x = row;
int temp_y = line;
int count = 0;//蛇身體個數
body body[MAX] = { 0 };//蛇身坐標記錄結構體陣列
while (1)
{
//生成食物
food(arr, &food_x, &food_y);
arr[food_x][food_y] = 3;
MapPrint(arr,count);//列印圖形
if (count==0)
arr[row][line] = 0;//沒有身體的時候,蛇頭原來位置變為空白
//保留蛇頭移動前的位置
temp_x = row;
temp_y = line;
Move(&row, &line,&move);//蛇頭移動
if (Judge(arr, line, row) == 0)//判斷是否撞墻
{
break;
}
JudgeFood(food_x,food_y,row, line, &count);//判斷是否吃到食物
GetBody(arr, body, count, temp_x, temp_y);//蛇身構造
arr[row][line] = 2;//新位置變成蛇頭
Sleep(200);//通過控制休眠時間來控制蛇頭移動速度
}
}
#include "snake.h"
int main()
{
Game();
printf("游戲結束\n");
system("pause");
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/267445.html
標籤:其他
