Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.04.2017, 07:03   #1
KAMLS
Форумчанин
 
Регистрация: 09.04.2017
Сообщений: 598
По умолчанию Оптимизация.

Здравствуйте!
Я решил пример по книге Р.Лафоре. Часть примера приводится в ходе предоставления материала, а часть - это задание из "Упражнений".
Моей задачей было, разделить перемешанную колоду карт между 4 игроками в бридж. А после вывести на экран поделенную колоду.
Хотелось бы узнать, можно ли как-либо уменьшить код, оптимизировать, в части именно разделения колоды карт между 4 игроками?
Код:
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<conio.h>
using namespace std;
enum Suit{clubs, diamonds, hearts, spades};
const int jack=11;
const int queen=12;
const int king=13;
const int ace=14;
class card
{
private:
	int number;
	Suit suit;
public:
	card()
	{}
	void set(int n, Suit s)
	{ suit=s; number=n;}
	void display();
};
void card ::display()
{
	if(number>=2 && number <=10)
		cout<<number;
	else 
	{
		switch(number)
		{
		case jack: cout<<'J'; break;
		case queen: cout<<'Q'; break;
		case king: cout<<'K'; break;
		case ace: cout<<'A'; break;
		}
	}
	switch (suit)
	{
	case clubs: cout<<static_cast<char>(5); break;
	case diamonds: cout<<static_cast<char>(4); break;
	case hearts: cout<<static_cast<char>(3); break;
	case spades: cout<<static_cast<char>(6); break;
	}
}
int main ()
{
	setlocale(LC_ALL,"rus");
	card deck[52];
	card ch1[13], ch2[13], ch3[13], ch4[13];
	int j,a=0,b=0,c=0,d=0;
	cout<<endl;
	for(j=0; j<52; j++)
	{
		int num=(j%13)+2;
		Suit su=Suit(j/13);
		deck[j].set(num,su);
	}
	cout<<"Исходная колода:\n";
	for(j=0; j<52; j++)
	{
		deck[j].display();
		cout<<" ";
		if(!((j+1)%13))
			cout<<endl;
	}
	srand(time(NULL));
	for(j=0; j<52; j++)
	{
		int k=rand()%52;
		card temp=deck[j];
		deck[j]=deck[k];
		deck[k]=temp;
	}
	cout<<"Перемешанная колода:\n";
	for(j=0; j<52; j++)
	{
		deck[j].display();
		cout<<" ";
		if(!((j+1)%13))
			cout<<endl;
	}
	//деление колоды на 4 части
	for(j=0; j<52; j++)
	{
		if(j<=12)
		{
			ch1[a]=deck[j];
			a++;
		}
		else
		if(j>12 && j<=25)
		{
			ch2[b]=deck[j];
			b++;
		}
		else
		if(j>25 && j<=38)
		{
			ch3[c]=deck[j];
			c++;
		}
		else
		if(j>38 && j<=52)
		{
			ch4[d]=deck[j];
			d++;
		}
	}
	cout<<"\nПервый игрок:\n";
	for(j=0; j<=12; j++)
	{
		ch1[j].display();
		cout<<" ";
	}
	cout<<endl;
	cout<<"Второй игрок:\n";
	for(j=0; j<=12; j++)
	{
		ch2[j].display();
		cout<<" ";
	}
	cout<<endl;
	cout<<"Третий игрок:\n";
	for(j=0; j<=12; j++)
	{
		ch3[j].display();
		cout<<" ";
	}
	cout<<endl;
	cout<<"Четвертый игрок:\n";
	for(j=0; j<=12; j++)
	{
		ch4[j].display();
		cout<<" ";
	}
	getch();
	return 0;
}
______________________
Используйте тег [CODE] (кнопка с решеткой # в форме сообщения) при вставке кода на форум.

Последний раз редактировалось Alex11223; 24.04.2017 в 08:13.
KAMLS вне форума Ответить с цитированием
Старый 24.04.2017, 08:27   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Цитата:
Сообщение от KAMLS Посмотреть сообщение
можно ли как-либо уменьшить код
Каждую обработку массивов chX можно вынести в функцию с параметрами.
waleri вне форума Ответить с цитированием
Старый 24.04.2017, 08:56   #3
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Код:
#include<vector>
#include<array>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<ctime>


using namespace std;
enum Suit{clubs, diamonds, hearts, spades};
const int jack=11;
const int queen=12;
const int king=13;
const int ace=14;
class card
{
private:
	int number;
	Suit suit;
public:
	card()
	{}
    card(int n, Suit s)
    {
        set(n, s);
    }
	void set(int n, Suit s)
	{ suit=s; number=n;}
	void display() const; //важное дополнение const, позволяет дальше вызывать дисплей, для const объектов
};
void card ::display() const
{
	if(number>=2 && number <=10)
		cout<<number;
	else 
	{
		switch(number)
		{
		case jack: cout<<'J'; break;
		case queen: cout<<'Q'; break;
		case king: cout<<'K'; break;
		case ace: cout<<'A'; break;
		}
	}
	switch (suit)
	{
	case clubs: cout<<static_cast<char>(5); break;
	case diamonds: cout<<static_cast<char>(4); break;
	case hearts: cout<<static_cast<char>(3); break;
	case spades: cout<<static_cast<char>(6); break;
	}
}

using hand_t    = std::vector<card>; //вектор карт, это как бы массив переменной длины

//массив фиксированой длины из векторов, в отличие от обычного массива, может давать итераторы для стандартных алгоритмов
//это замена авторских card ch1[13], ch2[13], ch3[13], ch4[13];
//раз есть номера - то это уже массив из массивов быть должен (у нас из векторов, что круче, можно раздавать 2 колоды сразу без изменений программы)
using players_t = std::array<hand_t, 4>;

//можно сделать даже так
//using players_t = std::vector<hand_t>;
//в таком варианте игроков может быть не строго 4

//функция - печать (почти авторская)
void print_hand(const hand_t& what)
{
        //а здесь "трюк" sz = what.size(); j < sz, проверка условия вычисляется при каждом проходе цикла, мы не знаем, как много времени size(), может занять, но он не менятеся в процессе, поэтому мы его "оптимизируем"
        for(size_t j=0, sz = what.size(); j < sz; ++j) //j < sz evaluated on each step, so doing sz = what.size() will speedup
	{
		what.at(j).display(); //используем at, вместо [], т.к. дает const iterator
		cout<<" ";
		if(!((j+1)%13))
			cout<<endl;
	}
}

//функция - перемешатор
void shuffle(hand_t& what)
{
    for(size_t j=0, sz = what.size(); j < sz; ++j) 
	{
		int k=rand()%sz;
                std::swap(what[j], what[k]);		
	}
}


int main ()
{
	setlocale(LC_ALL,"rus");
	srand(time(NULL));
    
        hand_t    deck;
	players_t players;
    
        cout<<endl;
        deck.reserve(52); //ускоряем добавление элементов, говорим, что памяти нам понадобится на 52
	for(size_t i = 0; i < 52; ++i)
		deck.push_back(card( (i%13)+2, Suit(i/13) )); //добавляем элементы, а память уже есть, но там еще нет карт
	
	cout<<"Исходная колода:\n";
	print_hand(deck);    
	
	cout<<"Перемешанная колода:\n";
      	shuffle(deck);
        print_hand(deck);    
	
    //деление колоды на 4 части
    for (size_t i = 0, hand_sz = deck.size() / players.size(); i < players.size(); ++i) //for std::array method size() is constant, so can use directly on each step
    {
        players[i].resize(hand_sz); //создаем 12 пустых карт игрока (в отличие от reserve, который только резервирует память)
        //copy принимает 3 параметра - откуда_начало, откуда_конец, куда_начало (все итераторы)
        std::copy(deck.begin() + i * hand_sz, deck.begin() + (i + 1) * hand_sz, players[i].begin());
        cout << std::endl << i + 1 << "й игрок:" << std::endl;
        print_hand(players[i]);
    }
    	deck.clear(); //очищаем колоду - в банке карт теперь нет
        cin.ignore(); //ждем нажатия ENTER, авторский getch работает только на windows
	return 0;
}
Обратите внимание: массивы заменены на контейнеры std::vector, std::array, что позволяет избавится от магических чисел 56, 12, а так же использовать стандартные алгоритмы вроде std::copy (на самом деле, там еще удобнее с лямбдами, но требует С++11).
Вообще использование стандартных контейнеров и алгоритмов предпочтительнее циклов и массивов, т.к. позволяют компилятору четка предсказывать ошибки + 1 легким #define могут превратить "цикл" в параллельный на все процессоры системы.

Последний раз редактировалось alexzk; 24.04.2017 в 10:23.
alexzk вне форума Ответить с цитированием
Старый 24.04.2017, 10:21   #4
KAMLS
Форумчанин
 
Регистрация: 09.04.2017
Сообщений: 598
По умолчанию

Спасибо Вам большое. Я изучу Ваш код. Однако я до контейнеров еще не дошел. Приступил только к теме преобразование типов и перегрузка операций. ))Мой визуал выдает ошибку на 114 строке. Не могу скриншот прикрепить. Визуал 2008, Ваш наверное новее.
[IMG]file:///C:/Documents%20and%20Settings/Admin/Мои%20документы/Мои%20рисунки/кадр_4.jpg[/IMG]

