1 Востаннє редагувалося Kotey (19.05.2013 18:56:14)

Тема: Виправити помилки у програмі

Потрібно виправити управління: 
-Заборонити рух у зворотний бік; 
-Зробити управління стрілочками; 
Якщо є які небуть ідеї, буду радий їх побачити.

#include <stdlib.h> 
#include <dos.h>//для затримки
#include <stdio.h>
#include <conio.h>
//Прототипи
void draw_line(int x, int y);
void show_score();
void move();
void setup_level();
//Глобальні змінні
const int maxy=15, maxx=77;
const int snake_start_x=33,snake_start_y=7;
const char up_key='w', down_key='s', left_key='a', right_key='d';
int score, sl, speed, food, i, level, firstpress, high_score=0;
char food_field[maxy][maxx];
char direction = right_key;
struct snake_segment {
int y,x;
} snake[100];
//Початок програми
main()
{
char h=1;
int y1,x1;
char keypress;
//Коло перезапуску гри
do
{
food=3; level=1; score=0; speed=150;
rand();
setup_level();
//Головне коло гри
do
{
delay(speed);
//Зміна напряму
if (kbhit())
{
keypress=getch();
direction=keypress;
}
move();
//Порожній останній сегмент змія
gotoxy(snake[0].x,snake[0].y);
cprintf(" ");
//видаляємо його з масиву
for (i=1;i<=sl;i++)
snake[i-1]=snake[i];
//Перефарбовуємо змія в зелений
textcolor(LIGHTGREEN);
for (i=0;i<=sl;i++)
{
gotoxy(snake[i].x,snake[i].y);
cprintf("0");
}
//Голова змія
textcolor(DARKGRAY);
y1=wherey();
x1=wherex();
gotoxy(x1-1,y1); cprintf("%c",h);
for (i=0;i<=sl;i++)
if(keypress==up_key){gotoxy(x1-1,y1); cprintf("%c",h);}else
if(keypress==down_key){gotoxy(x1-1,y1); cprintf("%c",h);}else
if(keypress==left_key){gotoxy(x1-1,y1); cprintf("%c",h);}else
if(keypress==right_key){gotoxy(x1-1,y1); cprintf("%c",h);}
//Робимо курсор невидимим
_setcursortype(_NOCURSOR);
//Пауза перед кожним рівнем
if (firstpress) { while(!kbhit()); firstpress = 0; }
/*Определение врезания в стены*/
if ((snake[sl-1].y>maxy+2)||(snake[sl-1].y<=2)||
(snake[sl-1].x>maxx+1)||(snake[sl-1].x<=1)||
/*Врізання в камні */
 (food_field[snake[sl-1].y-3][snake[sl-1].x-2]=='X'))
keypress='x'; //кінець гри
//врізання змія в самого в себе
for (i=0;i<sl-1;i++)
if ( (snake[sl-1].y)==(snake[i].y) &&
(snake[sl-1].x)==(snake[i].x))
{
keypress='x'; //Коніць гри
}
//Знаходження їжі
if (food_field[snake[sl-1].y-3][snake[sl-1].x-2]=='*')
{
//Збільшення очок та довжини змія
score+=sl+food; show_score(); sl++;
//Перехід на наступний рівень
if (sl==(level+3)*2)
{
score+=level*1; food+=1; level++;// збільшення рівня і кількості їжі
if ((level%2==0)&&(speed>1)) speed-10;// збільшення швидкості кожні два рівня
setup_level(); //Установки рівня
}
}
} while (keypress!='x'); //Кінець ігрового циклу
if (score > high_score) high_score = score;
show_score();
gotoxy(30,7); textcolor(LIGHTRED); cprintf("G A M E   O V E R");
gotoxy(30,10); textcolor(YELLOW); cprintf("Another Game (y/n)? ");
do keypress=getch(); while((keypress!='y')&&(keypress!='n'));
} while (keypress=='y'); //перезапуск ігрового циклу
return 0;
}
void setup_level() //Функція встановлення рівня
{
int y,x,i;
//Настройка глобальних змінних для нового рівня
sl=level+4; direction=right_key;
firstpress=1;
//Зповнення поля символами ' '
for(y=0;y<maxy;y++)
for(x=0;x<maxx;x++)
food_field[y][x]= ' ';
//Заповнення поля каміннями та їжею
for(i=0;i<food*2;i++)
{
y= rand()%maxy;
x= rand()%maxx;
if(i<food)
food_field[y][x]='X';
else
food_field[y][x]='*';
}
//Створення масива довжини sl
for(i=0;i<sl;i++)
{
snake[i].y=snake_start_y;
snake[i].x=snake_start_x+i;
}
// Вимальовка поля
draw_line(1,2);
for(y=0;y<maxy;y++)
{
gotoxy(1,y+3);
textcolor(LIGHTBLUE); cprintf("|");
textcolor(BROWN);
for(x=0;x<maxx;x++)
cprintf("%c",food_field[y][x]);
textcolor(LIGHTBLUE);
cprintf("|");
}
draw_line(1,maxy+3);
show_score();
gotoxy(2,maxy+6);
textcolor(LIGHTRED);
cprintf("Left: %c,Right: %c, Up: %c, Down: %c, Exit: x. Any key to start.",
 left_key,right_key,up_key,down_key);
 textcolor(GREEN);
gotoxy(32,1);
cprintf("~~~SNAKE GAME~~~");
 return;
}
void draw_line(int x, int y) //Функція створення лінії з =
{
 gotoxy(x,y); textcolor(LIGHTBLUE);
for (x=0;x<maxx+2;x++) cprintf("=");
return;
}
void show_score() //Функція виводу очків на екран
{
textcolor(LIGHTCYAN);
gotoxy(2,maxy+4);
cprintf("Level: %05d",level);
gotoxy(40,maxy+4);
textcolor(LIGHTGREEN);
cprintf("Score: %05d",score);
gotoxy(60,maxy+4);
textcolor(LIGHTMAGENTA);
cprintf("High Score: %05d",high_score);
return;
}
void move() //Функція руху
{
switch(direction)
{
case(right_key): snake[sl].y=snake[sl-1].y;
                 snake[sl].x=snake[sl-1].x+1;
                 break;
case(left_key) : snake[sl].y=snake[sl-1].y;
                 snake[sl].x=snake[sl-1].x-1;
                 break;
case(up_key)   : snake[sl].y=snake[sl-1].y-1;
                      snake[sl].x=snake[sl-1].x;
                      break;
case(down_key) : snake[sl].y=snake[sl-1].y+1;
                      snake[sl].x=snake[sl-1].x;
                 break;
  }
return ;
}

