Программирование игры "Дурак" (карточная) на языке программирования С++

Заказать уникальную курсовую работу
Тип работы: Курсовая работа
Предмет: C++
  • 3232 страницы
  • 1 + 1 источник
  • Добавлена 11.01.2011
800 руб.
  • Содержание
  • Часть работы
  • Список литературы
  • Вопросы/Ответы
ЗАДАНИЕ НА ПРОЕКТИРОВАНИЕ
1. ПОСТАНОВКА ЗАДАЧИ
2. ОТОБРАЖЕНИЕ КАРТ
3. СТРУКТУРЫ ДАННЫХ
4. АЛГОРИТМ ОБРАБОТКИ ДЕЙСТВИЙ ИГРОКА-ЧЕЛОВЕКА
5. АЛГОРИТМ ДЕЙСТВИЙ ПРОГРАММНОГО ИГРОКА
6. ОРГАНИЗАЦИЯ ИГРОВОГО ЦИКЛА
7. СОЗДАНИЕ ПРИЛОЖЕНИЯ
8. ЗАКЛЮЧЕНИЕ
СПИСОК ЛИТЕРАТУРЫ
ПРИЛОЖЕНИЕ 1
ПРИЛОЖЕНИЕ 2


Фрагмент для ознакомления

Top=card->c.X; // прямоугольник для обмена
r.Left=card->c.Y;
r.Bottom=r.Top+3;
r.Right=r.Left+5;
WriteConsoleOutput(h,card->buf,size,coord,&r); // восстанавливаем стол из буфера
card->c.X=c.X; // перемещаем карту
card->c.Y=c.Y;
r.Top=card->c.X;
r.Left=card->c.Y;
r.Bottom=r.Top+3;
r.Right=r.Left+5;
ReadConsoleOutput(h,card->buf,size,coord,&r); // считываем новый участок стола
WriteConsoleOutput(h,card->cur,size,coord,&r); // выводим карту
}

void TurnCard(int t,struct CCard *card) // повернуть карту
{
if(t)
card->cur=card->avers; // лицом
else
card->cur=Revers; // рубашкой
}

void CreateRevers() // создание рубашки карты
{
// рубащке рисуем псевдографикой
// рамка черным по белому
// середина ярко-синим по белому
Revers[0].Char.AsciiChar=(unsigned char)218;
Revers[0].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[1].Char.AsciiChar=(unsigned char)196;
Revers[1].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[2].Char.AsciiChar=(unsigned char)196;
Revers[2].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[3].Char.AsciiChar=(unsigned char)196;
Revers[3].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[4].Char.AsciiChar=(unsigned char)191;
Revers[4].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[5].Char.AsciiChar=(unsigned char)179;
Revers[5].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[6].Char.AsciiChar=(unsigned char)177;
Revers[6].Attributes=FOREGROUND_INTENSITY|FOREGROUND_BLUE|BACKGROUND_RED|
BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[7].Char.AsciiChar=(unsigned char)177;
Revers[7].Attributes=FOREGROUND_INTENSITY|FOREGROUND_BLUE|BACKGROUND_RED|
BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[8].Char.AsciiChar=(unsigned char)177;
Revers[8].Attributes=FOREGROUND_INTENSITY|FOREGROUND_BLUE|BACKGROUND_RED|
BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[9].Char.AsciiChar=(unsigned char)179;
Revers[9].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[10].Char.AsciiChar=(unsigned char)192;
Revers[10].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[11].Char.AsciiChar=(unsigned char)196;
Revers[11].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[12].Char.AsciiChar=(unsigned char)196;
Revers[12].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[13].Char.AsciiChar=(unsigned char)196;
Revers[13].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
Revers[14].Char.AsciiChar=(unsigned char)217;
Revers[14].Attributes=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
}

void CreateArrow() // создание стрелки
{
COORD size,coord;
SMALL_RECT r;

size.X=1; // размер
size.Y=1;
coord.X=0; // координаты в буфере
coord.Y=0;
r.Top=0; // прямоугольник для обмена
r.Left=0;
r.Bottom=1;
r.Right=1;
arr.pic.Char.AsciiChar=(unsigned char)'^'; // собственно стрелка желтым по зеленому
arr.pic.Attributes=FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|
BACKGROUND_GREEN;
ReadConsoleOutput(h,&arr.buf,size,coord,&r);// считываем подстилающий прямоугольник
}