Последний раз редактировалось KAMLS; 24.04.2017 в 10:32. Причина: Не могу прикрепить скриншот
KAMLS вне форума Ответить с цитированием
Старый 24.04.2017, 10:27   #5
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от KAMLS Посмотреть сообщение
Спасибо Вам большое. Я изучу Ваш код. Однако я до контейнеров еще не дошел. Приступил только к теме преобразование типов и перегрузка операций. ))
Ну...контейнеры то такое, удобства. У вас ключевая ошибка была
card ch1[13], ch2[13], ch3[13], ch4[13];

это нада было делать как массив из массивов и обрабатывать так же в цикле. Раз возникла нумерация ch1, ch2 ... то логично, что это массив.
В моем примере std::copy это спрятанный цикл.. для ваших массив из массивов были бы вложеные
for (i...)
{
for(j)
{
}
}

И второй момент - привыкайте на каждый чих определять тип, как у меня вон

using hand_t = std::vector<card>; //вектор карт, это как бы массив переменной длины
using players_t = std::array<hand_t, 4>;

Тогда не запутаетесь + можно удобно его изменить на другой какой-то, без глобального переделывания кода.
...я там комментов в код подаписал, обновите себе...

Последний раз редактировалось alexzk; 24.04.2017 в 10:33.
alexzk вне форума Ответить с цитированием
Старый 24.04.2017, 10:42   #6
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Это какая ? std::copy ошибка?
...у меня вообще g++

