/* Copyright 2014 Grady Moran Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include //http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz //#include #define SIDELEN 7 //SIDELEN * SIDELEN sized board #define DELAY 3 //tenths of seconds, higher is easier typedef struct _coord{ int x, y; } coord; void placeFood(int board[SIDELEN][SIDELEN]); void makeChanges(char dir, int * snakelen, coord * head, int board[SIDELEN][SIDELEN]); //maybe make this return a boolean/char to indicate when the game is over void displayBoard(int board[SIDELEN][SIDELEN]); char getInput(char dir); //if no valid input (wasd) is pressed after DELAY tenths of seconds, dir is returned. int main() { int board[SIDELEN][SIDELEN]; //board is a 2D array of ints with 0 for nothing, a positive int for part of the snake, and -1 for a food thing int i, j; for (i = 0; i < SIDELEN; i++){ for (j = 0; j < SIDELEN; j++){ board[i][j] = 0; } } int snakelen; snakelen = 1; char dir = 'w'; coord head; head.x = SIDELEN/2; head.y = SIDELEN/2; board[head.y][head.x] = snakelen; //ncurses intialization stuff initscr(); noecho(); placeFood(board); displayBoard(board); while(1){//while the game is running dir = getInput(dir); makeChanges(dir, &snakelen, &head, board); displayBoard(board); } endwin(); } void placeFood(int board[SIDELEN][SIDELEN]) { srandom(time(NULL)); coord my_try; my_try.x = random() % SIDELEN; my_try.y = random() % SIDELEN; while (board[my_try.y][my_try.x] != 0){ //placing the food on the snake my_try.x = random() % SIDELEN; my_try.y = random() % SIDELEN; } board[my_try.y][my_try.x] = -1; } void makeChanges(char dir, int * snakelen, coord * head, int board[SIDELEN][SIDELEN]) { int i, j, emptyspots = 0; //win for (i = 0; i < SIDELEN; i++){ for (j = 0; j < SIDELEN; j++){ if (board[j][i] == 0) emptyspots++; } } if (emptyspots == 0){ clear(); printw("You win! Get a life!"); refresh(); flushinp(); getch(); endwin(); exit(0); } switch (dir){ //change variables to represent moves case 'a': if (head->y != 0) head->y--; else head->y = SIDELEN -1;//the elses are when it is at the edge and needs to wrap around the other side of the screen break; case 'd': if (head->y < SIDELEN-1) head->y++; else head->y = 0; break; case 's': if (head->x < SIDELEN-1) head->x++; else head->x = 0; break; case 'w': if (head->x != 0) head->x--; else head->x = SIDELEN -1; break; } if (board[head->y][head->x] == 0 || board[head->y][head->x] == 1){ //move normally board[head->y][head->x] = *snakelen + 1; } else if (board[head->y][head->x] < 0){ //gets the food *snakelen+=1; board[head->y][head->x] = *snakelen; int i, j; for (i = 0; i < SIDELEN; i++){ for (j = 0; j < SIDELEN; j++){ if (board[i][j] >= 1) board [i][j]++; } } placeFood(board); } else { //lose clear(); printw("You lose! Ha ha!"); refresh(); getch(); endwin(); exit(0); } //making the changes for (i = 0; i < SIDELEN; i++){ for (j = 0; j < SIDELEN; j++){ if (board[i][j] >= 1) board [i][j]--; } } } void displayBoard(int board[SIDELEN][SIDELEN]) { clear(); char snake[] = "[#] "; char food[] = "[X] "; char nothing[] = "[ ] "; int i,j; char thisline[SIDELEN * 4]; for (i = 0; i < SIDELEN; i++){ strcpy(thisline, ""); for (j = 0; j < SIDELEN; j++){ if (board[j][i] > 0){ strcat(thisline, snake); } if (board[j][i] < 0){ strcat(thisline, food); } if (board[j][i] == 0){ strcat(thisline, nothing); } } printw("%s\n", thisline); } refresh(); } char getInput(char dir) { flushinp(); halfdelay(DELAY); struct timeval t1, t2; gettimeofday(&t1, NULL); char x = getch(); gettimeofday(&t2, NULL); cbreak(); flushinp(); unsigned long long elapsed = 1000 * (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) / 1000; long leftOverDelay = (long) (DELAY * 100 - elapsed)*1000000; //convert seconds to nanoseconds and make sure seconds is actually in long form struct timespec t; t.tv_sec = 0; t.tv_nsec = leftOverDelay; nanosleep(&t, NULL); if (x == 'w' || x == 'a' || x == 's' || x == 'd') return x; return dir; }