Git Product home page Git Product logo

alynva / freecell Goto Github PK

View Code? Open in Web Editor NEW
7.0 4.0 3.0 205.67 MB

:spades::hearts::clubs::diamonds: Projeto referente ao trabalho sobre pilhas (T1) do curso Estrutura de Dados (ED) do Bacharelado em Ciência da Computação (BCC) na Universidade Federal de São Carlos (UFSCar).

Home Page: http://edcomjogos.dc.ufscar.br/

License: MIT License

C++ 2.99% Makefile 0.04% C 96.40% Objective-C 0.54% CMake 0.03%
freecell jogo cartas estrutura-de-dados pilha sdl2

freecell's Introduction

GitHub contributors GitHub tag Codacy grade Github Downloads All Releases

FreeCell

image

Repositório do Projeto 1 da disciplina Estrutura de Dados

O objetivo deste projeto é demonstrar a aplicação do primeiro tópico de Estruturas de Dados, Pilha. Para tal usaremos como modelo o jogo de cartas individual Freecell, cuja estrutura é composta de 8 pilhas intermediárias de cartas que estão inicialmente desordenadas e 4 pilhas finais, inicialmente vazias, que deverão ser compostas por cartas de um único naipe para acabar o jogo.

Estrutura de Dados do jogo:

  • 8 Pilhas intermediárias serão usadas para o início do jogo e para movimentação inicial das cartas. A regra dessas 8 pilhas é que uma carta só pode ser movimentada se for colocada em cima de outra de valor diretamente maior. Assim, mesmo começando ordenadas aleatoriamente na mesa, as pilhas feitas pelo jogador ficarão em ordem decrescente de valor de cima pra baixo. A segunda regra dessas pilhas é que só pode ser colocada uma carta em cima da outra se elas forem de cores diferentes. Essas duas regras são de simples implementação, apenas sendo necessário um atributo Cor ou Naipe e um valor numérico para cada uma delas, e as operações feitas para se movimentar cartas únicas são simplesmente Pop(x) na pilha original e Push(x) na pilha de destino.
  • 4 Espaços de valor único para movimentação extra. Inicialmente vazios. (Acho que esses 4 podem ser simplesmente variáveis ou então Pilhas de valor único que operam simplesmente com Pop() e Push() de uma carta só)
  • 4 Pilhas finais, usadas para ordenar as cartas dos 4 naipes e terminar o jogo. Essas pilhas ao contrário das intermediárias são ordenadas em forma crescente, começando no Ás e terminando no Rei, inicialmente vazias. Sua regra é que todas podem ser inicialmente usadas por qualquer naipe, mas após receberem a primeira carta, só poderão receber cartas do naipe da mesma. Só utilizarão Push(), visto que é o destino final das cartas do baralho.

Instalação

Os arquivos já compilados para Windows e Linux podem ser encontrados neste link. Para os demais sistemas operacionais, o código fonte pode ser facilmente compilado executando o comando make no diretório ./Source/src.

Recompilação em Linux

Para refazer a compilação em sistemas Unix, é necessário verificar se as bibliotecas dev do SDL2. Você pode verificar isso pelo comando:

dpkg-query -l "libsdl2*-dev"

Caso as bibliotecas libsdl2-dev, libsdl2-image-dev, libsdl2-mixer-dev e libsdl2-ttf-dev não estejam instalas, rode o seguinte comando:

sudo apt install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev -y

Após a instalação, basta executar o comando make dentro da pasta ./src/ e o executável será gerado automaticamente na pasta ./bin/. Para executá-lo rapidamente, execute make run na pasta ./src/

Descrição da Implementação

A arquitetura do projeto foi definida da seguinte maneira:

Arquitetura

Pilha

Para a implementação do tipo abstrato de dados pilha, ficou decidido a utilização de uma pilha duplamente encadeada com nó header.

Pilha vazia

Pilha com três elementos

Tem-se então, que cada elemento é armazenado em um nó com três atributos, sendo eles:

  • Value: armazena o elemento em si;
  • Next: ponteiro que define o nó do pŕoximo elemento;
  • Previous: ponteiro que define o nó do elemento anterior;

Essa pilha tem as funções mais básicas, para a utilização desse TAD temos as funções mais básicas, seguem elas:

  • isEmpty(): retorna um booleano, com valor verdadeiro se a pilha está vazia (isto é o atributo Dir do Header aponta para o Header), e valor falso se a pilha está cheia.
  • push(element, &check): insere element no topo da pilha, e check recebe verdadeiro, se foi possível inserir, ou verdadeiro, se não foi possível.
  • pop(&element): remove o elemento do topo da pilha e passa para element. A função retorna verdadeiro se foi possível remover o elemento no topo (i.e. a pilha não estava vazia), ou falso caso não foi possível.
  • clear(): limpa a pilha, removendo todos os elementos, deixando apenas o nó de header.
  • getSize(): retorna o tamanho atual da pilha.
  • peek(): retorna um ponteiro apontando para o nó no topo da pilha.