alex@moy-super:~/Work/tests$ ./a.out

Исходная колода:
2 3 4 5 6 7 8 9 10 J Q K A
2 3 4 5 6 7 8 9 10 J Q K A
2 3 4 5 6 7 8 9 10 J Q K A
2 3 4 5 6 7 8 9 10 J Q K A
Перемешанная колода:
K 7 7 6 3 9 8 4 4 10 9 10 8
Q 2 J A K K 2 2 9 8 3 5 4
3 A Q Q 10 10 6 J J 2 Q 5 7
K 6 4 3 A 5 9 A 5 J 8 6 7

1й игрок:
K 7 7 6 3 9 8 4 4 10 9 10 8

2й игрок:
Q 2 J A K K 2 2 9 8 3 5 4

3й игрок:
3 A Q Q 10 10 6 J J 2 Q 5 7

4й игрок:
K 6 4 3 A 5 9 A 5 J 8 6 7

Скопируйте текст ошибки....

Последний раз редактировалось alexzk; 24.04.2017 в 10:46.
alexzk вне форума Ответить с цитированием
Старый 24.04.2017, 10:56   #7
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
привыкайте на каждый чих определять тип, как у меня вон
это ж холиварный вопрос, многие наоборот считают, что в большинстве случаев так не стоит делать: сложнее читать код, придется постоянно смотреть что это, чтобы понять что с ним можно делать и т.п.

это ж просто алиас, а не тип.
Он не запрещает например присвоить одно другому если исходные типы это позволяют.

