Доделать змейку так, работало на любой раскладке - 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);
    }

Объяснение кода листинга программы

  1. Код представляет собой бесконечный цикл while(1), который выполняется до тех пор, пока пользователь не нажмет клавишу «ESC» (VK_ESCAPE).
  2. Внутри цикла, программа проверяет, нажаты ли клавиши 'A', 'W', 'S', 'D', 'UP', 'DOWN', 'LEFT' и 'RIGHT'.
  3. Если любая из этих клавиш нажата, программа выводит на экран соответствующее сообщение.
  4. После проверки всех клавиш, программа делает паузу в 100 миллисекунд с помощью функции Sleep(100).
  5. Программа начнет работать снова после завершения паузы и продолжит цикл, пока пользователь не нажмет клавишу «ESC».

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

14   голосов , оценка 3.714 из 5
Похожие ответы