Com esse tipo básico, derivam-se as funções especifícas, responsáveis pelas pilhas do Freecell.

Pilha Inteligente

Essa implementação herda do tipo abstrato pilha definido anteriormente. Sua função é garantir métodos mais complexos para as pilhas do jogo. Tem-se portanto, que os atributos da pilha também serão herdados, e mais alguns são implementados.

Dentre os atributos e métodos novos, o mais importante é o método canPush(carta1, carta2), que checa se é possível inserir a carta no topo da pilha. Nesse caso, a classe pilha inteligente não tem uma implementação específica de canPush(), já que o mesmo terá comportamentos diferentes entre as pilhas intermediárias, finais e auxiliares.

Autores

Créditos

  • Alisson Nunes - Interface e parte gráfica.
  • Gabriel Alves - Implementação da estrutura dos dados.
  • Matheus Bortoleto - Interface e parte gráfica.
  • Rafael Sales - Documentação e música.
  • Músicas utilizadas

Licença

O código a seguir foi criado para propósitos educacionais e seu reuso é aberto a qualquer um que o queira utilizar, com permissões de cópia, criação, distribuição e remoção de partes ou totalidade dele, desde que se deem os devidos créditos aos autores.

freecell's People

Contributors

alynva avatar rsaless avatar sp0oks avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

rsaless sp0oks

freecell's Issues

Randomização de cartas

Duas questões, primeiro que atualmente está dando este erro em máquinas Windows:

image

O que se faz necessário uma nova implementação da função. Segundo que, na minha concepção é melhor com que essa função esteja na classe Baralho, ao invés de na classe PilhaInteligente ou derivadas.

Hack #1: mover mais de uma carta para a pilha única.

Quando há a possibilidade de mover mais de uma carta das pilhas intermediárias, caso você tente colocar elas em alguma pilha auxiliar livre, o jogo irá aceitar a primeira carta e voltar a segunda. Com isso, você consegue "inverter" cartas utilizando uma única pilha auxiliar. Segue os prints:
image
image
image

Travamentos desonhecidos #1

Postem aqui capturas de tela do jogo quando ele travar inexplicadamente, sem um padrão claro. Favor deixar visível todas as cartas do jogo. Esclarecer também a versão que estava utilizando e o contexto, caso necessário.

Hack #2: pegar pegar uma carta à cima, mesmo sendo incorreta

Se você for muito rápido, basta você pegar uma ou mais cartas corretas (segundo as regras), mantê-la na mesma pilha e tentar soltar e clicar novamente o mais rápido que poder. Se você fizer o último passo rápido o bastante, conseguirá pegar a carta de cima e colocá-la em outro lugar que aceite-a. Como demonstrado a seguir:
image
image
image
image
image

Varredura da Pilha

É necessário alterar a implementação de Pilha::render(), Pilha::organize() e Pilha::isInside().

Nestes, num primeiro momento utilizei a criação de uma outra pilha temporária e a recolocação de cada elemento de um pilha para outra, ida e volta. Onde na volta está sendo feito as interações necessárias, como o seguinte no método render():

template<typename T, int S>
void Pilha<T,S>::render() {
	Pilha<T,S> p_temp;		// Cria uma pilha temporária
	T t_temp;			// Cria um objeto da pilha temporário

	while (!this->isEmpty()) {	// Intera na pilha original até que a esvazie
		this->pop(t_temp);
		p_temp.push(t_temp);
	}
	while (!p_temp.isEmpty()) {	// Intera na pilha temporário até que a esvazie
		p_temp.pop(t_temp);
		t_temp.render();	// Realiza as operações necessárias
		this->push(t_temp);
	}
}

Para tal solução, pode-se usar o simples conceito de vetor na pilha. Preferencialmente usando métodos, privados talvez para não fugir do conceito de pilha, porém reaproveitáveis.

Problema com ponteiro de ponteiro

Ao tentar utilizar o Node::value como um T* ao invés de T, na branch "Setting-value-as-pointer", me deparei com o problema de erro em tempo de execução. Ao tentar debugar, isolei o EventManager::mouseMove() decorrente do FreeCell::menu() >> EventManager::update() e notei que o erro se dá decorrente da utilização de um ponteiro que aponta a outro ponteiro que aponta a uma instância de uma classe (no caso a classe Button), chamando um método dessa classe. Nos meus testes, o problema não está em chamar o método, mas sim em utilizar o ponteiro this dentro deste método. Procurei soluções e alternativas mas sem obter êxito.

Toda essa branch foi criada quando eu estava implementado o método EventManager::doubleClick() e nele há a necessidade de verificar se a carta que está sob o mouse é a primeira carta da pilha. Isso poderia ser contornado caso fizesse a verificação "crua", e não por endereço de memória, visto que não há cartas repetidas. Porém, noutra aplicação o cenário pode ser diferente.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.