# Final Project FINAL (06/05)
由於上次修這門課的時候,好像只用了rlutil.h裡的變換顏色,所以我決定不繼續做期末報告
於是我應用了這個標頭檔的一些函式,雖然他有很多東西是不能用的,但我還是順利地寫出了一個想要的東西--貪吃蛇遊戲,中間也不乏參考許多東西,下列是這些來源
## chatgpt:
https://chat.openai.com/share/430a1606-f874-4a5f-93e0-91647ff6e14
https://chat.openai.com/share/46eabdb6-6ea5-45b1-b29e-107285fd08e4e
https://chat.openai.com/share/9413dff1-ff8c-473d-8f5b-a7185bc2345b
(本來還想寫飛機遊戲,但感覺比較簡單)
https://chat.openai.com/share/d1320a5c-7de5-4367-bfd2-f83f40303e23
## 參考網站:
https://cloud.tencent.com/developer/article/2084567
https://www.796t.com/article.php?id=254410
(上面兩個是主要的,尤其第一個)
https://flyingdc.pixnet.net/blog/post/24333750
https://www.runoob.com/cprogramming/c-function-system.html
https://jasonblog.github.io/note/linux_system/linuxxi_tong_bian_cheng_zhi_jin_cheng_ff08_qi_ff09.html
https://tw511.com/a/01/13348.html
https://blog.gtwang.org/programming/c-cpp-rand-random-number-generation-tutorial-examples/
## 遇見的難題
非常多的DEBUG,印象最深的是由於我使用rlutil的gotoxy,導致我的光標非常不一樣(跟windows.h相比),所以其實大部分的BUG都是因為光標錯誤造成的,順帶一提,光標在這個程式裡非常重要。食物的產生,蛇頭的運算都是依靠光標達成的,所以我也開了許多測試的檔案來測試這個標頭檔內的光標是如何計算,最大的不一樣應該就是xy軸反轉以及x, y都是從1開始計算。除此之外就是漫長的debug了,像是食物隨機產生的算法;蛇頭生成位置如果和食物重疊,會造成食物消失的狀況等,都被一一解決。
## 主程式
```c=
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "rlutil.h"
//地圖大小
#define WIDTH 50
#define HEIGHT 30
//移動方向
#define UP 'w'
#define DOWN 's'
#define LEFT 'a'
#define RIGHT 'd'
int n,sp, i, j, eat = 0;
char ch = LEFT, dir = LEFT;
// 蛇
struct Snake//蛇
{
int x[100];
int y[100];
int len;
int speed;
} snake;
// 食物
struct Food
{
int x;
int y;
} food;
void initialize();
void map();
void newsnake();
void newfood();
int alive();
int main()
{
int sl;
do {
system ("cls");
setColor (LIGHTBLUE);
printf ("ARE YOU READY?");
setColor (YELLOW);
printf (" 1");
setColor (LIGHTBLUE);
printf (" to START,");
setColor (RED);
printf (" OTHER");
setColor (LIGHTBLUE);
printf (" to get ready\n");
n = getch();
system ("cls");
switch(n)
{
case '1':
{
setColor (YELLOW);
printf ("START!!\n");
sp = 300;
break;
}
default:
{
setColor (RED);
printf ("DON'T CARE, START DIFFICULT MODE!!\n");
sp = 50;
break;
}
}
sleep(1);
system ("cls");
initialize ();
map ();
//開始
while(1) {
newfood (); //食物
get_speed (); //速度
newsnake (); //移動
Sleep (snake.speed);
//存活
if(!(alive()))
{
break;
}
}
system ("cls");
printf("Game Over!\n");
printf("1:Restart\t2:exit\n");
sl = getch();
}
while(sl == '1');
return 0;
}
// 初始化
void initialize() {
srand (time(NULL));
// 初始化食物的位置
do {
food.x = rand() % (WIDTH - 2) + 2;
food.y = rand() % (HEIGHT - 2) + 2;
gotoxy (food.x, food.y);
printf ("@");
} while ((food.x == 23 && food.y == 15) || (food.x == 24 && food.y == 15) || (food.x == 25 && food.y == 15));
// 初始化蛇的位置和方向
snake.x[0] = 23;
snake.y[0] = 15;
gotoxy (snake.x[0], snake.y[0]);
printf ("&");
snake.len = 3;
snake.speed = 200;
for (i = 1; i < snake.len; i++) {
snake.x[i] = snake.x[i - 1] + 1;
snake.y[i] = snake.y[i - 1];
gotoxy (snake.x[i], snake.y[i]);
printf ("&");
}
// gotoxy (26, 15);
// printf (" ");
}
//地圖邊框
void map()
{
for(i = 1; i <= HEIGHT - 1; i++) {
gotoxy (1, i);
printf ("#");
gotoxy (WIDTH - 1, i);
printf ("#");
}
for(j = 1; j <= WIDTH - 1; j++) {
gotoxy(j, 1);
printf("#");
gotoxy(j, HEIGHT - 1);
printf("#");
}
}
//更新食物
void newfood()
{
if(snake.x[0] == food.x && snake.y[0] == food.y) {
srand(time(NULL));
int flag=1;
do {
food.x = rand() % (WIDTH - 2) + 2;
food.y = rand() % (HEIGHT - 2) + 2;
for(i=0; i<snake.len; i++) {
if(food.x==snake.x[i]&&food.y==snake.y[i]) {
flag=0;
break;
}
}
}
while(flag==0);
gotoxy (food.x, food.y);
printf ("@");
snake.len++;
eat = 1;
}
}
//更新蛇
void newsnake()
{
while (kbhit()) {
ch = getch();
}
//沒吃到不加長度
if (!eat) {
gotoxy (snake.x[snake.len - 1], snake.y[snake.len - 1]);
printf (" ");
}
//改變位置
for(i = snake.len-1; i > 0; i--) {
snake.x[i] = snake.x[i-1];
snake.y[i] = snake.y[i-1];
}
//方向
switch(ch) {
case UP:
{
if(dir == DOWN) {
snake.y[0]++;
break;
} else {
snake.y[0]--;
dir = UP;
break;
}
}
case DOWN:
{
if(dir == UP) {
snake.y[0]--;
break;
} else {
snake.y[0]++;
dir = DOWN;
break;
}
}
case LEFT:
{
if(dir == RIGHT) {
snake.x[0]++;
break;
} else {
snake.x[0]--;
dir = LEFT;
break;
}
}
case RIGHT:
{
if(dir==LEFT) {
snake.x[0]--;
break;
} else {
snake.x[0]++;
dir=RIGHT;
break;
}
}
default:
{
if(dir == DOWN) {
snake.y[0]++;
break;
} else if(dir == UP) {
snake.y[0]--;
break;
} else if(dir == LEFT) {
snake.x[0]--;
break;
} else if(dir == RIGHT) {
snake.x[0]++;
break;
}
}
}
//葛屁沒
int alive()
{
//撞牆
if (snake.x[0] == 1 || snake.x[0] == WIDTH - 1 || snake.y[0] == 1 || snake.y[0] == HEIGHT - 1) return 0;
//咬到自己
for (i = 1; i < snake.len; i++) {
if (snake.x[0] == snake.x[i] && snake.y[0] == snake.y[i]) return 0;
}
return 1;
}
//蛇越長越快
void get_speed()
{
if(snake.len<=6)
snake.speed=sp;
else if(snake.len<=10)
snake.speed=sp-20;
else if(snake.len<=20)
snake.speed=sp-50;
else if(snake.len<=30)
snake.speed=sp-60;
else
snake.speed=sp-70;
}
```
## 心得
這個遊戲還可以做一些介面的優化,但我覺得主要是在應用rlutil這個標頭檔,就沒有繼續寫下去了,報告做完以後我還在研究一個功能,就是能夠用WASD和方向鍵控制方向(目前只有WASD或方向鍵擇一),希望這次的報告對我之後的專題研究會有更多幫助