Цитата:
Сообщение от KAMLS Посмотреть сообщение
Не могу скриншот прикрепить. Визуал 2008, Ваш наверное новее.
[IMG]file:///C:/Documents%20and%20Settings/Admin/Мои%20документы/Мои%20рисунки/кадр_4.jpg[/IMG]
конечно нельзя дать ссылку на файл на вашем компе, если б это было возможно, то любой мог бы получить доступ к любому вашему файлу )
Надо или загрузить вложение на форум http://www.programmersforum.ru/showthread.php?t=238320, или на сторонний хостинг и дать ссылку.

Но скриншотить ошибки вообще не надо, можно ж просто скопировать текст ошибки (либо Ctrl+C в окне ошибок, либо в окне Output).
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 24.04.2017 в 11:11.
Alex11223 вне форума Ответить с цитированием
Старый 24.04.2017, 11:06   #8
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
это ж холиварный вопрос, многие наоборот считают, что в большинстве случаев так не стоит делать: сложнее читать код, придется постоянно смотреть что это, чтобы понять что с ним можно делать и т.п.

это ж просто алиас, а не тип.
Он не запрещает например присвоить одно другому если исходные типы это позволяют.
Первый раз слышу про холивар...и что, что алиас? Тут вам не ява, я могу сделать

struct some
{
size_t size() const
}

ну и все остальные методы, и тудысь впихнуть в typedef, или шаблон какой еще ... и оно скомпилится, как так и нада (если я определю, все использованые "названия"). Вопщем, давайте говорящие имена типам и не парте моск, как по мне

Вот на яве 2 одинаковых опр. с разными названиями будут совсем разные типы... а в С++ в том и сила, что потом можно менять и не парится

QList<int> на std::vector<int>

...вы вообще пробовали в сотне файлов с макросами сменить some* на std::shared_ptr<some> ? А я пробовал. Мой выбор - алиасить каждый чих) (можно приватно в классе).

Последний раз редактировалось alexzk; 24.04.2017 в 11:11.
alexzk вне форума Ответить с цитированием
Старый 24.04.2017, 11:14   #9
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Так я про typedef/using, где там тип?


Цитата:
Сообщение от alexzk Посмотреть сообщение
что потом можно менять и не парится

QList<int> на std::vector<int>
так у них же разные методы + работают по-разному, COW и т.п.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 24.04.2017, 11:19   #10
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Так я про typedef/using, где там тип?



так у них же разные методы + работают по-разному, COW и т.п.
Нет, QList поддерживает интерфейс стд. Так что, если писать интерфейсом стд - то все норм и заменяемо.

Про using ...ну да, это алиас как не крути. Но тем он и хорош, что алиас везде дальше пользуется, а "заалиасить" потом че угодно можно, абы интерфейс совпал. Блин, с такими вашими рассужденями, давайте магические числа писать, чо их алиас-константить.
Дибилов в мире С/С++ валом. Хорошо, что их SIGSEGV быстро на землю спускает, в отличие от JavaScript. Вон их в Qt набежало. Я у себя в продакшине 5.6 заморозил, дальше нельзя - сплошной баг на дев машине (5.8, 5.9). У меня прога старательно на std построена, кроме интерфейсов, где удобнее кт, собссно ядро без гуя для сервака компилится без кт. Так вот, на 5.6 работало, на 5.8 сплошные сиги...внтури кт, типа вдруг нельзя qml хостеру ставить самого себе property и прочее.

..блин, да я даже КДЕ снес после апдейта на 5.8 стали сплошные ошибки гуя кругом - того нет, то не сработало ...поставил lxqt на виджетах, без qml.

Последний раз редактировалось alexzk; 24.04.2017 в 11:27.
alexzk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Оптимизация htior Помощь студентам 0 25.01.2013 18:50
Оптимизация Красноглаз Паскаль, Turbo Pascal, PascalABC.NET 2 29.09.2011 11:16
Оптимизация... MikeMNN Общие вопросы C/C++ 0 15.12.2010 17:40
Оптимизация Alex Cones Общие вопросы Delphi 9 07.07.2010 08:47
Оптимизация Viper1287 Операционные системы общие вопросы 7 13.09.2009 15:33