void MoveArrow(COORD c) // перемещение стрелки
{
COORD size,coord;
SMALL_RECT r;

size.X=1; // размер
size.Y=1;
coord.X=0; // координаты в буфере
coord.Y=0;
r.Top=arr.c.X; // прямоугольник для обмена
r.Left=arr.c.Y;
r.Bottom=r.Top+1;
r.Right=r.Left+1;
// восстанавливаем поверхность из буфера
WriteConsoleOutput(h,&arr.buf,size,coord,&r);
arr.c.X=c.X; // координаты стрелки
arr.c.Y=c.Y;
r.Top=arr.c.X; // прямоугольник для обмена
r.Left=arr.c.Y;
r.Bottom=r.Top+1;
r.Right=r.Left+1;
ReadConsoleOutput(h,&arr.buf,size,coord,&r);// считываем подстилающий прямоугольник
WriteConsoleOutput(h,&arr.pic,size,coord,&r);// выводим стрелку в новом положении
}

void FillRect(COORD c,COORD d,int att) // заполнить прямоугольник
{
COORD size,coord;
SMALL_RECT r;
CHAR_INFO *rect;
int i,num;

num=d.X*d.Y; // вычисляем размер прямоугольника
rect=new CHAR_INFO[num]; // выделяем память
for(i=0; i < num; i++){
// заполняем пробелами с нужным атрибутом
rect[i].Char.AsciiChar=(unsigned char)' ';
rect[i].Attributes=att;
}
size.X=d.X; // размер
size.Y=d.Y;
coord.X=0; // координаты в буфере
coord.Y=0;
r.Top=c.X; // прямоугольник для обмена
r.Left=c.Y;
r.Bottom=r.Top+d.X;
r.Right=r.Left+d.Y;
WriteConsoleOutput(h,rect,size,coord,&r);// закрашиваем прямоугольник
delete[] rect;
}

int MessageAsk(char *l1, char *l2,char **a, int n) // меню
{
COORD size,coord,c,c_arr;
SMALL_RECT r;
CHAR_INFO buf[180];
CHAR_INFO rect[180];
DWORD written;
int alt=0;
char in;
int i;

size.X=30; // устанавливаем размеры меню
size.Y=6;
coord.X=0; // координаты в буфере
coord.Y=0;
r.Top=9; // прямоугольник для обмена
r.Left=25;
r.Bottom=r.Top+7;
r.Right=r.Left+30;
ReadConsoleOutput(h,buf,size,coord,&r); // считываем подстилающую поверхность
for(i=0; i < 180; i++){ // заполняем пробелами синего цвета
rect[i].Char.AsciiChar=(unsigned char)' ';
rect[i].Attributes=BACKGROUND_BLUE;
}
WriteConsoleOutput(h,rect,size,coord,&r); // выводим синий прямоугольник
c.X=27; // координаты первой строки
c.Y=10;
SetConsoleCursorPosition(h,c); // устанавливаем позицию
WriteConsole(h,(CONST VOID *)l1,strlen(l1),&written,NULL); // выводим строку
c.Y=11; // координаты второй строки
SetConsoleCursorPosition(h,c); // устанавливаем позицию
WriteConsole(h,(CONST VOID *)l2,strlen(l2),&written,NULL); // выводим строку
c.Y=13; // строка для размещения альтернатив
for(i=0; i < n; i++){ // выводим альтернативы
c.X=27+6*i; // позиция для вывода
SetConsoleCursorPosition(h,c); // устанавливаем позицию
WriteConsole(h,(CONST VOID *)a[i],strlen(a[i]),&written,NULL); // выводим альтернативу
}
c_arr.X=14; // позиция для перемещения стрелки
for(;;){
c_arr.Y=27+6*alt; // позиция для вывода
MoveArrow(c_arr); // перемещение стрелки
in=getch(); // ждем ввода
if(in == 13){ // нажат Enter
c_arr.X=0;
c_arr.Y=0;
MoveArrow(c_arr); // убираем стрелку
WriteConsoleOutput(h,buf,size,coord,&r);// восстанавливаем поверхность
return(alt); // возвращаем выбор
}
if(in == -32){ // это стрелка
in=getch(); // дочитываем еще один символ
if(in == 77){ // стрелка вправо
if(alt+1 < n) // наращиваем позицию стрелки с учетом предела
alt++;
}
else if(in ==75){ // стрелка влево
if(alt > 0) // уменьшаем позицию стрелки с учетом предела
alt--;
}
}
}
}

