티스토리 뷰

Stack을 이용한 자료구조 과제.


Solitaire 게임이라면...아주 전형적인 Stack 사용 예제 아닌가??


하면서도 되게 흥미로웠던 기억이 있어서 약간 정리 안된 코드지만


올려봐야지




#include<iostream>
#include<vector>
#include<string>
#include<cstdlib>
#include<time.h>
#include<iomanip>
using namespace std;

template<class T>
class Stack
{ 
public:
	Stack(int stackCapacity = 10);
	// 처음에 크기가 stackCapacity인 공백 스택을 생성
	bool IsEmpty() const;
	// 스택의 원소 수가 0이면 true, 아니면 false를 반환
	T& Top() const;
	// 스택의 상위 원소를 반환
	void Push(const T& item);
	// 스택의 상위에 item을 삽입
	void Pop();
	// 스택의 상위 원소를 삭제
	int get_topindex(){return top;}
private:
	T *stack;     // 스택 원소를 위한 배열
	int top;      // 톱 원소의 위치
	int capacity; // 스택 배열의 크기
	void ChangeSize1D(T*& a, const int oldSize, const int newSize);
};

template<class T>
Stack<T>::Stack(int stackCapacity) : capacity(stackCapacity), top(-1)
{
	if(capacity < 1)
		throw "Stack capacity must be>0";
	stack = new T[capacity];
}

template<class T>
inline bool Stack<T>::IsEmpty() const
{
	return (top == -1);
}

template<class T>
inline T& Stack<T>::Top() const
{
	if(IsEmpty())
		throw "Stack is empty";
	return stack[top];
}

template<class T>
void Stack<T>::Push(const T& item)
{
	if(top == capacity-1)
	{
		ChangeSize1D(stack, capacity, 2*capacity);
		capacity *= 2;
	}

	stack[++top] = item;
}

template<class T>
void Stack<T>::Pop()
{
	if(IsEmpty())
		throw "Stack is empty. Cannot delete";

	top--;
}

template<class T>
void Stack<T>::ChangeSize1D(T*& a, const int oldSize, const int newSize)
{
	if(newSize<0)
		throw "New length must be >= 0";

	T* temp = new T[newSize];            // 새로운 배열
	int number = min(oldSize, newSize);  // 복사할 원소 수
	copy(a, a+number, temp);
	delete []a;                          // 이전 메모리 제거
	a = temp;
}

struct Card{
	char type;
	string num;
};

class Solitaire{
public:
	Solitaire(){
	}
	void card_init();
	void print_pile();
	void playing_game();

private:
	Stack<Card>playing[7];
	Stack<Card>stock;
	Stack<Card>waste;
	Stack<Card>spade, diamond, heart, clover;
	static string cardnum[13];
};

string Solitaire::cardnum[13]={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};


void Solitaire ::card_init(){
	vector<Card>temp_card;
	srand((unsigned)time(NULL));
	char temptype[4]={'S', 'H', 'D', 'C'};
	for(int i=0;i<4;i++){
		for(int j=0;j<13;j++){
			Card temp;
			temp.type=temptype[i];
			temp.num =cardnum[j];
			temp_card.push_back(temp);
		}
	}
	for(int i=0;i<52;i++){
		int first = rand()%52;
		int second = rand()%52;
		Card swap;
		swap=temp_card[first];
		temp_card[first] = temp_card[second];
		temp_card[second]=swap;
	}
	for(int i=0;i<52;i++){
		if(i<1){
			playing[0].Push(temp_card[i]);
		}
		else if(i<3){
			playing[1].Push(temp_card[i]);
		}
		else if(i<6){
			playing[2].Push(temp_card[i]);
		}
		else if(i<10){
			playing[3].Push(temp_card[i]);
		}
		else if(i<15){
			playing[4].Push(temp_card[i]);
		}
		else if(i<21){
			playing[5].Push(temp_card[i]);
		}
		else if(i<28){
			playing[6].Push(temp_card[i]);
		}
		else{
			stock.Push(temp_card[i]);
		}
	}
	print_pile();
}
void Solitaire::print_pile(){
	if(waste.get_topindex()!=-1){
		cout<<"waste pile="<<waste.Top().type<<"."<<waste.Top().num<<endl;
	}
	else {
		cout<<"waste pile="<<endl;
	}
	for(int i=0;i<7;i++){
		for(int j=0;j<playing[i].get_topindex();j++){
			cout<<setw(5)<<"X";
		}
		cout<<"   "<<playing[i].Top().type<<"."<<playing[i].Top().num<<endl;
	}
	if(spade.get_topindex()!=-1){
		cout<<"Spade     "<<spade.Top().type<<"."<<spade.Top().num<<endl;
	}
	else{
		cout<<"Spade     "<<endl;
	}
	if(heart.get_topindex()!=-1){
		cout<<"Heart     "<<heart.Top().type<<"."<<heart.Top().num<<endl;
	}
	else{
		cout<<"Heart     "<<endl;
	}
	if(diamond.get_topindex()!=-1){
		cout<<"Diamond   "<<diamond.Top().type<<"."<<diamond.Top().num<<endl;
	}
	else{
		cout<<"Diamond   "<<endl;
	}
	if(clover.get_topindex()!=-1){
		cout<<"Clover    "<<clover.Top().type<<"."<<clover.Top().num<<endl;
	}
	else{
		cout<<"Clover    "<<endl;
	}

}

