[問題] 貪食蛇遇到阻斷式getch問題
開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
Mac OS (g++)
額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
ncurses.h
問題(Question):
目前寫的貪食蛇練習題,可以分別讓蛇自動前進及按上下左右鍵盤前進
但嘗試想把兩個功能合併,卻疑似發生阻斷,已經爬文過但還不知道怎麼解
在下面的程式碼有highlight,求解
餵入的資料(Input):
預期的正確結果(Expected Output):
錯誤結果(Wrong Output):
程式碼(Code):(請善用置底文網頁, 記得排版)
#include <iostream>
#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
using namespace std;
//int move(int y , int x);
#define Initial_Length 5
#define width 50
#define hieght 20
typedef struct snack{
int x;
int y;
}Snack;
Snack Sbody[1000];
Snack Newbody;
Snack Food;
void Show_Bulletinboard()
{
mvaddstr(2,55,"Press Enter or Space to start.");
mvaddstr(6,55,"Press P or p to pause.");
mvaddstr(10,55,"Press to arrow key to move.");
//加一個狀態欄位
//mvaddch(10,55,'\x18\x19\x1a\x1b');
mvaddstr(14,55,"Grade:");
mvaddstr(18,55,"Speed:");
}
void Initial_Snack_Position()
{
for (int i = 0; i < Initial_Length ; i++)
{
Sbody[i].y = 2;
Sbody[i].x = Initial_Length + 1 - (i);
}
}
void Print_Snack(int *Length)
{
for (int i = 0; i < *Length ; i++)
{
if (i == 0)
{
//改變頭的顏色
mvaddstr(Sbody[i].y, Sbody[i].x , "@");
//printf("\033[33m@");
}
else
{
mvaddstr(Sbody[i].y, Sbody[i].x , "@");
}
}
}
void Print_Dot(int Pos_y, int Pos_x, char ch )
{
mvaddch(Pos_y, Pos_x , ch);
//printf("\033[33m@");
}
void Initial_GameZone()
{
for (int j = 1 ; j <= hieght ; j++)
{
for (int i = 1; i <= width ; i++)
{
if (j == 1 || j == hieght)
{
Print_Dot(j,i,'#');
}
else if(i == 1 || i == width)
{
Print_Dot(j,i,'#');
}
}
}
}
void Change_Snack_Position(int * Length)
{
for(int i = *Length -1 ; i >= 0 ; i--)
{
if (i == 0) //移動頭
{
Sbody[i].x = Newbody.x;
Sbody[i].y = Newbody.y;
Print_Dot(Sbody[i].y , Sbody[i].x , '@');
}
else if (i == *Length -1) //清除尾巴
{
Print_Dot(Sbody[i].y, Sbody[i].x, ' ');
Sbody[i].x = Sbody[i-1].x;
Sbody[i].y = Sbody[i-1].y;
}
else{ //移動身體
Sbody[i].x = Sbody[i-1].x;
Sbody[i].y = Sbody[i-1].y;
Print_Dot(Sbody[i].y , Sbody[i].x, '@');
}
}
}
void Create_Food(int * Length) //產生食物的位置
{
int count = 0;
srand(time(NULL));
do
{
Food.x = (rand() % (width-2) ) +2;
Food.y = (rand() % (hieght-2)) +2;
for (int i = 0; i < *Length ; i++)
{
if (Sbody[i].x != Food.x && Sbody[i].y != Food.y)
{
count = count + 1;
}
}
}while ( count == *Length);
Print_Dot(Food.y , Food.x , '*');
}
void isEaten(int *Length) //判斷是否吃到食物
{
if (Sbody[0].x == Food.x && Sbody[0].y == Food.y)
{
*Length = *Length + 1; //當吃到新的果實,長出一節,位置在食物的位置
Sbody[*Length].x = Food.x;
Sbody[*Length].y = Food.y;
Print_Dot(Sbody[*Length].y,Sbody[*Length].x , '@');
Create_Food( Length );
}
}
bool isGameOver(int * Length)
{
bool flag = true;
for (int i = 1 ; i < *Length ; i++) //頭碰到身體
{
if (Sbody[0].x == Sbody[i].x && Sbody[0].y == Sbody[i].y)
{
flag = false;
}
}
for (int n = 1 ; n <= hieght ; n++) //頭碰到牆
{
for (int m = 1; m <= width ; m++)
{
if (n == 1 || n == hieght)
{
if (Sbody[0].x == m && Sbody[0].y == n)
{
flag = false;
}
}
else if(m == 1 || m == width)
{
if (Sbody[0].x == m && Sbody[0].y == n)
{
flag = false;
}
}
}
}
return flag;
}
int kbhit(void)
{
struct termios oldt, newt;
int ch;
int oldf;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF)
{
ungetc(ch, stdin);
return 1;
}
return 0;
}
int main(void) {
WINDOW * w; //產生視窗
w=initscr();
keypad(stdscr,TRUE); //啟動鍵盤特殊按鍵功能
int GameKey =1;
noecho();
int Length = Initial_Length;
Initial_GameZone(); //產生遊戲邊 筐
Show_Bulletinboard();
Initial_Snack_Position();
Print_Snack(&Length);
Create_Food(&Length);
while (GameKey != 27)
{
if ( kbhit() )
{
GameKey = getch(); //根據鍵盤上下左右間決定移動方向
switch(GameKey)
{
case KEY_UP:
Newbody.y = Sbody[0].y -1;
Newbody.x = Sbody[0].x;
setbuf(stdin,NULL);
break;
case KEY_DOWN:
Newbody.y = Sbody[0].y +1;
Newbody.x = Sbody[0].x;
setbuf(stdin,NULL);
break;
case KEY_LEFT:
Newbody.y = Sbody[0].y;
Newbody.x = Sbody[0].x -1;
setbuf(stdin,NULL);
break;
case KEY_RIGHT:
Newbody.y = Sbody[0].y;
Newbody.x = Sbody[0].x +1;
setbuf(stdin,NULL);
break;
default:;
}
}
else //依據原本的方向前進
{
if((Sbody[0].x - Sbody[1].x) == -1) //自動想左移動
{
Newbody.y = Sbody[0].y;
Newbody.x = Sbody[0].x -1;
}
else if ((Sbody[0].x - Sbody[1].x) == 1) //自動向右移動
{
Newbody.y = Sbody[0].y;
Newbody.x = Sbody[0].x +1;
}
else if ((Sbody[0].y-Sbody[0].y)== -1) //自動向上移動
{
Newbody.y = Sbody[0].y -1;
Newbody.x = Sbody[0].x;
}
else if ((Sbody[0].y - Sbody[1].y) == 1) //自動向下移動
{
Newbody.y = Sbody[0].y +1;
Newbody.x = Sbody[0].x;
}
else
{
}
sleep(1);
refresh();
}
Change_Snack_Position(&Length);
isEaten (&Length);
//GameKey = 1;
if ( isGameOver(&Length) == false) //判斷是否GameOver 吃到自己或是撞牆
{
break;
}
}
//getchar();
delwin(w);
return 0;
}
http://codepad.org/XP42S3rE
補充說明(Supplement):
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.115.156.66
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1439473205.A.511.html
→
08/13 21:43, , 1F
08/13 21:43, 1F
→
08/13 21:57, , 2F
08/13 21:57, 2F
→
08/13 21:58, , 3F
08/13 21:58, 3F
→
08/13 22:05, , 4F
08/13 22:05, 4F
→
08/13 22:06, , 5F
08/13 22:06, 5F
→
08/13 22:08, , 6F
08/13 22:08, 6F
→
08/13 22:09, , 7F
08/13 22:09, 7F
→
08/13 22:09, , 8F
08/13 22:09, 8F
→
08/13 22:10, , 9F
08/13 22:10, 9F
→
08/13 22:10, , 10F
08/13 22:10, 10F
→
08/13 22:10, , 11F
08/13 22:10, 11F
→
08/13 22:11, , 12F
08/13 22:11, 12F
→
08/13 22:11, , 13F
08/13 22:11, 13F
→
08/13 22:12, , 14F
08/13 22:12, 14F
→
08/13 22:12, , 15F
08/13 22:12, 15F
→
08/13 22:12, , 16F
08/13 22:12, 16F
→
08/13 22:13, , 17F
08/13 22:13, 17F
→
08/13 22:13, , 18F
08/13 22:13, 18F
→
08/13 22:15, , 19F
08/13 22:15, 19F
→
08/13 22:15, , 20F
08/13 22:15, 20F
→
08/13 22:15, , 21F
08/13 22:15, 21F
→
08/13 22:16, , 22F
08/13 22:16, 22F
→
08/13 22:16, , 23F
08/13 22:16, 23F
→
08/13 22:17, , 24F
08/13 22:17, 24F
→
08/13 22:42, , 25F
08/13 22:42, 25F
→
08/13 22:42, , 26F
08/13 22:42, 26F
→
08/13 22:43, , 27F
08/13 22:43, 27F
→
08/13 23:10, , 28F
08/13 23:10, 28F
→
08/13 23:16, , 29F
08/13 23:16, 29F
推
08/13 23:22, , 30F
08/13 23:22, 30F
→
08/13 23:22, , 31F
08/13 23:22, 31F
→
08/13 23:25, , 32F
08/13 23:25, 32F
→
08/13 23:26, , 33F
08/13 23:26, 33F
→
08/13 23:27, , 34F
08/13 23:27, 34F
→
08/13 23:35, , 35F
08/13 23:35, 35F
→
08/13 23:41, , 36F
08/13 23:41, 36F
推
08/13 23:43, , 37F
08/13 23:43, 37F
→
08/13 23:44, , 38F
08/13 23:44, 38F
→
08/14 08:34, , 39F
08/14 08:34, 39F
→
08/14 08:37, , 40F
08/14 08:37, 40F
→
08/14 08:42, , 41F
08/14 08:42, 41F
→
08/14 13:30, , 42F
08/14 13:30, 42F
→
08/14 13:31, , 43F
08/14 13:31, 43F
→
08/14 15:14, , 44F
08/14 15:14, 44F
→
08/14 20:08, , 45F
08/14 20:08, 45F
→
08/14 20:08, , 46F
08/14 20:08, 46F
→
08/14 20:09, , 47F
08/14 20:09, 47F
→
08/14 20:09, , 48F
08/14 20:09, 48F
討論串 (同標題文章)
以下文章回應了本文:
完整討論串 (本文為第 1 之 2 篇):