2

Re: Виправити помилки у програмі

Пропоную відформатувати код, щоб можна було, принаймні, вловити його логіку.

3 Востаннє редагувалося koala (19.05.2013 09:54:46)

Re: Виправити помилки у програмі

Kotey написав:

Потрібно виправити управління: 
-Заборонити рух у зворотний бік; 
-Зробити управління стрілочками;

1. Це настільки елементарно порівняно із всім іншим (на перший погляд - по одному рядку в кожному з case-ів в move), що виникає питання - а чи це твій код?
2. Стрілочки повертають два скан-коди, тобто потребують два виклики getch. http://lmgtfy.com/?q=%D1%81%D0%BA%D0%B0 … 0%BE%D0%B4
3. Цілком погоджуюся із Bartash. Код просто боляче читати.
4. Це обов'язкова умова, щоб програма була під 15 років як мертву ОС?

4

Re: Виправити помилки у програмі

koala написав:

Це обов'язкова умова, щоб програма була під 15 років як мертву ОС?

Нині популярним є використання трупів давно відамортизованих ресурсів, особливо у державних структурах. Це якщо згадати, наприклад, про дос у гімназіях, чистий паскаль у вишах та ОБолонський процес.

5

Re: Виправити помилки у програмі

Цілком доречні заувження. Код було зроблено по дуже старому зразку. Керування там, організованвано найпростішим методом. Про те що стрілочки повертають два скан-коди я не знав. І що до мови - ця мова і досі вивчається в вузах. Тому ця програма має бути саме на цій мові (

6

Re: Виправити помилки у програмі

А тепер найдурніше питання: яка це, зрештою, мова програмування? Це C++ без майже всього, чого нема в C?

7

Re: Виправити помилки у програмі

Це древня мова  С.

8

Re: Виправити помилки у програмі

Kotey написав:

Це древня мова  С.

Анахронізмів не бачу, тому віднесемо на С89.

Скан-кодів правда по два. Більше того, є випадки іншого штибу, коли комбінація клавіш дає в результаті код, аналогічний деякій одній клавіші (здається, ми так ловили Ctrl+M і деякі інші).

9 Востаннє редагувалося koala (19.05.2013 14:46:35)

Re: Виправити помилки у програмі

Kotey написав:

Це древня мова  С.

const int maxy=15, maxx=77;
char food_field[maxy][maxx];

За стандартом таке не має проходити навіть в C11. Принаймні, gcc лається.

10

Re: Виправити помилки у програмі

За "Древню мову" маю вибачитися. Я новачок в програмуванні. Просто отримав складне завдання.

11

Re: Виправити помилки у програмі

koala написав:
Kotey написав:

Це древня мова  С.

const int maxy=15, maxx=77;
char food_field[maxy][maxx];

За стандартом таке не має проходити навіть в C11. Принаймні, gcc лається.

const'а провтикав. Це - хрести. :(

Тобто код міг бути перше написаний під дос, а згодом була спроба його "модернізувати" під хрести.

З.І: змійку у нас один парубок писав консольну. Тільки для того цілком підійшли WinAPI-функції. :)