void OnButton1() // Кнопка "OK"/"Бито"/"Все"/"Беру"
{
if(take) // компьютер сказал "беру", кнопка называется "все"
next=1; // устанавливаем призна "все"
else
if(turn == 0) // это ход человека, кнопка называется "бито"
next=1; // устанавливаем признак "все"
else // это ход компьютера, кнопка называется "беру"
take=1; // устанавливаем признак "беру"
}

void OnLButtonUp(int num) // Реакция на выбор карты
{
int i;
list::iterator cur;
list::reverse_iterator curxa;

for(cur=pls[0].player.begin(),i=0; cur != pls[0].player.end(); cur++,i++) // ищем окно с таким описателем среди карт
if(i == num)
break;
if(turn == 0){ // если ход на стороне человека
// поле атаки пусто - кидаем первую карту,которую выбрал человек без ограничений
if(playattack.size() == 0){
toAttack(0,cur);
return;
}
// если карта не первая, учитываем ограничения (не более 6 отбоев)
else if(playattack.size() < 6){
if(titleExist(Card[*cur].title)){ // такой титул найден в игровых полях
toAttack(0,cur); // кидаем выбранную карту на поле атаки
return;
}
}
else{
next=1; // устанавливаем признак "все"
return;
}
}
else{ // если ход на стороне компьютера
// определяем последнюю карту, которую кинул компьютер
curxa=playattack.rbegin();
// выбранная карта может побить ее
if(Card[*cur].title > Card[*curxa].title &&
Card[*cur].suit == Card[*curxa].suit ||
Card[*cur].suit == trump && Card[*curxa].suit != trump){
toDefend(0,cur); // кидаем выбранную карту на поле защиты
return;
}
}
}

void compPlay(){ // Компьютерный игрок
list::iterator cur;
list::iterator curx;
list::reverse_iterator cury;
int title;

if(call == turn){ // атака
curx=NULL; // ищем подходящую карту
title=15;
if(playattack.size() == 0){ // это первая карта на игровых полях
for(cur=pls[call].player.begin(); cur != pls[call].player.end(); cur++){
// ищем минимальную некозырную карту
if(Card[*cur].suit != trump && Card[*cur].title < title){
title=Card[*cur].title;
curx=cur;
}
}
// некозырных не оказалось
if(curx == NULL)
for(cur=pls[call].player.begin(); cur != pls[call].player.end(); cur++){
// ищем минимальную козырную карту
if(Card[*cur].suit == trump && Card[*cur].title < title){
title=Card[*cur].title;
curx=cur;
}
}
}
else if(playattack.size() < 6){ // это не первая карта на игровых полях
// ищем минимальную некозырную карту с титулом, имеющимся на игровом поле
for(cur=pls[call].player.begin(); cur != pls[call].player.end(); cur++){
// карты с таким титулом есть на игровом поле
if(titleExist(Card[*cur].title) &&
Card[*cur].suit != trump && Card[*cur].title < title){
title=Card[*cur].title;
curx=cur;
}
}
// некозырных не оказалось
if(curx == NULL)
// ищем минимальную козырную карту
for(cur=pls[call].player.begin(); cur != pls[call].player.end(); cur++){
// карты с таким титулом есть на игровом поле
if(titleExist(Card[*cur].title) &&
Card[*cur].suit == trump && Card[*cur].title < title){
title=Card[*cur].title;
curx=cur;
}
}
}
else
next=1;
if(curx != NULL) // подходящая карта нашлась
toAttack(call,curx); // помещаем найденную карту в поле атаки
else
next=1; // устанавливаем признак "все"
}
else{ // защита
cury=playattack.rbegin();
curx=NULL;
title=15;
// ищем минимальную некозырную карту для отбоя
for(cur=pls[call].player.begin(); cur != pls[call].player.end(); cur++){
if(Card[*cur].title > Card[*cury].title &&
Card[*cur].suit == Card[*cury].suit &&
Card[*cur].title < title){
title=Card[*cur].title;
curx=cur;
}
}
if(curx == NULL) // некозырных не оказалось
// ищем минимальную козырную карту для отбоя
for(cur=pls[call].player.begin(); cur != pls[call].player.end(); cur++){
if(Card[*cur].suit == trump && Card[*cury].suit != trump &&
Card[*cur].title < title){
title=Card[*cur].title;
curx=cur;
}
}

if(curx != NULL) // подходящая карта нашлась
toDefend(call,curx);
else
take=1; // устанавливаем признак "беру"
}
}