void Solitaire::playing_game(){
	bool flag = true;
	int num=0;
	bool do_some = true;
	while(num++<10){
		if(do_some){
			waste.Push(stock.Top());
			stock.Pop();
		}
		if(waste.IsEmpty()) {
			waste.Push(stock.Top());
			stock.Pop();
		}
		if(waste.Top().type=='S' && waste.Top().num==cardnum[spade.get_topindex()+1]){
			print_pile();
			spade.Push(waste.Top());
			waste.Pop();
			do_some=false;
		}
		else if(waste.Top().type=='H' && waste.Top().num==cardnum[heart.get_topindex()+1]){
			print_pile();
			heart.Push(waste.Top());
			waste.Pop();
			do_some=false;
		}
		else if(waste.Top().type=='D' && waste.Top().num==cardnum[diamond.get_topindex()+1]){
			print_pile();
			diamond.Push(waste.Top());
			waste.Pop();
			do_some=false;
		}
		else if(waste.Top().type=='C' && waste.Top().num==cardnum[clover.get_topindex()+1]){
			print_pile();
			clover.Push(waste.Top());
			waste.Pop();
			do_some=false;
		}
		for(int i=0;i<7;i++){
			char temptype = playing[i].Top().type;
			if(playing[i].get_topindex()!=-1){
				switch(temptype){
				case 'S':
					{
						if(playing[i].Top().num==cardnum[spade.get_topindex()+1]){
							print_pile();
							spade.Push(playing[i].Top());
							playing[i].Pop();
							do_some=false;
						}
						else{
							do_some=true;
						}
						break;
					}
				case 'H':
					{
						if(playing[i].Top().num==cardnum[heart.get_topindex()+1]){
							print_pile();
							heart.Push(playing[i].Top());
							playing[i].Pop();
							do_some=false;
						}
						else{
							do_some=true;
						}
						break;
					}
				case 'D':
					{
						if(playing[i].Top().num==cardnum[diamond.get_topindex()+1]){
							print_pile();
							diamond.Push(playing[i].Top());
							playing[i].Pop();
							do_some=false;
						}
						else{
							do_some=true;
						}
						break;
					}
				case 'C':
					{
						if(playing[i].Top().num==cardnum[clover.get_topindex()+1]){
							print_pile();
							clover.Push(playing[i].Top());
							playing[i].Pop();
							do_some=false;
						}
						else{
							do_some=true;
						}
						break;
					}
				}
			}
		}
		print_pile();
	}

}

int main(){
	Solitaire solitaire;

	solitaire.card_init();
	solitaire.playing_game();

	return 0;

}


약간 가독성이 떨어지긴 하지만, S, D, H, C는 Spade, Diamond, Heart, Clover를 나타낸다.


카드는 무늬마다 13장씩 총 52장이 있고 이 문제의 요구사항은 자동 Solitaire 프로그램을 만드는 것이었다.


Solitaire는 카드를 잘못놓기 시작하면 끝이 나지 않기 때문에 무한 loop를 돌고싶지 않아서 10번 정도만 loop를 돌도록 했다.


뭐...저건 숫자만 수정하면 고쳐질거니까 한 100번까진 돌려봤는데


별 다른 알고리즘 없이 맨 처음 나오는 카드를 바로 더미에 올려주는 거라 100번 돈다 해서 게임이 끝날 가능성은 거의 희박하다....ㅎㅎㅋㅋㅋㅋㅋ





결과화면도 약간 가독성이 떨어지는거 같기도 하네....하하


어쨌든 이와 같이 동작 가능하다. 헐 그리고 캡쳐엔 안나왔지만 playing 더미에 있는 카드들끼리도 겹치기 가능하다.




만약 코드를 손본다면


1. 자동으로 10턴 이런것 보다는 사용자 입력이 더 재밌을거 같다.


2. 결과 가독성 면에서도 떨어지는것 같아서 출력부분을 이쁘게 수정...하고싶다


3. 이왕 효율적이게 하려면 직접 구현한 stack보다는 STL이 낫겠지....



댓글