Buscar

Jogo hex para Linux (Linguagem C)

Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original

hex.c
//Cabeçalhos
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
//Definições
#define MAX 11 //Tamanho máximo de tabuleiro
#define JOG1 "♣" //Símbolo representante do jogador 1
#define JOG2 "♫" //Símbolo representarte do jogador 2
//Estruturas e enumerações
typedef enum { //Telas de jogo
	MENU, NOVO, CARREGAR, AJUDA, CREDITOS, SAIR
} Tela;
typedef enum{ //Comandos do jogo
	JOGAR, ABANDONAR, SALVAR_E_SAIR, REINICIAR
} Comando;
typedef struct {
	int tam; // Tamanho do tabuleiro.
	int tabuleiro[MAX][MAX]; // Matriz que representa o tabuleiro.
	int vez; // Indica o jogador da vez.
	Tela tela; // Indica a tela que está apresentada atualmente.
} Jogo;
//Assinatura de funções
int vitoria(Jogo * game, int line, int colune, int first);
int salvar_jogo(Jogo game);
int parametros_main(int argv, char ** argc);
int efetuarcomando(Jogo * game);
void apresentacao();
void zerar(Jogo * game);
void menu(Tela * teladejogo);
void novo_jogo(Jogo * game, int qtdargumentos, char**argumentos);
void match(Jogo * game);
void imprimirtabuleiro(Jogo game);
void imprimacaractere(int peca);
void imprimahex(int size);
void imprimacomandos(Jogo game);
void imprimavitoria(Jogo game);
void limpar_buffer();
void pausa();
void sair();
void carregar_jogo (Jogo * game);
void ajuda(Tela * tela_atual);
void creditos(Tela * tela_atual);
//Função principal
int main(int argv, char ** argc){
	//Declaração de variáveis
	Jogo hex;
	hex.tela=MENU;
	//Menu loop
	while(7){
		switch(hex.tela){
			case MENU: menu(&hex.tela); 				break; //Tela inical 
			case NOVO: novo_jogo(&hex, argv, argc);	break; //Inicar um novo jogo
			case CARREGAR: 	carregar_jogo (&hex);	break; //Carregar jogo salvo
			case AJUDA: ajuda(&hex.tela);				break; //Explanação do jogo
			case CREDITOS: creditos(&hex.tela);			break; //Exibição de créditos
			case SAIR: sair(); 				break; //Encerrar programa
		}
	}
	return EXIT_SUCCESS;
}
//Funções adicionais
//Função responsável por ministrar uma partida
void match(Jogo * game){
	//Declaração de variáveis
	Comando comando=0;
	//Game loop
	while(7){
		//Comandos
		switch(comando){
		case ABANDONAR: game->tela=MENU; 		return;
		case SALVAR_E_SAIR: comando=salvar_jogo(*game); break;
		case REINICIAR:
			zerar(game); 
			comando=JOGAR; 
			break;
		case JOGAR:
			//Interface
			imprimirtabuleiro(*game);
			imprimacomandos(*game);	
			//Solicitar comando e aplicá-lo
			comando=efetuarcomando(game);
			break;
		}
	}
}
//Verificar a existência de vitória
int vitoria(Jogo * game, int line, int colune, int first){
	//Declaração de variáveis
	int i, j, soma=0;
	//Caso base de fim de caminho
	if(line<0 || line >game->tam-1 || colune <0 || colune >game->tam-1 || game->tabuleiro[line][colune]!=game->vez) return 0;
	if(!first){
		game->tabuleiro[line][colune]=0; //marcação de passagem
		if(game->vez==2){// caso base para o jogador 2
			if(colune==0) return 1;//atingiu a extremidade inferior
			else if(colune==game->tam-1) return 111; //atingiu a extremidade superior
		}
		else{	//caso base para o jogador 1
			if(line==0) return 1; //atingiu a extremidade superior
			else if(line==game->tam-1) return 111; //atingiu a extremidade inferior
		}
	}
	for(i=line-1; i<=line+1; i++){
		for(j=colune-1; j<=colune+1; j++){
			if(line-i!=colune-j) soma+=vitoria(game, i, j, 0); //Recursão
		} 
	}
	if(first) return (soma%111!=0 && soma>111); //retorno lógico se atingiu ambas extremidades
	else return soma;
}
int efetuarcomando(Jogo * game){
	//Declaração de variáveis
	int comando_invalido, colune;
	char line;
	Jogo gameaux;
	//Laço para garatir insercão correta
	do{
		comando_invalido=0;
		limpar_buffer(); //Limpando possível lixo do buffer
		scanf("%c", &line); //Lendo a linha
		line=toupper(line);
		//Comandos especiais
		switch(line){
			case 'Q': return ABANDONAR;
			case 'S': return SALVAR_E_SAIR;
			case 'R': return REINICIAR;
		}
		if (line<65 || line>64+game->tam){ //Fora dos limites do tabuleiro
			printf("~Posição inválida.\n");
			comando_invalido=7;
		}
		else{
			scanf("%d", &colune); //Lendo a coluna
			if (colune<1 || colune >game->tam){ //Fora dos limites do tabuleiro
				printf("~Posição inválida.\n");
				comando_invalido=7;
			}
			else if(game->tabuleiro[line-65][colune-1]!=0){ //A posição não está vazia
				printf("~Posição já ocupada!\n");
				comando_invalido=7;
			}
		}
	}while (comando_invalido);
	game->tabuleiro[line-65][colune-1]=game->vez; //Efetuando jogada
	gameaux=*game; //Variável auxiliar que poderá ter seus dados modificados
	//Checagem de vitória a partir da última jogada
	if(vitoria(&gameaux, line-65, colune-1, game->vez)){
		imprimirtabuleiro(*game);
		imprimavitoria(*game);
		pausa(); //O usuária decidirá quando despausar
		return ABANDONAR; //O jogo será encerrado
	}
	game->vez=2/game->vez; //Alternando o jogador da vez
	return JOGAR; //Nada de especial acontece
}
//Impressão do tabuleiro
//Salvar jogo no arquivo de estado
int salvar_jogo(Jogo game){
	//Declaraão de variáveis
	FILE * arquivo = fopen("hex_jogo_salvo.txt", "w");
	int i, j;
	//Verificação de abertura do arquivo
	if(arquivo == NULL) {
 printf("~Erro ao criar arquivo de salvamento.\n");
 pausa();
		return JOGAR;
 }
	//Gravar os dados 
	fprintf(arquivo, "[Tamanho]\n%d\n\n[Vez]\n%d\n\n", game.tam, game.vez);
	//Gravar Tabuleiro
	fprintf(arquivo, "[Tabuleiro]\n");
	for (i=0; i<game.tam; i++){
		for (j=0; j<game.tam; j++){
			fprintf(arquivo, "%d", game.tabuleiro[i][j]);
		}
		//Quebra de linha
		fprintf(arquivo, "\n");
	}
	fclose(arquivo);
	return ABANDONAR; //A partida será encerrada
}
//Carregamento de jogo apartir do arquivo de estado
void carregar_jogo (Jogo * game){
	//Declaraão de variáveis
	char linha[41];
	int i=0, j;
	FILE * arquivo = fopen("hex_jogo_salvo.txt", "r");
	game->tela=CARREGAR; //Mudança de tela
	//Verificação de abertura do arquivo
	if(arquivo == NULL) {
 printf("~Não existe jogo salvo.\n");
		game->tela=MENU; //Mudança de tela
 pausa(); //Pausando o terminal
		return ;
 }
	//Laço para ler linha por linha
	while(fgets(linha, 40, arquivo)!=NULL){
		i++;
		//Extração de dados
		if(i==2) sscanf(linha, "%d", &game->tam);
		else if(i==5) sscanf(linha, "%d", &game->vez);
		else if(i>=8){
			//Laço para preenchimeto do tabuleiro
			for(j=0; j<game->tam; j++){	
			game->tabuleiro[i-8][j]=linha[j]-48;
			}
		}
	}
	//Fechando arquivo
	fclose(arquivo);
	//Iniciar uma nova partida
	match(game);
}
void imprimirtabuleiro(Jogo game){
	//Declaração de variáveis
	int i, j;
	//Slogan
	imprimahex(game.tam);
	
	//impressão de elementos de tabuleiro
	for(j=1; j<=2*game.tam+3; j++){
		if(j==1 || j==2*game.tam+3) printf("║");
		else if(j==game.tam+2) printf("___");
		else printf(" ");
	}
	printf("\n");
	for (i=1; i<=game.tam; i++){
		printf("║");//Elemento de borda
		for(j=1; j<=game.tam-i; j++){
			if(j==game.tam-i) printf("\033[1;33m %s \033[m", JOG1); //Imprimindo símbolo do jogador 1 amarelo
			else printf(" ");
		}
		for(j=1; j<=i; j++){
			if (i!=game.tam || j!=1) printf("___");
			else printf(" ");
			printf("╱ ");
			imprimacaractere(game.tabuleiro[j-1][game.tam-i-1+j]); //Será impresso o símbolo de acordo com o que houver na casa
			printf(" ╲");
		}
		if(i!=game.tam) printf("___\033[1;36m %s\033[m", JOG2); //Imprimindo símbolo do jogador 2 ciano
		else printf(" ");
		for(j=i+1; j<game.tam; j++) printf(" ");//Espaçamento
		printf(" ║\n");//Elemento de borda
	}
	
	for (i=1; i<=game.tam; i++){
		printf("║"); //Elemento de borda
		for(j=1; j<=i; j++){
			if(j==i) printf(" %c", i+64); //Impressão das letras que referênciam as linhas
			else printf(" ");
		}
		for(j=game.tam; j>=i; j--){
			if (j==i) printf("╲___╱%d", game.tam-i+1); //impressão dos números que referenciam as colunas
			else if(i==1){
				printf("╲___╱
");
				imprimacaractere(game.tabuleiro[game.tam-j+i][game.tam-j]); //Será impresso o símbolo de acordo com o que houver na casa
				printf(" ");
			}
			else{
				printf("╲___╱ ");
				imprimacaractere(game.tabuleiro[game.tam-j+i][game.tam-j]); //Será impresso o símbolo de acordo com o que houver na casa
				printf(" ");
			}
		}
		for(j=2; j<=i; j++) printf(" "); //Espaçamento
		//Elementos de borda
		if(game.tam-i>=9) printf(" ║\n");
		else printf(" ║\n");
	}
	//Borda inferior
	printf("╠═══");
	for (j=1; j<2*game.tam; j++) printf("════");
	printf("════╣\n");
}
//Responsável de imprimir o caractere refente ao jogador passado
void imprimacaractere(int peca){
	if (peca==1) printf("\033[1;33m%s\033[m", JOG1); //imprimindo caractere do jogador 1 amarelo
	else if (peca==2) printf("\033[1;36m%s\033[m", JOG2); // Imprimindo caractere do jogador 2 ciano
	else printf(" "); //Casa vazia
}
//Apresentação de comandos disponíveis ao jogador
void imprimacomandos(Jogo game){
	//Declaração de variáveis
	int i;
	//Elementos de borda, impressão de mensagens e formatação com espaços
	printf("║ Q: abandonar jogo");
	for(i=1; i<(game.tam-1)*4-21; i++) printf(" ");
	printf(" S: salvar e sair ");
	for(i=1; i<(game.tam-1)*4-21; i++) printf(" ");
	printf(" R: reiniciar jogo ║\n");
	printf("║ Coordenadas: efetuar jogada");
	for(i=1; i<2*(game.tam-1)*4-38; i++) printf(" ");
	printf("Exemplos: A7, B11, G2 ║\n");
	printf("╠═══");
	for (i=1; i<2*game.tam; i++){
		if (i==game.tam) printf("══╦═");
		else printf("════");
	}
	printf("════╣\n║");
	for(i=1; i<(game.tam-1)*2-5; i++) printf(" ");
	printf("Jogador da vez: ");
	imprimacaractere(game.vez);
	for(i=1; i<(game.tam-1)*2-5; i++) printf(" ");
	printf("║");
	for(i=1; i<(game.tam-1)*2-8; i++) printf(" ");
	printf("Entre com um comando:__");
	for(i=1; i<(game.tam-1)*2-8; i++) printf(" ");
	printf("║\n╚═══");
	for (i=1; i<2*game.tam; i++){
		if (i==game.tam) printf("══╩═");
		else printf("════");
	}
	printf("════╝\n");
}
//Ações da tela de menu
void menu(Tela * teladejogo){
	//Declaração de variáveis
	int opcao=-1, erro;
	//Interface
	apresentacao();
	//Laço para garantir a correta inserção da opção desejada
	do{
		erro=0;
		limpar_buffer(); //Limpando o buffer
		scanf("%d", &opcao); //Lendo opção
		if(opcao<MENU || opcao>SAIR){
			erro=7;
			printf("~Opção inválida!\n");
		}
	} while (erro);
	*teladejogo=opcao; //Mudando tela de jogo de acordo com a opção
}
//Ações necessárias para um novo jogo
void novo_jogo(Jogo * game, int qtdargumentos, char**argumentos){
	game->tela=NOVO; //Mudança de tela
	//Obtenção do tamanho do tabuleiro
	game->tam=parametros_main(qtdargumentos, argumentos);
	zerar(game); //Zerar tabuleiro
	//Iniciar uma nova partida
	match(game);
}
//Extração do tamanho informado pelo usuário ao invocar programa e validação do mesmo
int parametros_main(int argv, char ** argc){
	int size;
	//Checando a quantidade de argumentos informada
	if(argv!=2){
		printf("~Impossível inicar um novo jogo.\n");
		printf("Uma quantidade inesperada de argumentos foi inserida ao invocar o programa.\nDeve ser informado apenas a dimensão do tabuleiro.\nExemplo: ./hex 9.\nAbortando...\n");
		exit(EXIT_FAILURE);//Encerrando programa
	}	
	size=atoi(argc[1]);
	//Checando a aceitação do tamanho informado
	if (size!=7 && size!=9 && size!=11){
		printf("~Impossível inicar um novo jogo.\n");
		printf("Foi inserido um tamanho de tabuleiro inválido ao invocar programa.\nSão somente aceitos tabuleiros 7x7, 9x9 e 11x11. \nAbortando...\n");
		exit(EXIT_FAILURE);//Encerrando programa
	}
	return size; //Retorno da função
}
//Impressão do slogan
void imprimahex(int size){
	//Declaração de variáveis
	int j;
	system("clear"); //Limpando a tela
	//Impressão do hex
	printf("╔════");
	for(j=2; j<size; j++) printf("════");
	printf("═╦ ╦╔═╗═╗ ╦");
	for(j=2; j<size; j++) printf("════");
	printf("════╗\n");
	printf("║ ");
	for(j=2; j<size; j++) printf(" ");
	printf("╠═╣╠╣ ╔╩╦╝");
	for(j=2; j<size; j++) printf(" ");
	printf(" ║\n");
	printf("╠════");
	for(j=2; j<size; j++) printf("════");
	printf("═╩ ╩╚═╝╩ ╚═");
	for(j=2; j<size; j++) printf("════");
	printf("════╣\n");
}
//Informe de vitória
void imprimavitoria(Jogo game){
	//Declaração de variáveis
	int i;
	//Impressão de elementos de borda, espaçamento e mensagem de vitória
	printf("║ ");
	imprimacaractere(game.vez);
	for (i=1; i<4*game.tam-12; i++) printf(" ");
	printf("O jogador ");
	imprimacaractere(game.vez);
	printf(" venceu!!");
	for (i=1; i<4*game.tam-11; i++) printf(" ");
	imprimacaractere(game.vez);
	printf(" ║\n╚═══");
	for (i=1; i<2*game.tam; i++) printf("════");
	printf("════╝\n");
}
//Apresentacão do programa, tela de menu
void apresentacao(){
	system("clear");//Limpando a tela
	printf("╔════════════════════════════════════════════════════════════════════════════╗\n");
	printf("║ ║\n");
	printf("║ ║\n");
	printf("║ ██ ▄█ ▄███████▓ ▀███▓ ███▓▀ ║\n");
	printf("║ █▓█ ███ ███ ██▓ ███▌ ██▓█▀ ║\n");
	printf("║ ███ █▓█ ███ █▀ ███ ▐█▓█ ║\n");
	printf("║ ▄██▓▄▄▄▄███▄▄ ▄███▄▄▄ ▀███▄███▀ ║\n");
	printf("║ ▀▀███▀▀▀▀███▀ ▀▀▓▓█▀▀▀ ████▀██▄ ║\n");
	printf("║ ▓██ ███ ███ █▄ ▐█▓█ ▀███ ║\n");
	printf("║ ███ ▓▓█ ███ ███ ▄███ ▓██▄ ║\n");
	printf("║ ███ █▀ ▓███▓████▓ ████ █▓█▄ ║\n");
	printf("║ ║\n");
	printf("║ __________ __________ __________ __________ __________ ║\n");
	printf("║ ╱ ╲ ╱ ╲ ╱ ╲ ╱ ╲ ╱ ╲ ║\n");
	printf("║ < 1)NOVO > < 2)CARREGAR > < 3)AJUDA > < 4)CRÉDITOS > < 5)SAIR > ║\n");
	printf("║ ╲__________╱ ╲__________╱ ╲__________╱ ╲__________╱ ╲__________╱ ║\n");
	printf("╠══════════════════════════╦═════════════════════╦═══════════════════════════╣\n");
	printf("║ ╔═════════════════════╣ ENTRE COM UMA OPÇÃO ╠══════════════════════╗ ║\n");
	printf("╚════╝ ╚═════════════════════╝ ╚════╝\n");
}
//Redefinir informações: zerar tabuleiro e jogador da vez voltado para o padrão
void zerar(Jogo * game){
	//Declaração de variáveis
	int i, j;
	//Percorrendo a tabuleiro e zerando
	for (i=0; i<game->tam; i++){
		for (j=0;j<game->tam; j++) game->tabuleiro[i][j]=0;
	}
	//Jogador da vez padrão
	game->vez=1;
}
//Responsável por limpar o buffer
void limpar_buffer(){
	__fpurge(stdin);//codigo para limpar o buffer
}
//Tela de creditos
void creditos(Tela * tela_atual){
	*tela_atual=CREDITOS; //Alterando a tela
	imprimahex(8); //Slogan
	printf("Desenvolvedor:\n");
	printf("\E[1;31mFrancinaldo Gomes. \nEmail: francisvexu@gmail.com\nFacebook: francinaldo.gomes.eu\E[0m\n");
	printf("Projeto avaliativo realizado para demostrar os conhecimentos adquiridos\nna disciplina Linguagens de Programação, a fim de obteção de conceito\nna terceira unidade.\n");	
	printf("\E[1;31mDocente: Alyppio Coutinho. \E[0m\n");
	pausa();
	*tela_atual=MENU; //Mudando de tela
}
//Tela de ajuda
void ajuda(Tela * tela_atual){
	*tela_atual=AJUDA;//Alterando a tela
	imprimahex(10); //Imprimindo slogan
	printf("║ INSTRUÇÕES ║\n");
	printf("╠═══════════════════════════════════════════════════════════════════════════════════╣\n");
	printf("║ CARACTERISTICAS GERAIS
║\n"); 
	printf("║1- Hex é um jogo de tabuleiro jogado em uma grade hexagonal. O jogo foi inventado║\n");
	printf("║ pelo matemático dinamarquês Piet Hein, que o introduziu em 1942 no Instituto ║\n");
	printf("║ Niels Bohr. Foi independentemente re-inventado em 1947 pelo matemático John ║\n");
	printf("║ Nash na Universidade de Princeton. ║\n");
	printf("║2- Cada jogador é detentor de dois lados opostos do losângulo. O objetivo é ║\n");
	printf("║ formar uma conexão entre esses dois lados utilizando suas peças. ║\n");
	printf("║3- O primeiro jogador a completar a sua ligação ganha o jogo. Os quatro cantos ║\n");
	printf("║ de cada hexágono das bordas pertencem a ambos os lados adjacentes. ║\n");
	printf("║4- O jogo nunca pode terminar em um empate, um fato provado por John Nash: a ║\n");
	printf("║ única maneira de evitar que o seu adversário forme um caminho conectado, é ║\n");
	printf("║ é também formar um caminho. Em outras palavras, Hex é um jogo determinado. ║\n");
	printf("║ COMO JOGAR ║\n");
	printf("║1- Ao invocar o programa, você deve informar o tamanho do tabuleiro, caso deseje ║\n");
	printf("║ um novo jogo, no formato ./hex X, onde X deve ser o tamanho (7, 9 ou 11). ║\n");
	printf("║2- A partir do menu, você tem as opções de carregar ou iniciar um novo jogo. ║\n");
	printf("║ Sempre será carregado o último jogo salvo, caso exista. ║\n");
	printf("║3- O primeiro jogador sempre será ");
	imprimacaractere(1);
	printf(" e o segundo ");
	imprimacaractere(2);
	printf(". Você pode decidir com seu ║\n");
	printf("║ adversário com qual jogar. ║\n");
	printf("║4- Para efetuar uma jogada, basta informar a coordenada da casa que quer ocupá-la.║\n");
	printf("║ A coordenada de uma casa é dada pela letra e número a ela correspondentes, no ║\n");
	printf("║ formato LNN ou LN, onde L é letra e N, número . ║\n");
	printf("╚═══════════════════════════════════════════════════════════════════════════════════╝\n");
	pausa();//Pausando terminal
	*tela_atual=MENU; //Mundado de tela
}
//Pausa no terminal
void pausa(){
	char pause;
	printf("> Pressione ENTER para continuar:\n");
	limpar_buffer();
	scanf("%c", &pause);
}
//Encerramento normal do programa
void sair(){
	imprimahex(8);//Slogan
	printf("╚══════════╣ Esperamos que tenha gostado. Volte logo ☻☻☻ ╠══════════╝\n\n");//Mensagem de despedida
	exit(EXIT_SUCCESS); //Encerramento programa
}
 
instrucoes.txt
Intruções
O programa funciona através do terminal.
-Para iniciar o programa chame pelo comando ./hex na pasta do arquivo executável. 
 Isso de estiver utilizando o arquivo "hex" já compilado disponível no arquivo.
 Caso deseje um novo jogo, deverar informar o tamanho do tabuleiro ao invocar o programa.
-Possibilidades (tamanhos de tabuleiro):
 ./hex 7
 ./hex 9
 ./hex 11
-Se o programa for invocado utilizando apenas ./hex, você poderá apenas jogar jogos já salvos.
-Essa forma peculiar de informar o tamanho do tabuleiro foi exigida pelo professor :v
hex

Teste o Premium para desbloquear

Aproveite todos os benefícios por 3 dias sem pagar! 😉
Já tem cadastro?

Outros materiais