// Функция генерации случайных чисел
ptrdiff_t random(ptrdiff_t i)
{
return rand()%i;
}
// указатель на генератор для random_shuffle
ptrdiff_t (*p_random)(ptrdiff_t)=random;

void ShuffleDeck() // Тасование карт, формирование колоды и определение козыря
{
int i;
vector vdeck;
vector::iterator curv;
list::reverse_iterator curc;
COORD c;

c.X=7; // место расположения колоды в окне
c.Y=2;
playattack.clear(); // очищаем поле нападения
playdefend.clear(); // очищаем поле защиты
for(i=0; i < 6; i++)
pls[i].player.clear(); // очищаем карты на руках у игроков
refuse.clear(); // очищаем отбой
deck.clear(); // очищаем колоду (при тасовке колода формируется заново,
// это связано с особенностями алгоритма random_shuffle)
for(i=0; i < 36; i++){
TurnCard(0,&Card[i]); // переворачиваем карты рубашкой вверх
vdeck.push_back(i); // вносим их номера в вектор
}
srand((unsigned)time(NULL)); // инициализируем датчик случайных чисел
random_shuffle(vdeck.begin(),vdeck.end(),p_random);// тасуем вектор с номерами карт
// переносим элементы вектора в список колоды
for(curv=vdeck.begin(); curv != vdeck.end(); curv++)
deck.push_back(*curv);
vdeck.clear(); // очищаем вектор
// размещаем колоду на игровом поле
for(curc=deck.rbegin(),i=0; curc != deck.rend(); curc++){
if(i == 0){
TurnCard(1,&Card[*curc]); // первую карту кладем картинкой вверх
trump=Card[*curc].suit; // по ее масти устанавливаем козырь
}
MoveCard(c,&Card[*curc]);
if(i == 0){
i=1;
c.Y += 2; // смещение колоды относительно козыря
}
}
}

void TakeCards(){ // Раздача карт
list::reverse_iterator curc;
int pos;

for(int j=0; j < 6; j++){
pos=nextPlayer(j); // раздача начиная с того, у кого сейчас ход
// до шести карт пока есть карты в колоде
while(pls[pos].player.size() < 6 && deck.size() > 0)
pls[pos].player.splice(pls[pos].player.begin(),deck,deck.begin());
layoutCards(pos,pls[pos].open); // выкладываем карты на поле
}
}
void toAttack(int pl,list::iterator crd){ // Помещение карты в поле атаки
COORD c;

playattack.splice(playattack.end(),pls[pl].player,crd);
c.Y=12+7*(playattack.size()-1); // координаты размещения на игровом поле
c.X=9;
TurnCard(1,&Card[*crd]); // лицом вверх
MoveCard(c,&Card[*crd]);
}
void toDefend(int pl,list::iterator crd){ // Помещение карты в поле защиты
COORD c;

playdefend.splice(playdefend.end(),pls[pl].player,crd);
c.Y=13+7*(playdefend.size()-1); // координаты размещения на игровом поле
c.X=13;
TurnCard(1,&Card[*crd]); // лицом вверх
MoveCard(c,&Card[*crd]);
}
void layoutCards(int pl,int t){ // Разложить карты игрока
list::iterator curc;
COORD c,d;

d.X=6;
d.Y=4;
c.Y=10; // начальное смещение по y
if(pl == 0){ // этот игрок - человек
c.X=20; // смещение по x
for(curc=pls[pl].player.begin(); curc != pls[pl].player.end(); curc++){
FillRect(c,d,BACKGROUND_GREEN);
TurnCard(t,&Card[*curc]);
MoveCard(c,&Card[*curc]);
c.Y += 6;
}
}
else{ // компьютерный игрок
c.X=2; // смещение по y
if(Pl == 2){ // игроков всего два - располагаем карты компьютерного игрока свободно
for(curc=pls[pl].player.begin(); curc != pls[pl].player.end(); curc++){
FillRect(c,d,BACKGROUND_GREEN);
TurnCard(t,&Card[*curc]);
MoveCard(c,&Card[*curc]);
c.Y += 6;
}
}
else{ // игроков более двух - располагаем карты колодой
c.Y += (pl-1)*15;
for(curc=pls[pl].player.begin(); curc != pls[pl].player.end(); curc++){
FillRect(c,d,BACKGROUND_GREEN);
TurnCard(t,&Card[*curc]);
MoveCard(c,&Card[*curc]);
}
}
}
}

