cursedsnakegame/main.cpp
2021-11-21 22:19:44 +07:00

642 lines
23 KiB
C++

#include <time.h>
#include <iostream>
#include <stdio.h>
#include <curses.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <string>
using namespace std;
#define termMaxX 145
#define termMaxY 36
#define paMaxX 100
#define paMaxY 30
#define upArrow 65
#define downArrow 66
#define rightArrow 67
#define leftArrow 68
#define clear() printf("\033[H\033[J")
void drawVoid(){
printf("\033[1;32m\033[40m \033[0m");
}
void drawSnake(){
printf("\033[1;32m\033[40m*\033[0m");
}
void SetCursorPosition(int XPos, int YPos) {
printf("\033[%d;%dH",YPos+1,XPos+1);
}
void moveSnake(int deltaX, int deltaY, int posX[100], int posY[100], int tempX[2], int tempY[2]){
tempX[0]=posX[0]+deltaX;
tempY[0]=posY[0]+deltaY;
bool sw=0;
for(int i=0;(posX[i]!=-1)&&(posY[i]!=-1);i++){
if((posX[i+1]==-1)&&(posY[i+1]==-1)){
SetCursorPosition(posX[i],posY[i]);
drawVoid();
}
if(sw==0){
tempX[1]=posX[i];
tempY[1]=posY[i];
posX[i]=tempX[0];
posY[i]=tempY[0];
SetCursorPosition(posX[i],posY[i]);
drawSnake();
sw=1;
}
else if(sw==1){
tempX[0]=posX[i];
tempY[0]=posY[i];
posX[i]=tempX[1];
posY[i]=tempY[1];
SetCursorPosition(posX[i],posY[i]);
drawSnake();
sw=0;
}
}
}
void drawFrame(){
for(int i=0;i<paMaxY;i++){
for(int j=0;j<paMaxX;j++){
if(i==0||i==(paMaxY-1)){
SetCursorPosition(j,i);
printf("\033[45m \033[0m");
}
else if(j==0||j==(paMaxX-1)){
SetCursorPosition(j,i);
printf("\033[45m \033[0m");
}
}
}
}
int crashWall(int posX, int posY){
if(posX==(paMaxX-1)||posX==0){
return 1;
}
if(posY==(paMaxY-1)||posY==0){
return 1;
}
return 0;
}
int eatFruit(int posX, int posY, int fruitX, int fruitY){
if(posX==fruitX&&posY==fruitY){
return 1;
}
else{
return 0;
}
}
int crashSnake(int posX[100],int posY[100]){
for(int i=1;posX[i]!=-1;i++){
if(posX[0]==posX[i]){
if(posY[0]==posY[i]){
return 1;
}
}
}
return 0;
}
int crashBomb(int posX, int posY, int bombX[100],int bombY[100], bool bombShown[100]){
for(int i=0;bombShown[i]==1;i++){
if(bombShown[i]==1){
if(posX==bombX[i]){
if(posY==bombY[i]){
return 1;
}
}
}
SetCursorPosition(0,paMaxY);
}
return 0;
}
void gameOver(int score){
cbreak();
noecho();
scrollok(stdscr, TRUE);
nodelay(stdscr, TRUE);
endwin();
for(int i=0;i<paMaxX;i++){
for(int j=0;j<paMaxY;j++){
SetCursorPosition(i,j);
printf("\033[45m \033[0m"); //\033[41m
}
}
//Draws GAME OVER
SetCursorPosition((paMaxX/2)-34,(paMaxY/2)-7);
printf("\033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m ");
SetCursorPosition((paMaxX/2)-34,(paMaxY/2)-6);
printf("\033[41m \033[45m \033[41m \033[45m \033[41m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m ");
SetCursorPosition((paMaxX/2)-34,(paMaxY/2)-5);
printf("\033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m ");
SetCursorPosition((paMaxX/2)-34,(paMaxY/2)-4);
printf("\033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m ");
SetCursorPosition((paMaxX/2)-34,(paMaxY/2)-3);
printf("\033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m ");
SetCursorPosition((paMaxX/2)-34,(paMaxY/2)-2);
printf("\033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m ");
SetCursorPosition((paMaxX/2)-34,(paMaxY/2)-1);
printf("\033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m \033[41m \033[45m ");
printf("\e[?25h");
//For score values with multiple digits
int scoreShift=0,temp=score;
while(temp>=10){
scoreShift++;
temp=temp/10;
}
SetCursorPosition(((paMaxX/2)-5)-(scoreShift/2),(paMaxY/2)+3);
printf("Score: %d", score);
SetCursorPosition(2,paMaxY-2);
printf("Input your name (without spaces!) and press ENTER to return to main menu.");
SetCursorPosition((paMaxX/2)-19,(paMaxY/2)+6);
printf("Enter you name: ");
//Save player scores at $HOME/.config/cursedSnakeGameScores
FILE *cmd=popen("echo -n $HOME", "r");
char result[100]={0x0};
fgets(result, sizeof(result), cmd);
pclose(cmd);
string fullpath=result;
fullpath+="/.config/cursedSnakeGameScores";
FILE *fptr = fopen(fullpath.c_str(),"a");
if (fptr == NULL)
{
printf("Could not open file");
return;
}
string playerName;
//Asks for player name
scanf("%s",playerName.c_str());
fprintf(fptr,"%d %s\n",score , playerName.c_str());
fclose(fptr);
}
int mainMenu() {
int currentButtonState=0,menuStarted=0;
printf("\e[?25l");//ปิดcursor
cbreak();
noecho();
scrollok(stdscr, TRUE);
nodelay(stdscr, TRUE);
char input;
while(1){
usleep(50000);
//ShowGameLogoOnFirstTime
SetCursorPosition((paMaxX/2)-44,(paMaxY/2)-12);
printf("\033[45m \033[107m#####\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m######\033[45m \033[107m#####\033[45m \033[107m#######\033[45m \033[107m######\033[45m \033[107m#####\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m########");
SetCursorPosition((paMaxX/2)-44,(paMaxY/2)-11);
printf("\033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m####\033[41m \033[107m##\033[45m \033[107m##\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m ");
SetCursorPosition((paMaxX/2)-44,(paMaxY/2)-10);
printf("\033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#######\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m ");
SetCursorPosition((paMaxX/2)-44,(paMaxY/2)-9);
printf("\033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m######\033[45m \033[107m#####\033[45m \033[107m#####\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m###\033[45m \033[107m######\033[45m ");
SetCursorPosition((paMaxX/2)-44,(paMaxY/2)-8);
printf("\033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#####\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#######\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m ");
SetCursorPosition((paMaxX/2)-44,(paMaxY/2)-7);
printf("\033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m##\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m ");
SetCursorPosition((paMaxX/2)-44,(paMaxY/2)-6);
printf("\033[45m \033[107m#####\033[45m \033[107m#####\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#####\033[45m \033[107m#######\033[45m \033[107m######\033[45m \033[107m#####\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m#\033[45m \033[107m########");
SetCursorPosition((paMaxX/2)-44,(paMaxY/2)-5);
printf("\033[45m GAME\033[0m");
//Author info
SetCursorPosition(paMaxX-8,paMaxY-3);
printf("\033[45mMade by\033[0m");
SetCursorPosition(paMaxX-39,paMaxY-2);
printf("\033[45mPongpeera Wongprasitthiporn (64010543)\033[0m");
//Instructions
SetCursorPosition(2,paMaxY-3);
printf("\033[45mUse ARROW KEYS to navigate\033[0m");
SetCursorPosition(2,paMaxY-2);
printf("\033[45mENTER to select\033[0m");
if(menuStarted<=3){
for(int i=0;i<paMaxX;i++){
for(int j=0;j<paMaxY;j++){
SetCursorPosition(i,j);
printf("\033[45m \033[0m"); //\033[41m
}
}
menuStarted++;
}
input=getch();
if(input==upArrow){
currentButtonState--;
if(currentButtonState<0){
currentButtonState=0;
}
}
if(input==downArrow){
currentButtonState++;
if(currentButtonState>2){
currentButtonState=2;
}
}
if(input=='\n'){
return currentButtonState;
}
//PlayButtonHighlighted
if(currentButtonState==0){
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)-1);
printf("\033[107m ");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+0);
printf("\033[107;31m Play \033[0m");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+1);
printf("\033[107m ");
}
//PlayButton
else{
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)-1);
printf("\033[45m ");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+0);
printf("\033[45m Play ");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+1);
printf("\033[45m ");
}
//LeaderboardsHighlighted
if(currentButtonState==1){
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+3);
printf("\033[107m ");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+4);
printf("\033[107;31m Scores \033[0m");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+5);
printf("\033[107m ");
}
//LeaderboardsButton
else{
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+3);
printf("\033[45m ");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+4);
printf("\033[45m Scores ");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+5);
printf("\033[45m ");
}
//ExitHighlighted
if(currentButtonState==2){
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+6);
printf("\033[107m ");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+7);
printf("\033[107;31m Exit \033[0m");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+8);
printf("\033[107m ");
}
//ExitButton
else{
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+6);
printf("\033[45m ");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+7);
printf("\033[45m Exit ");
SetCursorPosition((paMaxX/2)-7,(paMaxY/2)+8);
printf("\033[45m ");
}
}
}
void showScores() {
endwin();
system("sort $HOME/.config/cursedSnakeGameScores -nr > $HOME/.config/cursedSnakeGameScores.tmp && mv $HOME/.config/cursedSnakeGameScores.tmp $HOME/.config/cursedSnakeGameScores");
int line=0,currentLine=0;
char c; //UserInputCharacter
FILE *cmd=popen("echo -n $HOME", "r");
char result[100]={0x0};
fgets(result, sizeof(result), cmd);
pclose(cmd);
string fullpath=result;
fullpath+="/.config/cursedSnakeGameScores";
FILE *fptr = fopen(fullpath.c_str(),"r");
if(fptr == NULL) {
perror("Error in opening file");
return;
}
do {
c = fgetc(fptr);
if( feof(fptr) ) {
break ;
}
if(c=='\n'){
line++;
}
} while(1);
for(int i=0;i<paMaxX;i++){
for(int j=0;j<paMaxY;j++){
SetCursorPosition(i,j);
printf("\033[0m ");
}
}
drawFrame();
if(line==0){
SetCursorPosition((paMaxX/2)-8,paMaxY/2);
printf("No scores found.");
SetCursorPosition(64,paMaxY-2);
printf("Press Enter to return to main menu.");
getchar();
fclose(fptr);
return;
}
rewind(fptr);
//fclose(fptr);
string playerName[line];
string scores[line];
for(int i=0;i<line;i++){
playerName[i]="";
scores[i]="";
}
if(fptr == NULL) {
perror("Error in opening file");
return;
}
bool scoreName=0;
while(currentLine!=line){
c=fgetc(fptr);
if(scoreName==1){
playerName[currentLine]+=c;
}
if(scoreName==0){
scores[currentLine]+=c;
}
if(c==' ') scoreName=1;
if(c=='\n'){
scoreName=0;
currentLine++;
}
}
fclose(fptr);
drawFrame();
SetCursorPosition(50,3);
printf("Name");
SetCursorPosition(15,3);
printf("Score");
SetCursorPosition(5,3);
printf("Rank");
currentLine=0;
bool showLinesIndicator=1;
if(line<=20) showLinesIndicator=0;
cbreak();
noecho();
scrollok(stdscr, TRUE);
nodelay(stdscr, TRUE);
while(1){
usleep(10000);
c = getch();
if(showLinesIndicator==1){
if(c==upArrow){
for(int i=1;i<paMaxX-1;i++){
for(int j=4;j<paMaxY-1;j++){
SetCursorPosition(i,j);
printf("\033[0m ");
}
}
if(currentLine!=0) currentLine--;
}
if(c==downArrow){
for(int i=1;i<paMaxX-1;i++){
for(int j=4;j<paMaxY-1;j++){
SetCursorPosition(i,j);
printf("\033[0m ");
}
}
if(currentLine+20!=line) currentLine++;
}
for(int i=currentLine;i<20+currentLine;i++){
SetCursorPosition(50,4+i-currentLine);
printf("%s", playerName[i].c_str());
SetCursorPosition(15,4+i-currentLine);
printf("%s", scores[i].c_str());
SetCursorPosition(5,4+i-currentLine);
printf("%d", i+1);
}
SetCursorPosition(1,paMaxY-2);
printf("lines %d-%d",currentLine+1,currentLine+21);
}
if(showLinesIndicator==0){
for(int i=currentLine;i<line;i++){
SetCursorPosition(50,4+i);
printf("%s", playerName[i].c_str());
SetCursorPosition(15,4+i);
printf("%s", scores[i].c_str());
SetCursorPosition(5,4+i-currentLine);
printf("%d", i+1);
}
}
SetCursorPosition(64,paMaxY-2);
printf("Press Enter to return to main menu.");
SetCursorPosition(paMaxX-28,paMaxY-3);
printf("Use ARROW KEYS to navigate.");
if(c=='\n'){
break;
}
}
}
int game(){
clock_t start_t,this_t,start;
start_t=clock();
start=start_t;
int posX[101],posY[101],fruitX,fruitY,snakeLength=2,ft=0,bombX[100],bombY[100],bombAmount=3,bombLoop=1;
int tempX[2],tempY[2];
bool bombShown[100];
double thistimeMillisec;
srand(time(NULL));
char input,lastInput;
cbreak();
noecho();
scrollok(stdscr, TRUE);
nodelay(stdscr, TRUE);
start_color();
init_pair(1,COLOR_WHITE, COLOR_BLACK);
wbkgd(stdscr, COLOR_PAIR(1));
printf("\e[?25l");//ปิดcursor
for(int i=0;i<101;i++){
posX[i]=-1;
posY[i]=-1;
}
posX[0]=paMaxX/2;
posY[0]=paMaxY/2;
posX[1]=paMaxX/2;
posY[1]=(paMaxX/2)+1;
srand(time(NULL));
fruitX=rand()%96+2;
fruitY=rand()%26+2;
for(int i=0;i<100;i++){
bombX[i]=rand()%98+1;
bombY[i]=rand()%28+1;
for(int j=0;j<i;j++){
while(1){
if(bombX[i]!=bombX[j]){
if(bombY[i]!=bombY[j]){
break;
}
}
bombX[i]=rand()%98+1;
bombY[i]=rand()%28+1;
}
}
bombShown[i]=0;
}
while(1){ //เริ่มเกม
this_t=clock();
SetCursorPosition(posX[0],posY[0]);
if(ft<5){//สร้างงูรอบแรกสุด
for(int i=0;i<paMaxX;i++){
for(int j=0;j<paMaxY;j++){
SetCursorPosition(i,j);
printf("\033[0m ");
}
}
SetCursorPosition(posX[0],posY[0]);
drawSnake();
drawFrame();
ft++;
}
SetCursorPosition(0,0);
printf("\033[1;97\033[45mScore: %d\033[0m", snakeLength-2);
SetCursorPosition(0,paMaxY-1);
printf("\033[45mUse WASD or ARROW KEYS to move snake, hold to dash, B to stop snake, X to exit immediately.\033[0m");
input=getch();//รับจากแป้นพิมพ์
if(input=='x'){
break;
}
if(input=='a'||input==leftArrow){
if((posX[0]>=1)&&(lastInput!='d')){
moveSnake(-1,0,posX,posY,tempX,tempY);
lastInput='a';
}
}
else if(input=='d'||input==rightArrow){
if((posX[0]<=98)&&(lastInput!='a')){
moveSnake(1,0,posX,posY,tempX,tempY);
lastInput='d';
}
}
else if(input=='w'||input==upArrow){
if((posY[0]>=1)&&(lastInput!='s')){
moveSnake(0,-1,posX,posY,tempX,tempY);
lastInput='w';
}
}
else if(input=='s'||input==downArrow){
if((posY[0]<=28)&&(lastInput!='w')){
moveSnake(0,1,posX,posY,tempX,tempY);
lastInput='s';
}
}
else if(input=='b'){
lastInput='0';
}
thistimeMillisec=(double)(this_t-start_t)/(double)CLOCKS_PER_SEC*10;
if(((int)thistimeMillisec%10)==1){
if(lastInput=='a'){
if(posX[0]>=1){
moveSnake(-1,0,posX,posY,tempX,tempY);
lastInput='a';
}
}
else if(lastInput=='d'){
if(posX[0]<=98){
moveSnake(1,0,posX,posY,tempX,tempY);
lastInput='d';
}
}
if(crashWall(posX[0],posY[0])||crashSnake(posX,posY)){
system("((speaker-test -t sine -f 700)& pid=$!; sleep 1s; kill -9 $pid) > /dev/null");
break;
}
start_t=this_t;
}
thistimeMillisec=(double)(this_t-start)/(double)CLOCKS_PER_SEC*7;
if(((int)thistimeMillisec%10)==1){
if(lastInput=='w'){
if(posY[0]>=1){
moveSnake(0,-1,posX,posY,tempX,tempY);
lastInput='w';
}
}
else if(lastInput=='s'){
if(posY[0]<=28){
moveSnake(0,1,posX,posY,tempX,tempY);
lastInput='s';
}
}
start=this_t;
}
if(crashBomb(posX[0],posY[0],bombX,bombY,bombShown)){
system("((speaker-test -t sine -f 700)& pid=$!; sleep 1s; kill -9 $pid) > /dev/null");
break;
}
if(eatFruit(posX[0],posY[0],fruitX,fruitY)==1){
snakeLength++;
fruitX=rand()%96+2;
fruitY=rand()%26+2;
for(int k=0;bombShown[k]==1;k++){
while(1){
if(fruitX!=bombX[k]){
if(fruitY!=bombY[k]){
break;
}
}
fruitX=rand()%96+2;
fruitY=rand()%26+2;
}
}
if(snakeLength<=100){
posX[snakeLength-1]=0;
posY[snakeLength-1]=0;
}
system("((speaker-test -t sine -f 700)& pid=$!; sleep 0.1s; kill -9 $pid) > /dev/null");
}
SetCursorPosition(fruitX,fruitY);
printf("0");
if(snakeLength-2>=bombAmount){
bombLoop++;
bombShown[bombLoop-2]=1;
bombAmount=bombLoop*3;
}
for(int i=0;i<100;i++){
if(bombShown[i]==1){
SetCursorPosition(bombX[i],bombY[i]);
printf("\033[1;97m\033[41m \033[0m");
}
}
}
return snakeLength-2;
}
int main () {
int mainMenuSelected,score;
initscr();
while(1){
mainMenuSelected=mainMenu();
if(mainMenuSelected==0){
score=game();
gameOver(score);
getchar();
}
if(mainMenuSelected==1){
showScores();
}
if(mainMenuSelected==2){
return 0;
}
}
}