Доделать змейку так, работало на любой раскладке - C (СИ)
Формулировка задачи:
Как сделать так,чтобы фрукты не появлялись на хвосте у змейки?
Как сделать так,чтобы работало на любой раскладке (хоть китайской)?
Ссылка на код (чтобы не слетели комментарии):http://rgho.st/7ytBk6fSZ
//Змейка v3.0 #include <stdio.h> #include <string.h> #include <conio.h> //Для использования функции _kbhit, которая ждет нажатия клавиши с клавиатуры #include <unistd.h> //Для usleep(). Аргумент usleep() - количество миллисекунд. usleep() - задержка на определенная кол-во миллисекунд //Константа (ширина и высота "карты игры"): #define len 21 //Глобальная переменная признака конца игры: int gameOver; //Координаты змейки и фрукта, переменная записи счета игрока: int x,y,fruitX,fruitY,score; //Информация о хвосте: int tailX[333]={0,0},tailY[333]={0,0}; //Координаты хвоста по x и по y int nTail=0; //Количество элементов в хвосте //Флаг,используемый в вызове меню: int f; //Карта игры char map[len][len]; //Перечисление возможных передвижений, записанных в перечисляемый тип enum: enum eDirection { STOP=0, LEFT, RIGHT, UP, DOWN } dir; //Функция вызова меню: void Menu(void){ system("cls"); int n; f=1; printf("Menu:\n1.Start game\n2.Settings\n3.Exit\nInput: "); scanf("%d",&n); switch (n){ case 1: return; case 2: system("cls"); printf("In the game:\nPress a to go left\nPress w to go up\nPress s to go down\nPress d to go right\nPress x to exit the game\nIn the settings menu:\nPress 1 to exit settings menu\nInput: "); scanf("%d",&n); if (n==1){ system("cls"); Menu(); } break; case 3: f=0; return; } } //Функция настройки параметров void Setup(void){ gameOver=0; //Игра только началась -> проиграть вы не могли dir = STOP; //Змейка стоит на месте //Начальные координаты змейки: x=(len-1)/2; y=x; //Начальные координаты фрукта: srand(7); //"Затравочное" значение (можно без этой команды) fruitX=rand()%len; while((fruitX==0) || (fruitX==20)){ fruitX=rand()%len; } fruitY=rand()%len; while((fruitY==0) || (fruitY==20)){ fruitY=rand()%len; } score=0; //Изначально счет равен нулю return; } //Функция для прорисовка "карты" void Draw(void){ system("cls"); int i,j; memset(map,32,441); //Заполнение массива пробелами map[y][x]='0'; //Запись головы змейки //Запись хвоста змейки: for(i=0;i<nTail;i++){ map[tailY[i]][tailX[i]]='o'; } //Запись фрукта: map[fruitY][fruitX]='F'; //Запись границ поля: for(i=0;i<len;i++){ map[i][0]='#'; map[i][len-1]='#'; map[0][i]='#'; map[len-1][i]='#'; } //Отображение карты и счета: for(i=0;i<len;i++){ for(j=0;j<len;j++){ printf("%c",map[i][j]); } printf("\n"); } printf("Score: %d",score); return; } //Функция отслеживания нажатий void Input(void){ while (_kbhit()){ //Возвращает правду если пользователь нажал кнопку на клавиатуре switch(getch()){ case 'a': dir=LEFT; break; case 'd': dir=RIGHT; break; case 'w': dir=UP; break; case 's': dir=DOWN; break; case 'x': gameOver=1; break; } } return; } //Логика игры void Logic(void){ int i,j; int prevX=tailX[0]; //Предыдущая позиция хвоста по x int prevY=tailY[0]; //Предыдущая позиция хвоста по y int prev2X,prev2Y; tailX[0]=x; tailY[0]=y; for(i=1;i<nTail;i++){ prev2X=tailX[i]; prev2Y=tailY[i]; tailX[i]=prevX; tailY[i]=prevY; prevX=prev2X; prevY=prev2Y; } switch (dir){ case LEFT: x--; break; case RIGHT: x++; break; case UP: y--; break; case DOWN: y++; break; } //if ((x>len-2) || (x<1) || (y>len-2) || (y<1)){ //Выходим из игры при касании стенки //gameOver=1; //} //Альтернативный вариант: когда змейка касается стенки, то она выходит с другого края карты if (x>len-2){ x=1; } else{ if (x<1){ x=len-2; } } if (y>len-2){ y=1; } else{ if (y<1){ y=len-2; } } //Если мы наткнулись на свой хвост, то игра закончена: for(i=0;i<nTail;i++){ if ((tailX[i]==x) && (tailY[i]==y)){ gameOver=1; } } //"Поедание" фрукта: if ((x==fruitX) && (y==fruitY)){ score+=10; //За каждый фрукт +10 очков //Новое расположение фрукта: fruitX=rand()%len; while((fruitX==0) || (fruitX==20)){ fruitX=rand()%len; } fruitY=rand()%len; while((fruitY==0) || (fruitY==20)){ fruitY=rand()%len; } //Увеличивание хвоста: nTail++; } return; } //Основная функция программы int main(void){ system("chcp 1251>nul"); Menu(); if (f){ Setup(); while(!gameOver){ Draw(); Input(); Logic(); usleep(111111); //Зарержка на определенное количество миллисекунд } system("cls"); printf("GAME OVER\nYOUR SCORE: %d\n",score); } system("pause>nul"); return 0; }
Решение задачи: «Доделать змейку так, работало на любой раскладке»
textual
Листинг программы
while(1) { if(GetKeyState(VK_ESCAPE)&0x80) printf("Esc\n"); if(GetKeyState('A')&0x80) printf("A\n"); if(GetKeyState('W')&0x80) printf("W\n"); if(GetKeyState('S')&0x80) printf("S\n"); if(GetKeyState('D')&0x80) printf("D\n"); if(GetKeyState(VK_UP)&0x80) printf("%c\n",(char)24); if(GetKeyState(VK_DOWN)&0x80) printf("%c\n",(char)25); if(GetKeyState(VK_LEFT)&0x80) printf("%c\n",(char)27); if(GetKeyState(VK_RIGHT)&0x80) printf("%c\n",(char)26); Sleep(100); }
Объяснение кода листинга программы
- Код представляет собой бесконечный цикл while(1), который выполняется до тех пор, пока пользователь не нажмет клавишу «ESC» (VK_ESCAPE).
- Внутри цикла, программа проверяет, нажаты ли клавиши 'A', 'W', 'S', 'D', 'UP', 'DOWN', 'LEFT' и 'RIGHT'.
- Если любая из этих клавиш нажата, программа выводит на экран соответствующее сообщение.
- После проверки всех клавиш, программа делает паузу в 100 миллисекунд с помощью функции Sleep(100).
- Программа начнет работать снова после завершения паузы и продолжит цикл, пока пользователь не нажмет клавишу «ESC».
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д