void refuseCards(){ // Сформировать отбой
list::reverse_iterator curc;
COORD c;

c.X=14; // смещение расположения колоды отбоя
c.Y=3;
for(curc=refuse.rbegin(); curc != refuse.rend(); curc++){
TurnCard(0,&Card[*curc]);
MoveCard(c,&Card[*curc]);
}
}

// Проверка, имеются ли на игровом поле карты с указанным титулом
int titleExist(int title)
{
list::iterator cura;
list::iterator curd;

// есть ли карты с таким титулом на поле атаки?
for(cura=playattack.begin(); cura != playattack.end(); cura++)
if(title == Card[*cura].title)
break;
// есть ли карты с таким титулом на поле защиты?
for(curd=playdefend.begin(); curd != playdefend.end(); curd++)
if(title == Card[*curd].title)
break;
return cura != playattack.end() || curd != playdefend.end();
// есть ли карты с таким титулом на игровом поле
}

int nextPlayer(int offset) // Вычисление номера игрока, следующего за ходящим
{ // с учетом цикличности и признака существования
int pos;

pos=turn;
if(pos < 0)
pos=0;
for(int j=0; j < offset; j++){
do{
pos++;
if(pos > 5)
pos=0;
}while(!pls[pos].exist);
}
return pos;
}











22

1.Б. Страуструп Язык программирования C++. Специальное издание.– СПб.: "Невский Диалект", 2001.–1099 с.

Вопрос-ответ:

Какую задачу нужно решить при программировании игры "Дурак"?

В статье рассказывается о задачах и шагах, необходимых для создания игры "Дурак" с использованием языка программирования С. Основной задачей является разработка алгоритмов обработки действий игроков, отображения карт и организации игрового цикла.

Как осуществляется отображение карт в игре "Дурак"?

Для отображения карт используется функция WriteConsoleOutput, которая записывает символы и цвета в прямоугольную область консоли. В статье описывается, как создать и заполнять буфер символов для отображения карты, а также как задавать позицию отображения на консоли.

Какие структуры данных используются при программировании игры "Дурак"?

Для хранения и управления картами и игровыми данными используются различные структуры данных, такие как массивы и структуры. В статье описывается, как проектировать и использовать эти структуры для обеспечения правильной организации игры.

Какие алгоритмы обработки действий игрока и компьютера используются в игре "Дурак"?

Статья рассказывает о разработке алгоритмов для обработки действий игрока и компьютера. Для игрока описывается алгоритм выбора карты для хода, а для компьютера - алгоритм выбора карты для атаки и защиты. Эти алгоритмы основаны на правилах игры и предусматривают различные стратегии игры.

Как организован игровой цикл в игре "Дурак"?

В статье описывается, как организовать игровой цикл, который будет выполняться до окончания игры. Он включает в себя обработку действий игроков и компьютера, отображение карт и проверку условия окончания игры. Игровой цикл продолжается, пока игроки не разыграют все карты.

Какой язык программирования используется для создания игры "Дурак"?

Для создания игры "Дурак" используется язык программирования С.

Какие задачи нужно решить при проектировании игры "Дурак"?

При проектировании игры "Дурак" нужно решить задачи постановки задачи, отображения карт, организации игрового цикла и создания приложения.

Какие структуры данных используются в игре "Дурак"?

В игре "Дурак" используются структуры данных, такие как списки, массивы и стеки, которые позволяют хранить и обрабатывать информацию о картах и игровом состоянии.

Как обрабатываются действия игрока в игре "Дурак"?

Действия игрока в игре "Дурак" обрабатываются с помощью алгоритма обработки действий пользователя. Этот алгоритм определяет действия, которые игрок может совершить, и производит соответствующие изменения в игровом состоянии.

Как работает алгоритм действий программного игрока в игре "Дурак"?

Алгоритм действий программного игрока в игре "Дурак" основывается на различных стратегиях и правилах игры. Программный игрок анализирует текущую игровую ситуацию, выбирает оптимальный ход и совершает соответствующие действия.