12

Re: Виправити помилки у програмі

const'а провтикав. Це - хрести. :(
Тобто код міг бути перше написаний під дос, а згодом була спроба його "модернізувати" під хрести.

Я працюю в Turbo C++, тому що Turbo C я просто не можу запустити(
Перевіряю код на стареньких ЕОМ, які не мають навіть входу для флешки(

13

Re: Виправити помилки у програмі

Вам вже вказали напрямок роботи, показуйте, що зробили...

14

Re: Виправити помилки у програмі

Попробував зробити управління стрілочками

if (kbhit())
keypress=getch();
if (keypress==0)
{
keypress=getch();
direction=keypress;
} 

але виникає помилка при першому старті гри.
Також пробував поставити заборону на рух в протилежну сторону, але програма на неї не реагує.
(в глобальні добавляється unsigned char flag=0;)

void move()
{
switch(direction)
{
case(right_key):  if(flag&00000010) break;
  flag=00000001; snake[sl].y=snake[sl-1].y;
                 snake[sl].x=snake[sl-1].x+1;
                 break;
case(left_key) :  if(flag&00000001) break;
                flag=00000010; snake[sl].y=snake[sl-1].y;
                 snake[sl].x=snake[sl-1].x-1;
                 break;
case(up_key)   :   if(flag&00001000) break;
           flag=00000100; snake[sl].y=snake[sl-1].y-1;
 snake[sl].x=snake[sl-1].x;
 break;
case(down_key) :  if(flag&00000100) break;
 flag=00001000; snake[sl].y=snake[sl-1].y+1;
 snake[sl].x=snake[sl-1].x;
                 break;
  }
return ;
}

15

Re: Виправити помилки у програмі

але виникає помилка при першому старті гри.

Текст/скрін помилки в студію.

З.І: вам правда зручно читати код у такому вигляді, Kotey?.. %_%

16

Re: Виправити помилки у програмі

Так.
Там не помилка компілятора, там скоріше безкомпромісне завершення гри.

17

Re: Виправити помилки у програмі

Kotey написав:

Так.
Там не помилка компілятора, там скоріше безкомпромісне завершення гри.

Ну так на якомусь же етапі виконання. Зневаджувач доцільно запустити і покроково пройтися. Врешті-решт, якийсь дебаг-лог-файлик провести...

Очікую глюки десь отут:

move();
//...
//видаляємо його з масиву
for (i=1;i<=sl;i++)
snake[i-1]=snake[i];
//одну видалили - а іншу додали ж?

З.І: ліпше постіть код у нових постах: не редагуйте перший пост теми, бо це трохи спантеличує. :)

18

Re: Виправити помилки у програмі

Kotey написав:

Я працюю в Turbo C++, тому що Turbo C я просто не можу запустити(
Перевіряю код на стареньких ЕОМ, які не мають навіть входу для флешки(

Навіть якби запустили - він не пропустить ваш код, бо у коді присутні елементи С++.

19

Re: Виправити помилки у програмі

Я отримав багато відповідей на запитання, які я не ставив. Але на головне запитання з яким я звертався, я так і не отримав жодної відповіді, хоча б приблизної. Воно звучить десь так: "Як при натиснені одної клавіші в одному кроці, заборонити натиснення певної іншої клавіші в наступному кроці?" Це запитання вже досить довгий час залишається без відповіді.

20

Re: Виправити помилки у програмі

Kotey написав:

Я отримав багато відповідей на запитання, які я не ставив. Але на головне запитання з яким я звертався, я так і не отримав жодної відповіді, хоча б приблизної. Воно звучить десь так: "Як при натиснені одної клавіші в одному кроці, заборонити натиснення певної іншої клавіші в наступному кроці?" Це запитання вже досить довгий час залишається без відповіді.

А хіба відповідь не самоочевидна? Запам'ятати якусь інформацію, пов'язану із попереднім кроком (хоч клавішу, хоч напрямок руху) і перед тим, як робити наступний, порівняти - може, його не треба робити...

Подякували: Kotey1