C語言實現,編譯環境VS2017 附:easyx圖形化(文章末尾)
效果圖如下
(有一些函數kbhit,getch,在這表示爲_kbhit與_getch)//不同編譯器原因 注意在Dev等集成開發軟件下可能會CE
o(* ̄▽ ̄*)o
一、引言
作爲一個小白,相信大家的心情都是一樣的,渴望寫一個人生的第一個“貪喫蛇”。
在網上看了基本思路後,如果有一定的知識(鏈表的相關操作),寫出這個應該是不難的。
1、背景
打印遊戲背景框,以及一些初設的東西,如蛇的初始長度,可以的話可以自己加上出場界面
2、食物產生
通過srand,與rand 函數實現隨機產生
3、鍵盤信號獲取
由 _kbhit(),_getch() ,函數獲取
4、蛇的移動
分爲普通移動與喫到食物的移動
ps.(許多網上通過刷屏實現,其實可以靠覆蓋實現,將原來蛇覆蓋用空格,然後重新打印蛇)
二、一些必要函數
打印這個並不是圖形庫實現,所以要通過光標跳轉實現打印
注:此方法我也不清楚是從網上查閱資料所得,目前還是小白(ง •_•)ง
void gotoxy(int x, int y)
{
// 更新光標位置
COORD pos;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hOutput, pos);
// 隱藏光標
CONSOLE_CURSOR_INFO cursor;
cursor.bVisible = FALSE;
cursor.dwSize = sizeof(cursor);
SetConsoleCursorInfo(hOutput, &cursor);
}
應該是獲取窗口句柄
詳細可以參考
https://baike.baidu.com/item/SetConsoleCursorPosition/575826
https://baike.baidu.com/item/GetStdHandle/6909878?fr=aladdin
https://baike.baidu.com/item/coord/4594820?fr=aladdin
三、不多說,看代碼
以前寫的太爛了 現在重新更新了
/*
@Author: Joke-Lin
@Time: 2020-03-19
@Encoding: GB 2312
@IDE: VS2019
*/
#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<time.h>
#include<conio.h>
#define up 'w'
#define down 's'
#define left 'a'
#define right 'd'
void welcome(); // 開始界面
void Finish(); // 結束界面
void creatgraph(); // 圍牆打印
void gotoxy(int x, int y); // 光標跳轉,橫爲X 0,1,2..
void gotoprint(int x, int y); // 跳轉打印
void gotodelete(int x, int y);// 跳轉刪除
void creatfood(); // 食物產生
int ClickControl(); // 獲取鍵盤信號
int Judge(); // 遊戲結束判斷
void MovingBody(); // 蛇的移動
void Eating(); // 蛇喫到東西后的操作(伸長)
void ChangeBody(int x, int y); // 蛇的座標變換
/*全局變量 + 預處理:*/
typedef struct Snakes
{
int x;
int y;
struct Snakes* next;
}snake;
snake* head; // 聲明蛇頭指針
// 申明並定義食物
struct Food
{
int x;
int y;
}food;
char name[20]; // 保存用戶名 有興趣可以製作登錄系統
int score = 0; // 分數
char click = 1; // 記錄敲下的鍵盤按鍵
int speed; // 速度 其實是延遲的毫秒數
/************************************************************/
int main()
{
system("color 0B"); // 設置控制檯字體顏色
welcome(); // 歡迎界面
creatgraph(); // 創建地圖
creatfood(); // 新建食物
// 捕獲鼠標按鍵 ClickControl
if (ClickControl() == 0) return 0;
return 0;
}
/**********************************************************/
void welcome()
{
gotoxy(15, 10);
printf("/**********************************************/");
gotoxy(15, 20);
printf("/**********************************************/");
gotoxy(20, 13);
printf("WELCOME TO THE GAME OF RETRO SNAKE");
gotoxy(14, 16);
printf("請在英文輸入法中操作,反向移動等同於喫到自己,wasd控制p暫停");
gotoxy(20, 18);
printf("PLEASE ENTER YOUR NAME:");
scanf_s("%s", &name, 20);
system("cls");
}
/**********************************************************/
void creatgraph() {
int i;
/*
注意這裏橫座標是每次+2 因爲控制檯字符寬高比爲1:2
*/
for (i = 0; i < 58; i += 2)
{
gotoprint(i, 0);
gotoprint(i, 26);
}
for (i = 1; i < 26; i++)
{
gotoprint(0, i);
gotoprint(56, i);
}
gotoxy(63, 10);
printf("hello %s,Welcome To Play", name);
gotoxy(63, 15);
printf("Your Score Is:%d = ̄ω ̄= ", score);
gotoxy(63, 20);
printf("This Game Is Created By JOKER");
head = (snake*)malloc(sizeof(snake));
snake* p = (snake*)malloc(sizeof(snake));
snake* q = (snake*)malloc(sizeof(snake));
head->x = 16;
head->y = 15;
p->x = 16;
p->y = 16;
q->x = 16;
q->y = 17;
head->next = p;
p->next = q;
q->next = NULL;
}
/**********************************************************/
void gotoxy(int x, int y)
{
// 更新光標位置
COORD pos;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hOutput, pos);
// 隱藏光標
CONSOLE_CURSOR_INFO cursor;
cursor.bVisible = FALSE;
cursor.dwSize = sizeof(cursor);
SetConsoleCursorInfo(hOutput, &cursor);
}
/**********************************************************/
void gotoprint(int x, int y)
{
gotoxy(x, y);
printf("■");
}
/**********************************************************/
void gotodelete(int x, int y)
{
gotoxy(x, y);
printf(" ");
}
/**********************************************************/
void creatfood()
{
// 隨機產生一個食物
bool flag = false;
while (!flag)
{
flag = true;
srand((int)time(NULL));
food.y = rand() % (25 - 1 + 1) + 1;
food.x = rand() % (54 - 2 + 1) + 2;
if (food.x % 2 != 0)
{
food.x = food.x + 1;
}
snake* judge = head;
while (1) //遍歷排除蛇身重複
{
if (judge->next == NULL) break;
if (food.x == judge->x && food.y == judge->y)
{
flag = false;
}
judge = judge->next;
}
}
gotoxy(food.x, food.y);
printf("⊙");
}
/**********************************************************/
// 捕獲鼠標 遊戲主循環
int ClickControl()
{
char c;
while (1)
{
if (Judge() == 0) return 0;
if (_kbhit())
{
click = _getch();
}
MovingBody();
Eating();
}
return 1;
}
/**********************************************************/
void MovingBody() {
int x = head->x, y = head->y;
snake* p = head;
// 通過先清空後打印實現動畫效果
while (p->next != NULL) {
p = p->next;
}
gotodelete(p->x, p->y); // 消除尾節點
switch (click)
{
case up:
y -= 1;
break;
case down:
y += 1;
break;
case left:
x -= 2;
break;
case right:
x += 2;
break;
default:
break;
}
if (x != head->x || y != head->y) {
// 改變座標時更新 暫停遊戲停止更新蛇
ChangeBody(x, y);
}
p = head;
// 打印蛇頭
gotoprint(p->x, p->y);
// 蛇速度控制
int count = score / 10;
if (count <= 10) speed = 150;
else if (count > 10 && count <= 20) speed = 100;
else if (count > 20 && count <= 40) speed = 50;
else speed = 10;
Sleep(speed);
}
/**********************************************************/
// 喫到食物處理 添加一個尾巴
void Eating()
{
if (head->x == food.x && head->y == food.y)
{
creatfood();
snake* _new = (snake*)malloc(sizeof(snake));
snake* p;
p = head;
while (1)
{
if (p->next == NULL) break;
p = p->next;
}
p->next = _new;
_new->next = NULL;
score += 10;
gotoxy(77, 15);
printf("%d", score);
}
}
/**********************************************************/
// 更新蛇體座標 只需要消除尾結點 然後把新座標結點置爲頭結點即可
void ChangeBody(int x, int y)
{
snake* p = head;
while (p->next->next != NULL) {
p = p->next;
}
free(p->next);
p->next = NULL;
snake* new_head = (snake*)malloc(sizeof(snake));
new_head->x = x;
new_head->y = y;
new_head->next = head;
head = new_head;
}
/**********************************************************/
// 判斷是否遊戲結束
int Judge()
{
if (head->x == 0 || head->x == 56 || head->y == 0 || head->y == 26)
{
Finish();
return 0;
}
snake* p = head->next;
while (1)
{
if (p == NULL) break;
if (head->x == p->x && head->y == p->y)
{
Finish();
return 0;
}
p = p->next;
}
return 1;
}
/**********************************************************/
void Finish()
{
system("cls");
gotoxy(15, 10);
printf("/**********************************************/");
gotoxy(15, 20);
printf("/**********************************************/");
gotoxy(18, 14);
printf("GAME OVER o(* ̄▽ ̄*)o");
gotoxy(20, 16);
printf("Your Score is %d hiahiahia", score);
gotoxy(18, 18);
printf("還不錯哦, 繼續努力O(∩_∩)O");
gotoxy(0, 27);
// 釋放空間
snake* p = head, * q;
while (p != NULL) {
q = p->next;
free(p);
p = q;
}
system("pause");
}
四、
easyx 實現:鏈接地址
效果如下:
覺得好的話歡迎犒勞(ง •_•)ง (要恰飯的嘛嘿嘿)
對評論裏的重點問題,我有時間在博客裏多加一些