Пишу пакмана, точнее - вариацию на тему. Пишу под консоль винды. Может ли функция ReadConsoleInput не останавливать исполнения программы, ожидая события? Т.е. буфер событий заполняется всё время исполнения программы, а сама функция при вызове лишь записывает его в мой массив. Как я понимаю без многопоточности это не реализуемо. Придёся читать msdn. И ещё. Помогите реализовать волновой алгоритм (метод у меня называется intellect). Как он работает я понял, а вот реализовать - в голову не идёт. Моя прога работает так: карта представляет собой массив структуры, содержащей битовые поля. Прошу помощи, с одной стороны хочется сделать, а с другой время поджимет. Могу вообще забить, но я уже погрузился в задачу, очень обидно её бросать. Код (Text): #include <iostream> //#include <stdio.h> //#include <conio.h> #include <windows.h> //#include <stdlib.h> //#include <process.h> #include <time.h> #include <math.h> #include <conio.h> // 174еда 0стена 164зло 169пак class MOVING_UNITS { protected: enum direction { Up, Right, Left, Down } dir; virtual bool move(direction dir, int x, int y) = 0; }; class WALL { protected: virtual void place_walls() = 0; unsigned char wall_smile; WORD wall_attr; int MAX_WALL_LENGTH; int NUMBER_OF_WALLS; WALL(); }; WALL::WALL() { MAX_WALL_LENGTH = 3; NUMBER_OF_WALLS = 4; wall_attr = FOREGROUND_BLUE | FOREGROUND_GREEN; wall_smile = 0; } class PACMAN : protected MOVING_UNITS { protected: virtual void place_pacman() = 0; unsigned char pacman_smile; WORD pacman_attr; PACMAN(); }; PACMAN::PACMAN() { pacman_smile = 169; pacman_attr = FOREGROUND_GREEN | BACKGROUND_RED; } class EVIL : protected MOVING_UNITS { protected: virtual void place_evils() = 0; virtual void intellect(int x, int y) = 0; int NUMBER_OF_EVILS; unsigned char evil_smile; WORD evil_attr; EVIL(); }; EVIL::EVIL() { evil_smile = 164; evil_attr = FOREGROUND_RED; NUMBER_OF_EVILS = 1; } class FOOD { protected: virtual void place_food() = 0; int NUMBER_OF_FOOD; unsigned char food_smile; WORD food_attr; int food_counter; FOOD(); }; FOOD::FOOD() { food_smile = 174; food_attr = FOREGROUND_BLUE | FOREGROUND_GREEN; NUMBER_OF_FOOD = 2; food_counter = 0; } class WORLD_MAP : protected WALL, protected PACMAN, protected EVIL, protected FOOD { int WORLD_SIZE_X, WORLD_SIZE_Y; struct WORLD_MAP_STRUCT { unsigned Wall: 1; unsigned Evil: 1; unsigned Turn: 1; unsigned Food: 1; unsigned Space: 1; } *map; struct PACMAN_COORDINATE { int _X_; int _Y_; } pac; HANDLE hConsoleOutput; COORD dwCursorPosition; WCHAR cCharacter; DWORD lpNumberOfCharsWritten; DWORD lpNumberOfAttrsWritten; HANDLE hConsoleInput; INPUT_RECORD lpBuffer[128]; DWORD lpNumberOfEventsRead; unsigned char space_smile; WORD space_attr; WORD prev_key; void place_walls(); void place_food(); void place_evils(); void place_pacman(); bool move(direction dir, int x, int y); void paint(int x, int y); void intellect(int x, int y); void Game(); void KeyEventProc(int x, int y); public: WORLD_MAP(); }; void WORLD_MAP::intellect(int x, int y) { Sleep(100); if(abs(x - pac._X_) > abs(y - pac._Y_)) { if(x > pac._X_) { if(move(Left, x, y)) ; else { if(move(Up, x, y)) ; else move(Down, x, y); } } else if(move(Right, x, y)) ; else { if(y > pac._Y_) { if(move(Up, x, y)) ; } else move(Down, x, y); } } // ******************************************************* else { if(y > pac._Y_) { if(move(Up, x, y)) ; else { if(move(Left, x, y)) ; else move(Right, x, y); } } else if(move(Down, x, y)) ; else { if(move(Left, x, y)) ; else move(Right, x, y); } } } void WORLD_MAP::paint(int x, int y) { dwCursorPosition.X = x; dwCursorPosition.Y = y; WORD wAttribute; if((x == pac._X_) && (y == pac._Y_)) { cCharacter = pacman_smile; wAttribute = pacman_attr; } else if((map[y*WORLD_SIZE_X+x].Space) && (map[y*WORLD_SIZE_X+x].Food) ) { cCharacter = food_smile; wAttribute = food_attr; } else if(map[y*WORLD_SIZE_X+x].Space) { cCharacter = space_smile; wAttribute = space_attr; } else if(map[y*WORLD_SIZE_X+x].Evil) { cCharacter = evil_smile; wAttribute = evil_attr; } else if(map[y*WORLD_SIZE_X+x].Wall) { cCharacter = wall_smile; wAttribute = wall_attr; } else return; FillConsoleOutputAttribute(hConsoleOutput, wAttribute, 1, dwCursorPosition, &lpNumberOfAttrsWritten); FillConsoleOutputCharacter(hConsoleOutput, cCharacter, 1, dwCursorPosition, &lpNumberOfCharsWritten); } void WORLD_MAP::KeyEventProc(int x, int y) { if(map[pac._Y_*WORLD_SIZE_X+pac._X_].Evil) { FreeConsole(); AllocConsole(); std::cout << "You loose!"; getch(); exit(0); } //38вверх 37влево 40вниз 39вправо Sleep(150); WCHAR smth = lpBuffer[0].Event.KeyEvent.wVirtualKeyCode; switch(smth) { case 38: prev_key = 38; if(map[(y-1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y-1)*WORLD_SIZE_X+x].Food = false; } pac._Y_--; if(!move(Up, x, y)) pac._Y_++; break; case 37: prev_key = 37; if(map[y*WORLD_SIZE_X+x-1].Food) { food_counter++; map[y*WORLD_SIZE_X+x-1].Food = false; } pac._X_--; if(!move(Left, x, y)) pac._X_++; break; case 39: prev_key = 39; if(map[y*WORLD_SIZE_X+x+1].Food) { food_counter++; map[y*WORLD_SIZE_X+x+1].Food = false; } pac._X_++; if(!move(Right, x, y)) pac._X_--; break; case 40: prev_key = 40; if(map[(y+1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y+1)*WORLD_SIZE_X+x].Food = false; } pac._Y_++; if(!move(Down, x, y)) pac._Y_--; break; default: switch(prev_key) { case 38: if(map[(y-1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y-1)*WORLD_SIZE_X+x].Food = false; } pac._Y_--; if(!move(Up, x, y)) pac._Y_++; break; case 37: if(map[y*WORLD_SIZE_X+x-1].Food) { food_counter++; map[y*WORLD_SIZE_X+x-1].Food = false; } pac._X_--; if(!move(Left, x, y)) pac._X_++; break; case 39: if(map[y*WORLD_SIZE_X+x+1].Food) { food_counter++; map[y*WORLD_SIZE_X+x+1].Food = false; } pac._X_++; if(!move(Right, x, y)) pac._X_--; break; case 40: if(map[(y+1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y+1)*WORLD_SIZE_X+x].Food = false; } pac._Y_++; if(!move(Down, x, y)) pac._Y_--; break; default: //std::cout << "AA"; break; } break; } if(food_counter >= NUMBER_OF_FOOD) { FreeConsole(); AllocConsole(); std::cout << "You win!"; getch(); exit(0); } for(y=0; y<WORLD_SIZE_Y; y++) for(x=0; x<WORLD_SIZE_X; x++) map[y*WORLD_SIZE_X+x].Turn = false; for(y=0; y<WORLD_SIZE_Y; y++) for(x=0; x<WORLD_SIZE_X; x++) if((map[y*WORLD_SIZE_X+x].Evil) && (!(map[y*WORLD_SIZE_X+x].Turn))) intellect(x, y); } void WORLD_MAP::Game() { int x, y; std::cout << "\nGame starts!"; FreeConsole(); AllocConsole(); hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); for(x=0; x<WORLD_SIZE_X; x++) for(y=0; y<WORLD_SIZE_Y; y++) paint(x, y); while(true) { ReadConsoleInput(hConsoleInput, lpBuffer, 128, &lpNumberOfEventsRead); //как scanf, пока не произойдёт событие, выполнять программу дальше не будет KeyEventProc(pac._X_, pac._Y_); } } void WORLD_MAP::place_pacman() { int x, y; std::cout << "\nGenerating pacman..."; srand(time(0)); do { x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); } while( !( (map[y*WORLD_SIZE_X+x].Space) && (!map[y*WORLD_SIZE_X+x].Food) ) ); pac._X_ = x; pac._Y_ = y; } void WORLD_MAP::place_food() { int x, y, i; std::cout << "\nGenerating food..."; srand(time(0)); for(i=0; i<NUMBER_OF_FOOD; i++) { x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); if(map[y*WORLD_SIZE_X+x].Space) map[y*WORLD_SIZE_X+x].Food = true; else i--; } } void WORLD_MAP::place_evils() { int x, y, i; std::cout << "\nGenerating evils..."; srand(time(0)); for(i=0; i<NUMBER_OF_EVILS; i++) { x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); if(map[y*WORLD_SIZE_X+x].Space && (!map[y*WORLD_SIZE_X+x].Food)) { map[y*WORLD_SIZE_X+x].Evil = true; map[y*WORLD_SIZE_X+x].Space = false; } else i--; } } void WORLD_MAP::place_walls() { int x, y, i, j; std::cout << "\nGenerating walls..."; for(i=0; i<NUMBER_OF_WALLS; i++) { srand(time(0)); x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); for(j=0; j<MAX_WALL_LENGTH; j++) { if((map[y*WORLD_SIZE_X+x].Space) && (!map[y*WORLD_SIZE_X+x].Food)) { map[y*WORLD_SIZE_X+x].Wall = true; map[y*WORLD_SIZE_X+x].Space = false; } else j--; x = abs( (rand()) > 16000 ? (x+1)%WORLD_SIZE_X : (x-1)%WORLD_SIZE_X ); y = abs( (rand()) > 16000 ? (y+1)%WORLD_SIZE_Y : (y-1)%WORLD_SIZE_Y ); } } } WORLD_MAP::WORLD_MAP() { int i, j; std::cout << "This is pacman!"; prev_key = 0; WORLD_SIZE_X = 25; WORLD_SIZE_Y = 15; map = new WORLD_MAP_STRUCT [WORLD_SIZE_X*WORLD_SIZE_Y]; space_smile = 199; space_attr = FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_BLUE; for(i=0; i<WORLD_SIZE_Y; i++) for(j=0; j<WORLD_SIZE_X; j++) { map[i*WORLD_SIZE_X+j].Space = true; map[i*WORLD_SIZE_X+j].Food = false; map[i*WORLD_SIZE_X+j].Wall = false; map[i*WORLD_SIZE_X+j].Evil = false; map[i*WORLD_SIZE_X+j].Turn = false; } place_walls(); place_food(); place_evils(); place_pacman(); Game(); } bool WORLD_MAP::move(direction dir, int x, int y) { switch (dir) { case Up: if((map[(y-1)*WORLD_SIZE_X+x].Space) && (!map[(y-1)*WORLD_SIZE_X+x].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[(y-1)*WORLD_SIZE_X+x] = map[y*WORLD_SIZE_X+x]; map[(y-1)*WORLD_SIZE_X+x].Turn = true; paint(x, y-1); } else return false; break; case Down: if((map[(y+1)*WORLD_SIZE_X+x].Space) && (!map[(y+1)*WORLD_SIZE_X+x].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[(y+1)*WORLD_SIZE_X+x] = map[y*WORLD_SIZE_X+x]; map[(y+1)*WORLD_SIZE_X+x].Turn = true; paint(x, y+1); } else return false; break; case Left: if((map[y*WORLD_SIZE_X+x-1].Space) && (!map[y*WORLD_SIZE_X+x-1].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[y*WORLD_SIZE_X+x-1] = map[y*WORLD_SIZE_X+x]; map[y*WORLD_SIZE_X+x-1].Turn = true; paint(x-1, y); } else return false; break; case Right: if((map[y*WORLD_SIZE_X+x+1].Space) && (!map[y*WORLD_SIZE_X+x+1].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[y*WORLD_SIZE_X+x+1] = map[y*WORLD_SIZE_X+x]; map[y*WORLD_SIZE_X+x+1].Turn = true; paint(x+1, y); } else return false; break; } map[y*WORLD_SIZE_X+x].Food = false; map[y*WORLD_SIZE_X+x].Space = true; map[y*WORLD_SIZE_X+x].Evil = false; map[y*WORLD_SIZE_X+x].Turn = false; paint(x, y); return true; } int main() { WORLD_MAP the_very_game; return 0; }
Вот код с потоками. Почему не получается открыть поток по адрессу функции? Пишет, что что-то с адрессом поточной функции Код (Text): #include <iostream> //#include <stdio.h> //#include <conio.h> #include <windows.h> //#include <stdlib.h> //#include <process.h> #include <time.h> #include <math.h> #include <conio.h> // 174еда 0стена 164зло 169пак class MOVING_UNITS { protected: enum direction { Up, Right, Left, Down } dir; virtual bool move(direction dir, int x, int y) = 0; }; class WALL { protected: virtual void place_walls() = 0; unsigned char wall_smile; WORD wall_attr; int MAX_WALL_LENGTH; int NUMBER_OF_WALLS; WALL(); }; WALL::WALL() { MAX_WALL_LENGTH = 3; NUMBER_OF_WALLS = 4; wall_attr = FOREGROUND_BLUE | FOREGROUND_GREEN; wall_smile = 0; } class PACMAN : protected MOVING_UNITS { protected: virtual void place_pacman() = 0; unsigned char pacman_smile; WORD pacman_attr; PACMAN(); }; PACMAN::PACMAN() { pacman_smile = 169; pacman_attr = FOREGROUND_GREEN | BACKGROUND_RED; } class EVIL : protected MOVING_UNITS { protected: virtual void place_evils() = 0; virtual void intellect(int x, int y) = 0; int NUMBER_OF_EVILS; unsigned char evil_smile; WORD evil_attr; EVIL(); }; EVIL::EVIL() { evil_smile = 164; evil_attr = FOREGROUND_RED; NUMBER_OF_EVILS = 1; } class FOOD { protected: virtual void place_food() = 0; int NUMBER_OF_FOOD; unsigned char food_smile; WORD food_attr; int food_counter; FOOD(); }; FOOD::FOOD() { food_smile = 174; food_attr = FOREGROUND_BLUE | FOREGROUND_GREEN; NUMBER_OF_FOOD = 2; food_counter = 0; } class WORLD_MAP : protected WALL, protected PACMAN, protected EVIL, protected FOOD { int WORLD_SIZE_X, WORLD_SIZE_Y; struct WORLD_MAP_STRUCT { unsigned Wall: 1; unsigned Evil: 1; unsigned Turn: 1; unsigned Food: 1; unsigned Space: 1; } *map; struct PACMAN_COORDINATE { int _X_; int _Y_; } pac; HANDLE hConsoleOutput; HANDLE hConsoleInput; unsigned char space_smile; WORD space_attr; WORD prev_key; void place_walls(); void place_food(); void place_evils(); void place_pacman(); bool move(direction dir, int x, int y); void paint(int x, int y); void intellect(int x, int y); void Game(); DWORD WINAPI MyThreadFunction(LPVOID lpParameter); void KeyEventProc(int x, int y, INPUT_RECORD *lpBuffer); public: WORLD_MAP(); }; DWORD WINAPI WORLD_MAP::MyThreadFunction(LPVOID lpParameter) { DWORD lpNumberOfEventsRead; if(ReadConsoleInput(hConsoleInput, (PINPUT_RECORD)lpParameter, 128, &lpNumberOfEventsRead)) return 0; else return 1; } void WORLD_MAP::intellect(int x, int y) { Sleep(100); if(abs(x - pac._X_) > abs(y - pac._Y_)) { if(x > pac._X_) { if(move(Left, x, y)) ; else { if(move(Up, x, y)) ; else move(Down, x, y); } } else if(move(Right, x, y)) ; else { if(y > pac._Y_) { if(move(Up, x, y)) ; } else move(Down, x, y); } } // ******************************************************* else { if(y > pac._Y_) { if(move(Up, x, y)) ; else { if(move(Left, x, y)) ; else move(Right, x, y); } } else if(move(Down, x, y)) ; else { if(move(Left, x, y)) ; else move(Right, x, y); } } } void WORLD_MAP::paint(int x, int y) { COORD dwCursorPosition; WCHAR cCharacter; DWORD lpNumberOfCharsWritten; DWORD lpNumberOfAttrsWritten; WORD wAttribute; dwCursorPosition.X = x; dwCursorPosition.Y = y; if((x == pac._X_) && (y == pac._Y_)) { cCharacter = pacman_smile; wAttribute = pacman_attr; } else if((map[y*WORLD_SIZE_X+x].Space) && (map[y*WORLD_SIZE_X+x].Food) ) { cCharacter = food_smile; wAttribute = food_attr; } else if(map[y*WORLD_SIZE_X+x].Space) { cCharacter = space_smile; wAttribute = space_attr; } else if(map[y*WORLD_SIZE_X+x].Evil) { cCharacter = evil_smile; wAttribute = evil_attr; } else if(map[y*WORLD_SIZE_X+x].Wall) { cCharacter = wall_smile; wAttribute = wall_attr; } else return; FillConsoleOutputAttribute(hConsoleOutput, wAttribute, 1, dwCursorPosition, &lpNumberOfAttrsWritten); FillConsoleOutputCharacter(hConsoleOutput, cCharacter, 1, dwCursorPosition, &lpNumberOfCharsWritten); } void WORLD_MAP::KeyEventProc(int x, int y, INPUT_RECORD *lpBuffer) { if(map[pac._Y_*WORLD_SIZE_X+pac._X_].Evil) { FreeConsole(); AllocConsole(); std::cout << "You loose!"; getch(); exit(0); } //38вверх 37влево 40вниз 39вправо Sleep(150); WCHAR smth = lpBuffer[0].Event.KeyEvent.wVirtualKeyCode; switch(smth) { case 38: prev_key = 38; if(map[(y-1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y-1)*WORLD_SIZE_X+x].Food = false; } pac._Y_--; if(!move(Up, x, y)) pac._Y_++; break; case 37: prev_key = 37; if(map[y*WORLD_SIZE_X+x-1].Food) { food_counter++; map[y*WORLD_SIZE_X+x-1].Food = false; } pac._X_--; if(!move(Left, x, y)) pac._X_++; break; case 39: prev_key = 39; if(map[y*WORLD_SIZE_X+x+1].Food) { food_counter++; map[y*WORLD_SIZE_X+x+1].Food = false; } pac._X_++; if(!move(Right, x, y)) pac._X_--; break; case 40: prev_key = 40; if(map[(y+1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y+1)*WORLD_SIZE_X+x].Food = false; } pac._Y_++; if(!move(Down, x, y)) pac._Y_--; break; default: switch(prev_key) { case 38: if(map[(y-1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y-1)*WORLD_SIZE_X+x].Food = false; } pac._Y_--; if(!move(Up, x, y)) pac._Y_++; break; case 37: if(map[y*WORLD_SIZE_X+x-1].Food) { food_counter++; map[y*WORLD_SIZE_X+x-1].Food = false; } pac._X_--; if(!move(Left, x, y)) pac._X_++; break; case 39: if(map[y*WORLD_SIZE_X+x+1].Food) { food_counter++; map[y*WORLD_SIZE_X+x+1].Food = false; } pac._X_++; if(!move(Right, x, y)) pac._X_--; break; case 40: if(map[(y+1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y+1)*WORLD_SIZE_X+x].Food = false; } pac._Y_++; if(!move(Down, x, y)) pac._Y_--; break; default: //std::cout << "AA"; break; } break; } if(food_counter >= NUMBER_OF_FOOD) { FreeConsole(); AllocConsole(); std::cout << "You win!"; getch(); exit(0); } for(y=0; y<WORLD_SIZE_Y; y++) for(x=0; x<WORLD_SIZE_X; x++) map[y*WORLD_SIZE_X+x].Turn = false; for(y=0; y<WORLD_SIZE_Y; y++) for(x=0; x<WORLD_SIZE_X; x++) if((map[y*WORLD_SIZE_X+x].Evil) && (!(map[y*WORLD_SIZE_X+x].Turn))) intellect(x, y); } void WORLD_MAP::Game() { int x, y; INPUT_RECORD lpBuffer[128]; HANDLE hThread; //LPTHREAD_START_ROUTINE lpStartAdress; //lpStartAdress = &MyThreadFunction; hThread = CreateThread(NULL, 0, MyThreadFunction, lpBuffer, 0, NULL); // ПОЧЕМУ НЕ УДАЁТСЯ ВЫЗВАТЬ????? std::cout << "\nGame starts!"; FreeConsole(); AllocConsole(); hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); for(x=0; x<WORLD_SIZE_X; x++) for(y=0; y<WORLD_SIZE_Y; y++) paint(x, y); while(true) KeyEventProc(pac._X_, pac._Y_, lpBuffer); } void WORLD_MAP::place_pacman() { int x, y; std::cout << "\nGenerating pacman..."; srand(time(0)); do { x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); } while( !( (map[y*WORLD_SIZE_X+x].Space) && (!map[y*WORLD_SIZE_X+x].Food) ) ); pac._X_ = x; pac._Y_ = y; } void WORLD_MAP::place_food() { int x, y, i; std::cout << "\nGenerating food..."; srand(time(0)); for(i=0; i<NUMBER_OF_FOOD; i++) { x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); if(map[y*WORLD_SIZE_X+x].Space) map[y*WORLD_SIZE_X+x].Food = true; else i--; } } void WORLD_MAP::place_evils() { int x, y, i; std::cout << "\nGenerating evils..."; srand(time(0)); for(i=0; i<NUMBER_OF_EVILS; i++) { x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); if(map[y*WORLD_SIZE_X+x].Space && (!map[y*WORLD_SIZE_X+x].Food)) { map[y*WORLD_SIZE_X+x].Evil = true; map[y*WORLD_SIZE_X+x].Space = false; } else i--; } } void WORLD_MAP::place_walls() { int x, y, i, j; std::cout << "\nGenerating walls..."; for(i=0; i<NUMBER_OF_WALLS; i++) { srand(time(0)); x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); for(j=0; j<MAX_WALL_LENGTH; j++) { if((map[y*WORLD_SIZE_X+x].Space) && (!map[y*WORLD_SIZE_X+x].Food)) { map[y*WORLD_SIZE_X+x].Wall = true; map[y*WORLD_SIZE_X+x].Space = false; } else j--; x = abs( (rand()) > 16000 ? (x+1)%WORLD_SIZE_X : (x-1)%WORLD_SIZE_X ); y = abs( (rand()) > 16000 ? (y+1)%WORLD_SIZE_Y : (y-1)%WORLD_SIZE_Y ); } } } WORLD_MAP::WORLD_MAP() { int i, j; std::cout << "This is pacman!"; prev_key = 0; WORLD_SIZE_X = 25; WORLD_SIZE_Y = 15; map = new WORLD_MAP_STRUCT [WORLD_SIZE_X*WORLD_SIZE_Y]; space_smile = 199; space_attr = FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_BLUE; for(i=0; i<WORLD_SIZE_Y; i++) for(j=0; j<WORLD_SIZE_X; j++) { map[i*WORLD_SIZE_X+j].Space = true; map[i*WORLD_SIZE_X+j].Food = false; map[i*WORLD_SIZE_X+j].Wall = false; map[i*WORLD_SIZE_X+j].Evil = false; map[i*WORLD_SIZE_X+j].Turn = false; } place_walls(); place_food(); place_evils(); place_pacman(); Game(); } bool WORLD_MAP::move(direction dir, int x, int y) { switch (dir) { case Up: if((map[(y-1)*WORLD_SIZE_X+x].Space) && (!map[(y-1)*WORLD_SIZE_X+x].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[(y-1)*WORLD_SIZE_X+x] = map[y*WORLD_SIZE_X+x]; map[(y-1)*WORLD_SIZE_X+x].Turn = true; paint(x, y-1); } else return false; break; case Down: if((map[(y+1)*WORLD_SIZE_X+x].Space) && (!map[(y+1)*WORLD_SIZE_X+x].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[(y+1)*WORLD_SIZE_X+x] = map[y*WORLD_SIZE_X+x]; map[(y+1)*WORLD_SIZE_X+x].Turn = true; paint(x, y+1); } else return false; break; case Left: if((map[y*WORLD_SIZE_X+x-1].Space) && (!map[y*WORLD_SIZE_X+x-1].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[y*WORLD_SIZE_X+x-1] = map[y*WORLD_SIZE_X+x]; map[y*WORLD_SIZE_X+x-1].Turn = true; paint(x-1, y); } else return false; break; case Right: if((map[y*WORLD_SIZE_X+x+1].Space) && (!map[y*WORLD_SIZE_X+x+1].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[y*WORLD_SIZE_X+x+1] = map[y*WORLD_SIZE_X+x]; map[y*WORLD_SIZE_X+x+1].Turn = true; paint(x+1, y); } else return false; break; } map[y*WORLD_SIZE_X+x].Food = false; map[y*WORLD_SIZE_X+x].Space = true; map[y*WORLD_SIZE_X+x].Evil = false; map[y*WORLD_SIZE_X+x].Turn = false; paint(x, y); return true; } int main() { WORLD_MAP the_very_game; return 0; }
А... как я понял, нельзя поточную функцию делать закрытым членом класса. Только глобально можно объявлять?
Antolflash Статический метод тоже можно использовать. А с некоторым извращением(см. листинг 2) можно запускать вообще любой метод в отдельном потоке.
Прошу прощения за плохой пример. Надо вот так) Код (Text): #include <windows.h> #include <iostream> class MY { static DWORD WINAPI MyThreadFunction(LPVOID lpParam); HANDLE hThread; public: MY(); ~MY(); }; MY::MY() { int j, i; LPVOID lpParam; //LPTHREAD_START_ROUTINE lpStartAdress; //lpStartAdress = (LPTHREAD_START_ROUTINE)&MY::MyThreadFunction; i = 0; lpParam = &i; //hThread = CreateThread(NULL, 0, lpStartAdress, lpParam, 0, NULL); hThread = CreateThread(NULL, 0, MyThreadFunction, lpParam, 0, NULL); for(j = 0; j < 15; j++) std::cout << j; } MY::~MY() { WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); } DWORD WINAPI MY::MyThreadFunction(LPVOID lpParam) { for(; ((int *)lpParam)[0] < 15; ((int *)lpParam)[0]++) std::cout << ((int *)lpParam)[0]; return 0; } int main() { std::cout << "MAIN"; MY my; return 0; }
Как сделать так, чтобы выполнение определённого куска кода в одном потоке было непрерывным? Т.е. главный поток и мой поток выполняются параллельно. Вдруг бац, пока полностью не выполнится заданный целостный кусок кода в главном потоке, мой поток не выполняется. Т.е. нужно что-то что выключает, а потом включает многопоточность.
Создай эвент (CreateEvent) и заюзай WaitForSingleObject. Тогда ты сможешь устанавливая эвент, включать процедуру, процедура выполнилась, выключила эвент, далее при новом выполнении ожидать прихода эвента. Можно это реализовать даже в процедуре потока, в цикле, чтобы не выходить из процедуры. Потом просто терминейтишь поток, когда он будет находиться в режиме ожидания.
Antolflash Ради такой ерунды создавать потоки? Жесть. Зачем ReadConsoleInput? getch, тем более, что соnio и так юзаете.
Вот, кстати, последний рабочий вариант. Код (Text): #include <iostream> #include <windows.h> #include <time.h> #include <math.h> #include <conio.h> // 174еда 0стена 164зло 169пак class MOVING_UNITS { protected: enum direction { Up, Right, Left, Down } dir; virtual bool move(direction dir, int x, int y) = 0; }; class WALL { protected: virtual void place_walls() = 0; unsigned char wall_smile; WORD wall_attr; int MAX_WALL_LENGTH; int NUMBER_OF_WALLS; WALL(); }; WALL::WALL() { MAX_WALL_LENGTH = 3; NUMBER_OF_WALLS = 4; wall_attr = FOREGROUND_BLUE | FOREGROUND_GREEN; wall_smile = 0; } class PACMAN : protected MOVING_UNITS { protected: virtual void place_pacman() = 0; unsigned char pacman_smile; WORD pacman_attr; PACMAN(); }; PACMAN::PACMAN() { pacman_smile = 169; pacman_attr = FOREGROUND_GREEN | BACKGROUND_RED; } class EVIL : protected MOVING_UNITS { protected: virtual void place_evils() = 0; virtual void intellect(int x, int y) = 0; int NUMBER_OF_EVILS; unsigned char evil_smile; WORD evil_attr; EVIL(); }; EVIL::EVIL() { evil_smile = 164; evil_attr = FOREGROUND_RED; NUMBER_OF_EVILS = 4; } class FOOD { protected: virtual void place_food() = 0; int NUMBER_OF_FOOD; unsigned char food_smile; WORD food_attr; int food_counter; FOOD(); }; FOOD::FOOD() { food_smile = 174; food_attr = FOREGROUND_BLUE | FOREGROUND_GREEN; NUMBER_OF_FOOD = 4; food_counter = 0; } class WORLD_MAP : protected WALL, protected PACMAN, protected EVIL, protected FOOD { int WORLD_SIZE_X, WORLD_SIZE_Y; struct WORLD_MAP_STRUCT { unsigned Wall: 1; unsigned Evil: 1; unsigned Turn: 1; unsigned Food: 1; unsigned Space: 1; } *map; struct PACMAN_COORDINATE { int _X_; int _Y_; } pac; static HANDLE hConsoleOutput; static HANDLE hConsoleInput; unsigned char space_smile; WORD space_attr; WORD prev_key; void place_walls(); void place_food(); void place_evils(); void place_pacman(); bool move(direction dir, int x, int y); void paint(int x, int y); int skip; int skip_c; DWORD SLEEP_TIME; void intellect(int x, int y); void Game(); void KeyEventProc(int x, int y); static DWORD WINAPI MyThreadFunction(LPVOID lpParameter); static bool terminator; static CRITICAL_SECTION CS; static HANDLE hThread; static bool win_loose; static INPUT_RECORD lpBuffer[128]; public: WORLD_MAP(); ~WORLD_MAP(); }; bool WORLD_MAP::terminator = true; HANDLE WORLD_MAP::hConsoleInput; HANDLE WORLD_MAP::hConsoleOutput; INPUT_RECORD WORLD_MAP::lpBuffer[128]; HANDLE WORLD_MAP::hThread; bool WORLD_MAP::win_loose; DWORD WINAPI WORLD_MAP::MyThreadFunction(LPVOID lpParameter) { DWORD lpNumberOfEventsRead; while(true){ if(terminator) PeekConsoleInput(hConsoleInput, (PINPUT_RECORD)lpParameter, 128, &lpNumberOfEventsRead); else { FreeConsole(); AllocConsole(); if(win_loose) std::cout << "You win!"; else std::cout << "You loose!"; CloseHandle(hThread); ExitThread(0); } } return 0; } void WORLD_MAP::intellect(int x, int y) { if(abs(x - pac._X_) > abs(y - pac._Y_)) { if(x > pac._X_) { if(move(Left, x, y)) ; else { if(move(Up, x, y)) ; else move(Down, x, y); } } else if(move(Right, x, y)) ; else { if(y > pac._Y_) { if(move(Up, x, y)) ; } else move(Down, x, y); } } // ******************************************************* else { if(y > pac._Y_) { if(move(Up, x, y)) ; else { if(move(Left, x, y)) ; else move(Right, x, y); } } else if(move(Down, x, y)) ; else { if(move(Left, x, y)) ; else move(Right, x, y); } } } void WORLD_MAP::paint(int x, int y) { COORD dwCursorPosition; WCHAR cCharacter; DWORD lpNumberOfCharsWritten; DWORD lpNumberOfAttrsWritten; WORD wAttribute; dwCursorPosition.X = x; dwCursorPosition.Y = y; if((x == pac._X_) && (y == pac._Y_)) { cCharacter = pacman_smile; wAttribute = pacman_attr; } else if((map[y*WORLD_SIZE_X+x].Space) && (map[y*WORLD_SIZE_X+x].Food) ) { cCharacter = food_smile; wAttribute = food_attr; } else if(map[y*WORLD_SIZE_X+x].Space) { cCharacter = space_smile; wAttribute = space_attr; } else if(map[y*WORLD_SIZE_X+x].Evil) { cCharacter = evil_smile; wAttribute = evil_attr; } else if(map[y*WORLD_SIZE_X+x].Wall) { cCharacter = wall_smile; wAttribute = wall_attr; } else return; FillConsoleOutputAttribute(hConsoleOutput, wAttribute, 1, dwCursorPosition, &lpNumberOfAttrsWritten); FillConsoleOutputCharacter(hConsoleOutput, cCharacter, 1, dwCursorPosition, &lpNumberOfCharsWritten); } void WORLD_MAP::KeyEventProc(int x, int y) { if(map[pac._Y_*WORLD_SIZE_X+pac._X_].Evil) { terminator = false; win_loose = false; } if(food_counter >= NUMBER_OF_FOOD) { terminator = false; win_loose = true; } //38вверх 37влево 40вниз 39вправо WCHAR smth = lpBuffer[0].Event.KeyEvent.wVirtualKeyCode; switch(smth) { case 38: prev_key = 38; if(map[(y-1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y-1)*WORLD_SIZE_X+x].Food = false; } pac._Y_--; if(!move(Up, x, y)) pac._Y_++; break; case 37: prev_key = 37; if(map[y*WORLD_SIZE_X+x-1].Food) { food_counter++; map[y*WORLD_SIZE_X+x-1].Food = false; } pac._X_--; if(!move(Left, x, y)) pac._X_++; break; case 39: prev_key = 39; if(map[y*WORLD_SIZE_X+x+1].Food) { food_counter++; map[y*WORLD_SIZE_X+x+1].Food = false; } pac._X_++; if(!move(Right, x, y)) pac._X_--; break; case 40: prev_key = 40; if(map[(y+1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y+1)*WORLD_SIZE_X+x].Food = false; } pac._Y_++; if(!move(Down, x, y)) pac._Y_--; break; default: switch(prev_key) { case 38: if(map[(y-1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y-1)*WORLD_SIZE_X+x].Food = false; } pac._Y_--; if(!move(Up, x, y)) pac._Y_++; break; case 37: if(map[y*WORLD_SIZE_X+x-1].Food) { food_counter++; map[y*WORLD_SIZE_X+x-1].Food = false; } pac._X_--; if(!move(Left, x, y)) pac._X_++; break; case 39: if(map[y*WORLD_SIZE_X+x+1].Food) { food_counter++; map[y*WORLD_SIZE_X+x+1].Food = false; } pac._X_++; if(!move(Right, x, y)) pac._X_--; break; case 40: if(map[(y+1)*WORLD_SIZE_X+x].Food) { food_counter++; map[(y+1)*WORLD_SIZE_X+x].Food = false; } pac._Y_++; if(!move(Down, x, y)) pac._Y_--; break; default: //std::cout << "AA"; break; } break; } FlushConsoleInputBuffer(hConsoleInput); for(y=0; y<WORLD_SIZE_Y; y++) for(x=0; x<WORLD_SIZE_X; x++) map[y*WORLD_SIZE_X+x].Turn = false; Sleep(SLEEP_TIME); skip_c++; if(!(skip_c % skip)) for(y=0; y<WORLD_SIZE_Y; y++) for(x=0; x<WORLD_SIZE_X; x++) if((map[y*WORLD_SIZE_X+x].Evil) && (!(map[y*WORLD_SIZE_X+x].Turn))) intellect(x, y); } void WORLD_MAP::Game() { int x, y; std::cout << "\nGame starts!"; FreeConsole(); AllocConsole(); hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); for(x=0; x<WORLD_SIZE_X; x++) for(y=0; y<WORLD_SIZE_Y; y++) paint(x, y); hThread = CreateThread(NULL, 0, MyThreadFunction, lpBuffer, 0, NULL); while(terminator) KeyEventProc(pac._X_, pac._Y_); if(!terminator) getch(); } void WORLD_MAP::place_pacman() { int x, y; std::cout << "\nGenerating pacman..."; srand(time(0)); do { x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); } while( !( (map[y*WORLD_SIZE_X+x].Space) && (!map[y*WORLD_SIZE_X+x].Food) ) ); pac._X_ = x; pac._Y_ = y; } void WORLD_MAP::place_food() { int x, y, i; std::cout << "\nGenerating food..."; srand(time(0)); for(i=0; i<NUMBER_OF_FOOD; i++) { x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); if(map[y*WORLD_SIZE_X+x].Space) map[y*WORLD_SIZE_X+x].Food = true; else i--; } } void WORLD_MAP::place_evils() { int x, y, i; std::cout << "\nGenerating evils..."; srand(time(0)); for(i=0; i<NUMBER_OF_EVILS; i++) { x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); if(map[y*WORLD_SIZE_X+x].Space && (!map[y*WORLD_SIZE_X+x].Food)) { map[y*WORLD_SIZE_X+x].Evil = true; map[y*WORLD_SIZE_X+x].Space = false; } else i--; } } void WORLD_MAP::place_walls() { int x, y, i, j; std::cout << "\nGenerating walls..."; for(i=0; i<NUMBER_OF_WALLS; i++) { srand(time(0)); x = abs( (rand()) % WORLD_SIZE_X ); y = abs( (rand()) % WORLD_SIZE_Y ); for(j=0; j<MAX_WALL_LENGTH; j++) { if((map[y*WORLD_SIZE_X+x].Space) && (!map[y*WORLD_SIZE_X+x].Food)) { map[y*WORLD_SIZE_X+x].Wall = true; map[y*WORLD_SIZE_X+x].Space = false; } else j--; x = abs( (rand()) > 16000 ? (x+1)%WORLD_SIZE_X : (x-1)%WORLD_SIZE_X ); y = abs( (rand()) > 16000 ? (y+1)%WORLD_SIZE_Y : (y-1)%WORLD_SIZE_Y ); } } } WORLD_MAP::WORLD_MAP() { int i, j; std::cout << "This is pacman!"; prev_key = 0; WORLD_SIZE_X = 30; WORLD_SIZE_Y = 20; terminator = true; skip = 4; skip_c = 0; SLEEP_TIME = 250; map = new WORLD_MAP_STRUCT [WORLD_SIZE_X*WORLD_SIZE_Y]; space_smile = 199; space_attr = FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_BLUE; for(i=0; i<WORLD_SIZE_Y; i++) for(j=0; j<WORLD_SIZE_X; j++) { map[i*WORLD_SIZE_X+j].Space = true; map[i*WORLD_SIZE_X+j].Food = false; map[i*WORLD_SIZE_X+j].Wall = false; map[i*WORLD_SIZE_X+j].Evil = false; map[i*WORLD_SIZE_X+j].Turn = false; } place_walls(); place_food(); place_evils(); place_pacman(); Game(); } WORLD_MAP::~WORLD_MAP() { delete map; } bool WORLD_MAP::move(direction dir, int x, int y) { switch (dir) { case Up: if((map[(y-1)*WORLD_SIZE_X+x].Space) && (!map[(y-1)*WORLD_SIZE_X+x].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[(y-1)*WORLD_SIZE_X+x] = map[y*WORLD_SIZE_X+x]; map[(y-1)*WORLD_SIZE_X+x].Turn = true; paint(x, y-1); } else return false; break; case Down: if((map[(y+1)*WORLD_SIZE_X+x].Space) && (!map[(y+1)*WORLD_SIZE_X+x].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[(y+1)*WORLD_SIZE_X+x] = map[y*WORLD_SIZE_X+x]; map[(y+1)*WORLD_SIZE_X+x].Turn = true; paint(x, y+1); } else return false; break; case Left: if((map[y*WORLD_SIZE_X+x-1].Space) && (!map[y*WORLD_SIZE_X+x-1].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[y*WORLD_SIZE_X+x-1] = map[y*WORLD_SIZE_X+x]; map[y*WORLD_SIZE_X+x-1].Turn = true; paint(x-1, y); } else return false; break; case Right: if((map[y*WORLD_SIZE_X+x+1].Space) && (!map[y*WORLD_SIZE_X+x+1].Food) && (y < WORLD_SIZE_Y) && (x < WORLD_SIZE_X)) { map[y*WORLD_SIZE_X+x+1] = map[y*WORLD_SIZE_X+x]; map[y*WORLD_SIZE_X+x+1].Turn = true; paint(x+1, y); } else return false; break; } map[y*WORLD_SIZE_X+x].Food = false; map[y*WORLD_SIZE_X+x].Space = true; map[y*WORLD_SIZE_X+x].Evil = false; map[y*WORLD_SIZE_X+x].Turn = false; paint(x, y); return true; } int main() { WORLD_MAP the_very_game; return 0; } А как реализовать постоянное движение пакмана иначе? Я потоки использовал, чтобы он при нажатиях клавишь лишь менял направление, а двигается он всегда. Какие есть замечания по коду, советы?
Antolflash омг. зачем такой страшный огород?.. например, добавляешь в WORLD_MAP список движущихся объектов, у которых есть метод move_self, в цикле вызываешь этот метод поочередно для каждого. соответственно, в цикле в первую очередь провяряешь нажаты/отпущены ли клавиши поворота, соответственно меняешь направления движения. как-то так.
Antolflash микрозамечание WORLD_MAP::~WORLD_MAP() { //delete map; delete[] map; } а вообще - множественное наследование типа class WORLD_MAP : protected WALL, protected PACMAN, protected EVIL, protected FOOD{ не загусто ли?