Ir ao conteúdo
  • Cadastre-se

C Programa Tic Tac Toe


Lucas.Zottis

Posts recomendados

E ai galera, certinho?

Criei esse jogo da velha para praticar e gostaria de opiniões sobre ele.

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <windows.h>
#include <string.h>
#include "Facilitador.h"
#define TAM 8

// Dados sobre os players (a maquina conta como player e será inicializado no começo do jogo);
typedef struct {
	// Nome do player, a maquina será COM;
	char name[10];
	// Dados sobre partidas, vitórias, empates e derrotas;
	int match, win, tie, lose;
}Player;
// grade do jogo;
char house[TAM];
// Referenciação dos players;
Player player1;
Player player2;
Player com;

/* Declaração das funções */
void Menu();
void GameMode();
void VersusCOM();
void VersusHuman();
void ExitProgram();
void InitHouses();
void Initiate();
void ShowHouses();
void HumanMove(int turn);
void IAMove();
void EmptyHouse(int spot, int turn);
int Verify();

int main() {
	// Inicializações;
	Initiate();
	// CONFIGURANDO PARA O IDIOMA PORTUGUES;
	setlocale(LC_ALL, "Portuguese");
	int i, j;
	// Apresentação;
	char intro [5][40] = {
		"Olá!",
		"Prazer, eu sou o Jarvas.",
		"Sejam bem vindos ao Tic Tac Toe.",
		"Espero que se divirtam.",
		"Tenham um bom jogo e boa sorte.",
	};
	titulo("TIC TAC TOE");
	for (i = 0; i < 5; i++) {
		printf(" ");
		for (j = 0; j < 40; j++) {
			printf("%c", intro[i][j]);
		}
		pulalinha();
	}
	pausa();
	Clean();
	Menu();
	return 0;
}
// Menu Principal;
void Menu() {
	int menu;
	do{ // Menu principal;
		titulo("TIC TAC TOE");
		printf("\n 1 - Jogar");
		printf("\n 2 - Estatísticas");
		printf("\n 0 - Fechar");
		printf("\n\n | Opção: ");
		scanf("%d", &menu);
		if (menu < 0 || menu > 2){
			printf("\n Opção inválida!");
			printf("\n Informe uma opção válida do menu.");
			sleep(2);
		}
		Clean();
	}while(menu < 0 || menu > 2);
	switch(menu){
		case 1: // Menu de seleção de modo de jogo;
			GameMode();
		break;
		case 2: // Quadro de dados sobre partidas;
			printf("Aqui terá dados sobre as partidas.");
			Menu();
		break;
		case 0: // Fechar programa;
			ExitProgram();
			Menu();
		break;
	}
}
// Modo de jogo;
void GameMode(){
	int menu;
	do{ // Menu modo de Jogo;
		titulo("TIC TAC TOE");
		printf("\n 1 - vs COM");
		printf("\n 2 - vs Player");
		printf("\n 0 - Voltar");
		printf("\n\n | Opção: ");
		scanf("%d", &menu);
		if (menu < 0 || menu > 2){
			printf("\n Opção inválida!");
			printf("\n Informe uma opção válida do menu.");
			sleep(2);
		}
		Clean();
	}while(menu < 0 || menu > 2);
	switch (menu){
		case 1: // Jogar vs COM;
			VersusCOM();
		break;
		case 2: // Jogar vs Player;
			VersusHuman();
		break;
		case 0: // Voltar para o menu principal;
			titulo("TIC TAC TOE");
			Clean();
			Menu();
		break;
	}
}
// Versus COM;
void VersusCOM() {
	int winner = 3;
	int turn = 1;
	InitHouses();
	limpabuffer();
	titulo("TIC TAC TOE");
	printf("\n\n Player 1: ");
	gets(player1.name);
	Clean();
	do { // Execução do jogo;
		titulo("TIC TA TOE");
		ShowHouses();
		switch (turn) {
			case 1:
				HumanMove(turn);
				turn = 2;
			break;
			case 2:
				IAMove();
				turn = 1;
			break;
		}
		winner = Verify();
		Clean();
	} while (winner > 2);
	switch (winner) { // Verifica quem ganhou;
		case 1: // Player 1 ganhou!!
			titulo("TIC TA TOE");
			ShowHouses();
			printf("\n\n %s ganhou!!", player1.name);
		break;
		case 2: // Player 2 ganhou!!
			titulo("TIC TA TOE");
			ShowHouses();
			printf("\n\n %s ganhou!!", com.name);		
		break;
		default: // Deu empate!!
			titulo("TIC TA TOE");
			ShowHouses();
			printf("\n\n %s e %s empataram!!", player1.name, com.name);
		break;
	}
	sleep(2);
	Clean();
	GameMode();
}
// Versus Humano;
void VersusHuman() {
	int winner = 3;
	int turn = 1;
	InitHouses();
	limpabuffer();
	titulo("TIC TAC TOE");
	printf("\n\n Player 1: ");
	gets(player1.name);
	printf("\n\n Player 2: ");
	gets(player2.name);
	Clean();
	do { // Execução do jogo;
		titulo("TIC TA TOE");
		ShowHouses();
		switch (turn) {
			case 1:
				HumanMove(turn);
				turn = 2;
			break;
			case 2:
				HumanMove(turn);
				turn = 1;
			break;
		}
		winner = Verify();
		Clean();
	} while (winner > 2);
	switch (winner) { // Verifica quem ganhou;
		case 1: // Player 1 ganhou!!
			titulo("TIC TA TOE");
			ShowHouses();
			printf("\n\n %s ganhou!!", player1.name);
		break;
		case 2: // Player 2 ganhou!!
			titulo("TIC TA TOE");
			ShowHouses();
			printf("\n\n %s ganhou!!", player2.name);		
		break;
		default: // Deu empate!!
			titulo("TIC TA TOE");
			ShowHouses();
			printf("\n\n %s e %s empataram!!", player1.name, player2.name);
		break;
	}
	sleep(2);
	Clean();
	GameMode();
}
// Sair programa;
void ExitProgram() {
	char leave;
	int setExit = 0;
	do { // Sair do programa;
		titulo("TIC TAC TOE");
		printf("\n Deseja sair [S/N]? ");
		limpabuffer();
		scanf("%c", &leave);
		getchar();
		if ((leave == 's') || (leave == 'S')) {
			Clean();
			titulo("TIC TAC TOE");
			printf("\n Tchau!!");
			sleep(1);
			exit(0);
		} else {
			if ((leave == 'n') || (leave == 'N')) {
				Clean();
				break;
			} else {
				printf("\n Opção invalida!!");
			}
		}
		Sleep(750);
		Clean();
	} while ((leave != 's' && leave != 'S') || (leave != 'n' && leave != 'N'));
}
// Inicializador de grade;
void InitHouses() {
	int i;
	// Inicialização da grade;
	for (i = 0; i <= 9; i++) {
		house[i] = ' ';
	}
}
// Mostra grade;
void ShowHouses() {
	int i, count;
	pulalinha();
	printf(" ");
	for (i = 0; i <= 2; i++) {
		printf("|%c|", house[i]);
	}
	pulalinha();
	printf(" ");
	for (i = 3; i <= 5; i++) {
		printf("|%c|", house[i]);
	}
	pulalinha();
	printf(" ");
	for (i = 6; i <= 8; i++) {
		printf("|%c|", house[i]);
	}
}
// Inicializações;
void Initiate(){
	// Player 1;
	player1.match = 0;
	player1.win = 0;
	player1.tie = 0;
	player1.lose = 0;
	// Player 2;
	player2.match = 0;
	player2.win = 0;
	player2.tie = 0;
	player2.lose = 0;
	// COM;
	strcpy(com.name, "Jarvas");
	com.match = 0;
	com.win = 0;
	com.tie = 0;
	com.lose = 0;
	// Inicialização da grade;
	InitHouses();
}
// Jogada humana;
void HumanMove(int turn) {
	int spot;
	switch (turn) {
		case 1:
			printf("\n\n -> %s", player1.name);
			printf("\n Local [1-9]: ");
			scanf("%d", &spot);
		break;
		case 2:
			printf("\n\n -> %s", player2.name);
			printf("\n Local [1-9]: ");
			scanf("%d", &spot);
		break;
	}
	EmptyHouse(spot, turn);
}
// Jogada IA;
void IAMove() {
	int spot, i;
	// Definindo casa para jogar;
	srand(time(NULL));
	spot = rand() % TAM;
	// Verifica se local está ocupado;
	if (house[spot] == ' ') {
		house[spot] = 'O';
	} else {
		char dots[3] = "...";
		char *s = dots;
		printf("\n\n -> %s está Pensando", com.name);
		for (i = 0; i < strlen(dots); i++) {
			printf("%c", *s);
			Sleep(200);
		}
		IAMove();
	}
}
// Verifica se local está ocupado;
void EmptyHouse(int spot, int turn) {
	switch (turn) {
		case 1:
			if (house[spot - 1] == ' '){
				house[spot - 1] = 'X';
			} else {
				printf(" Ocupado!!");
				Sleep(750);
			}
		break;
		
		case 2:
			if (house[spot - 1] == ' '){
				house[spot - 1] = 'O';
			} else {
				printf(" Ocupado!!");
				Sleep(750);
			}
		break;
	}
}
// Verifica se alguem ganhou;
int Verify() {
	// winner = 1 é Player um - winner = 2 é player dois - winner = 0 é empate;
	int winner = 3;
	// Verifica se o Player 1 ganhou;
	if (house[0] == 'X' && house[1] == 'X' && house[2] == 'X') {
		winner = 1;
	} else {
		if (house[3] == 'X' && house[4] == 'X' && house[5] == 'X') {
			winner = 1;
		} else {
			if (house[6] == 'X' && house[7] == 'X' && house[8] == 'X') {
				winner = 1;
			} else {
				if (house[0] == 'X' && house[3] == 'X' && house[6] == 'X') {
					winner = 1;
				} else {
					if (house[1] == 'X' && house[4] == 'X' && house[7] == 'X') {
						winner = 1;
					} else {
						if (house[2] == 'X' && house[5] == 'X' && house[8] == 'X') {
							winner = 1;
						} else {
							if (house[0] == 'X' && house[4] == 'X' && house[8] == 'X') {
								winner = 1;
							} else {
								if (house[2] == 'X' && house[4] == 'X' && house[6] == 'X') {
									winner = 1;
								}
							}
						}
					}
				}
			}
		}
	}
	// Verifica se o Player 2 ganhou;
	if (house[0] == 'O' && house[1] == 'O' && house[2] == 'O') {
		winner = 2;
	} else {
		if (house[3] == 'O' && house[4] == 'O' && house[5] == 'O') {
			winner = 2;
		} else {
			if (house[6] == 'O' && house[7] == 'O' && house[8] == 'O') {
				winner = 2;
			} else {
				if (house[0] == 'O' && house[3] == 'O' && house[6] == 'O') {
					winner = 2;
				} else {
					if (house[1] == 'O' && house[4] == 'O' && house[7] == 'O') {
						winner = 2;
					} else {
						if (house[2] == 'O' && house[5] == 'O' && house[8] == 'O') {
							winner = 2;
						} else {
							if (house[0] == 'O' && house[4] == 'O' && house[8] == 'O') {
								winner = 2;
							} else {
								if (house[2] == 'O' && house[4] == 'O' && house[6] == 'O') {
									winner = 2;
								}
							}
						}
					}
				}
			}
		}
	}
	// Verifica se foi empate;
	if (winner != 0 && winner != 1) {
		if (house[0] != ' ' && house [1] != ' ' && house [2] != ' ' && house[3] != ' ' && house[4] != ' ' && house[5] != ' ' && house[6] != ' ' && house[7] != ' ' && house[8] != ' ') {
			winner = 0;
		}
	}
	return winner;
}

 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Note que você não incluiu o código importado do Facilitador.h então não dá para nós compilarmos.

 

5 horas atrás, Lucas.Zottis disse:

#define TAM 8

 

5 horas atrás, Lucas.Zottis disse:

// grade do jogo;
char house[TAM];

 

Jogo da velha tem 9 casas então TAM deveria ser igual a 9.

 

A função Verify() poderia ser simplificada para algo desse tipo:

int Verify() {
    // winner = 1 é Player um - winner = 2 é player dois - winner = 0 é empate;
    
    int i;
    
    // Verifica linhas;
    for(i=0; i<3; i++){
        if(house[i*3] == house[i*3+1] && house[i*3] == house[i*3+2]){
            if(house[i*3] == 'X') return 1;
            if(house[i*3] == 'O') return 2;
        }
    }
    
    // Verifica Colunas:
    for(i=0; i<3; i++){
        if(house[i] == house[i+3] && house[i] == house[i+6]){
            if(house[i] == 'X') return 1;
            if(house[i] == 'O') return 2;
        }
    }
    
    // Verifica Diagonal Principal:
    if(house[0] == house[4] && house[0] == house[8]){
        if(house[0] == 'X') return 1;
        if(house[0] == 'O') return 2;
    }
    
    // Verifica Diagonal Secundária
    if(house[2] == house[4] && house[2] == house[7]){
        if(house[2] == 'X') return 1;
        if(house[2] == 'O') return 2;
    }
    
    // Verifica se foi empate;
    if (house[0] != ' ' && house[1] != ' ' && house[2] != ' ' &&
        house[3] != ' ' && house[4] != ' ' && house[5] != ' ' && 
        house[6] != ' ' && house[7] != ' ' && house[8] != ' ') {
            return 0;
    }
    
    return 3;
}

 

adicionado 1 minuto depois

 

 

Se tiver interesse dê uma olhada nesse código de um jogo da velha que fiz faz um tempo e postei nesse outro tópico:

 

 

  • Curtir 3
Link para o comentário
Compartilhar em outros sites

Foi mal, esqueci que tinha o facilitador.h.

Ta ai.

// Limpa tela;
void Clean(){
	system("CLS");
}

// Limpa buffer;
void limpabuffer(){
	setbuf(stdin, NULL);
}

// Pula linha;
void pulalinha(){
	printf("\n");
}

// Nome programa;
void titulo(char nome[50]){
	printf("\n\t\t\t\t | --------------- %s --------------- |\n", nome);
}

// Pausa;
void pausa(){
	printf("\n\t");
	system("pause");
}

 

adicionado 5 minutos depois

@devair1010 Eu tinha feito ele faz algum tempo, então não me recordo quanto tempo.

Eu tava mexendo em uns arquivos aqui e vi ele, pensei em tentar melhorar algumas coisas. Levou dois dias (entre trabalho e faculdade) para modificar ele. O código original tinha quase 700 linhas 😐.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@isrnick É para verificar se todas as casas da grade são diferentes de ' ', ou seja, se a grade estiver completa e mesmo assim ninguém formar um trio. Eu tava analisando a correção do verify que você fez, não seria melhor eu ter feito um laço for com um contador para verificar se todas as casas estão ocupadas?

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

32 minutos atrás, Lucas.Zottis disse:

Eu tava analisando a correção do verify que você fez, não seria melhor eu ter feito um laço for com um contador para verificar se todas as casas estão ocupadas?

 

No caso do empate? Pode sim, conta quantos ' ' tem e se for igual a 0 retorna deu empate.

 

Também pode fazer assim:

    int tied = 1;
    for (i=0; i<9; i++){
        if (house[i] == ' '){
            tied = 0;
            break;
        }
    }
    if (tied) return 0;

Ou seja, procura por ' ' no vetor todo, se encontrar algum não empatou (tied=0) então pode parar de procurar (break).

 

Obs: tied = empatou em inglês também poderia usar draw ou broke/break even.

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

@isrnick Obrigado pelas dicas.

Deu uma boa melhorada com elas, mas sinto que o código desse jogo ainda não está bom.

Eu estava testando o jogo e após algum tempo jogando, deu algum bug quando eu estava no meio do jogo que saiu sozinho da partida, voltando aos menus e saindo do jogo.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Tem sérios problemas de recursão descontrolada no código, seu programa chama as funções mas nunca finaliza e retorna delas, pois ao invés de usar return ou deixar chegar ao fim do código da função (quando a função é void) você faz uma chamada para uma nova instancia da função do nível anterior.

 

Veja um exemplo do que seu programa pode fazer ao chamar novamente as funções (ao invés de retornar):

 

main -> Menu -> Gamemode -> VersusCOM -> GameMode -> Menu -> GameMode -> VersusHuman

 

Observe que toda vez você chama a função e então no exemplo acima tem 3 funções Gamemode carregadas, 2 Menu, e 1 VersusCom carregados na memória, incluindo as variáveis criadas nelas que não está mais usando, enquanto está jogando no VersusHuman.

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

Este é meu programa de Jogo da Velha, uma implementação que fiz a alguns anos, possui:

Algoritmo AlphaBeta Minimax para jogar.

Tabuleiro em BitBoard.

 

Segue o Código:

 

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

typedef enum
{
	None = 0,
	TL = 1, TC = 2, TR = 4,
	ML = 8, MC = 16, MR = 32,
	BL = 64, BC = 128, BR = 256,
	TopRow = TL | TC | TR,
	MiddleRow = ML | MC | MR,
	BottomRow = BL | BC | BR,
	LeftColumn = TL | ML | BL,
	CenterColumn = TC | MC | BC,
	RightColumn = TR | MR | BR,
	Diagonal1 = TL | MC | BR,
	Diagonal2 = TR | MC | BL,
	All = TopRow | MiddleRow | BottomRow
} GridCells;

typedef struct {
	GridCells Current;
	GridCells Opponent;
	bool CurrentIsO;
} Grid;

typedef struct {
	int count;
	GridCells items[9];
} EnumerableGridCells;

Grid ttt_new_grid(GridCells current, GridCells opponent, bool isO);
Grid ttt_new_grid_empty(void);
bool ttt_check(GridCells state, GridCells target);
bool ttt_can_move(const Grid* grid, GridCells target);
bool ttt_make_move(Grid* grid, GridCells target);
bool ttt_check_win(GridCells target);
bool ttt_current_is_loser(const Grid* this);
bool ttt_is_draw(const Grid* grid);
bool ttt_is_finished(const Grid* grid);

Grid ttt_make_move_new_grid(Grid* grid, GridCells target);
void ttt_get_moves(const Grid* grid, EnumerableGridCells* valid_moves);

int alphabeta_minimax(Grid* grid, GridCells* best);
void ttt_print_grid(const Grid* this);

void ttt_human_player(Grid* grid, GridCells* target);
void ttt_ia_player(Grid* grid, GridCells* target);

void ttt_new_game(void (*player1)(Grid*, GridCells*), void (*player2)(Grid*, GridCells*));

bool want_new_game();

int main()
{
	bool player1_is_human = true;

	while (true)
	{
		if (player1_is_human)
			ttt_new_game(ttt_human_player, ttt_ia_player);
		else
			ttt_new_game(ttt_ia_player, ttt_human_player);
		if (!want_new_game())
			break;
		player1_is_human = !player1_is_human;
	}

	return 0;
}

Grid ttt_new_grid(GridCells current, GridCells opponent, bool isO)
{
	Grid result;
	result.Current = current;
	result.Opponent = opponent;
	result.CurrentIsO = isO;

	return result;
}

Grid
ttt_new_grid_empty()
{
	Grid result;
	result.Current = None;
	result.Opponent = None;
	result.CurrentIsO = false;

	return result;
}

inline bool inline_ttt_check(GridCells state, GridCells target)
{
	return (state & target) == target;
}

bool ttt_check(GridCells state, GridCells target)
{
	return (state & target) == target;
}

bool ttt_can_move(const Grid* grid, GridCells target)
{
	if (target == None)
		return false;
	if (ttt_check(grid->Current, target))
		return false;
	if (ttt_check(grid->Opponent, target))
		return false;

	return true;
}

bool ttt_make_move(Grid* grid, GridCells target)
{
	if (!ttt_is_finished(grid) && ttt_can_move(grid, target))
	{
		*grid = ttt_new_grid(grid->Opponent, grid->Current | target, !grid->CurrentIsO);
		return true;
	}
	return false;
}

Grid ttt_make_move_new_grid(Grid* grid, GridCells target)
{
	return ttt_new_grid(grid->Opponent, grid->Current | target, !grid->CurrentIsO);
}

bool ttt_check_win(GridCells target)
{
	if (ttt_check(target, TopRow))
		return true;
	if (ttt_check(target, MiddleRow))
		return true;
	if (ttt_check(target, BottomRow))
		return true;
	if (ttt_check(target, LeftColumn))
		return true;
	if (ttt_check(target, CenterColumn))
		return true;
	if (ttt_check(target, RightColumn))
		return true;
	if (ttt_check(target, Diagonal1))
		return true;
	if (ttt_check(target, Diagonal2))
		return true;

	return false;
}

bool ttt_current_is_loser(const Grid* grid)
{
	return ttt_check_win(grid->Opponent);
}

bool ttt_is_draw(const Grid* grid)
{
	if (!ttt_check(grid->Opponent | grid->Current, All))
		return false;

	return !ttt_current_is_loser(grid);
}

bool ttt_is_finished(const Grid* grid)
{
	return ttt_is_draw(grid) || ttt_current_is_loser(grid);
}

void ttt_get_moves(const Grid* grid, EnumerableGridCells* valid_moves)
{
	valid_moves->count = 0;

	if (ttt_current_is_loser(grid))
		return;

	GridCells occupation = grid->Current | grid->Opponent;

	if (!ttt_check(occupation, MC))
		valid_moves->items[valid_moves->count++] = MC;
	if (!ttt_check(occupation, TL))
		valid_moves->items[valid_moves->count++] = TL;
	if (!ttt_check(occupation, TR))
		valid_moves->items[valid_moves->count++] = TR;
	if (!ttt_check(occupation, BL))
		valid_moves->items[valid_moves->count++] = BL;
	if (!ttt_check(occupation, BR))
		valid_moves->items[valid_moves->count++] = BR;
	if (!ttt_check(occupation, ML))
		valid_moves->items[valid_moves->count++] = ML;
	if (!ttt_check(occupation, MR))
		valid_moves->items[valid_moves->count++] = MR;
	if (!ttt_check(occupation, TC))
		valid_moves->items[valid_moves->count++] = TC;
	if (!ttt_check(occupation, BC))
		valid_moves->items[valid_moves->count++] = BC;
}

static int alphabeta_minimax_depth(Grid* grid, GridCells* best, int alpha, int beta, int depth)
{
	*best = None;
	int bestResult = -10;
	GridCells garbage;

	if (ttt_current_is_loser(grid))
		return -10 + depth;

	if (ttt_is_draw(grid))
		return 0;

	EnumerableGridCells moves;
	ttt_get_moves(grid, &moves);
	int i;
	for (i = 0; i < moves.count; i++)
	{
		int move = moves.items[i];

		Grid other = ttt_make_move_new_grid(grid, move);
		alpha = -alphabeta_minimax_depth(&other, &garbage, -beta, -alpha, depth + 1);

		if (beta <= alpha)
			return alpha;

		if (alpha > bestResult)
		{
			*best = move;
			bestResult = alpha;
		}
	}
	return bestResult;
}

int alphabeta_minimax(Grid* grid, GridCells* best)
{
	return alphabeta_minimax_depth(grid, best, -10, +10, 1);
}

static char ttt_get_char(const Grid* grid, GridCells target)
{
	if (ttt_check(grid->Current, target))
		return grid->CurrentIsO ? 'O' : 'X';
	if (ttt_check(grid->Opponent, target))
		return grid->CurrentIsO ? 'X' : 'O';
	return ' ';
}

void ttt_print_grid(const Grid* this)
{
	printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
	printf("     |     |     \n");
	printf("  %c  |  %c  |  %c  \n",
		ttt_get_char(this, TL), ttt_get_char(this, TC), ttt_get_char(this, TR));
	printf("     |     |     \n");
	printf("-----------------\n");
	printf("     |     |     \n");
	printf("  %c  |  %c  |  %c  \n",
		ttt_get_char(this, ML), ttt_get_char(this, MC), ttt_get_char(this, MR));
	printf("     |     |     \n");
	printf("-----------------\n");
	printf("     |     |     \n");
	printf("  %c  |  %c  |  %c  \n",
		ttt_get_char(this, BL), ttt_get_char(this, BC), ttt_get_char(this, BR));
	printf("     |     |     \n");
}

size_t get_char_buffer(char* buffer, size_t size)
{
	size_t index = 0;
	int c;
	while ((c = fgetc(stdin)) != '\r' && c != '\n' && c != EOF)
		if (index + 1 < size)
			buffer[index++] = c;
	if (c == '\r' && (c = fgetc(stdin)) != '\n' && c != EOF)
		ungetc(c, stdin);
	buffer[index] = '\0';
	return index;
}

void ttt_human_player(Grid* grid, GridCells* target)
{
	printf("Entre com o lance: ");
	do
	{
		char buffer[3];
		get_char_buffer(buffer, 3);
		if (strcmp(buffer, "1") == 0 || strcmp(buffer, "TL") == 0)
			*target = TL;
		else if (strcmp(buffer, "2") == 0 || strcmp(buffer, "TC") == 0)
			*target = TC;
		else if (strcmp(buffer, "3") == 0 || strcmp(buffer, "TR") == 0)
			*target = TR;
		else if (strcmp(buffer, "4") == 0 || strcmp(buffer, "ML") == 0)
			*target = ML;
		else if (strcmp(buffer, "5") == 0 || strcmp(buffer, "MC") == 0)
			*target = MC;
		else if (strcmp(buffer, "6") == 0 || strcmp(buffer, "MR") == 0)
			*target = MR;
		else if (strcmp(buffer, "7") == 0 || strcmp(buffer, "BL") == 0)
			*target = BL;
		else if (strcmp(buffer, "8") == 0 || strcmp(buffer, "BC") == 0)
			*target = BC;
		else if (strcmp(buffer, "9") == 0 || strcmp(buffer, "BR") == 0)
			*target = BR;
		else
			*target = None;
	}
	while(!ttt_can_move(grid, *target));
}

void ttt_ia_player(Grid* grid, GridCells* target)
{
	alphabeta_minimax(grid, target);
}

void ttt_new_game(void (*player1)(Grid*, GridCells*), void (*player2)(Grid*, GridCells*))
{
	Grid grid_game = ttt_new_grid_empty();
	bool current_player1 = true;
	while (!ttt_is_finished(&grid_game))
	{
		ttt_print_grid(&grid_game);
		GridCells move = None;
		if (current_player1)
			player1(&grid_game, &move);
		else
			player2(&grid_game, &move);

		grid_game = ttt_make_move_new_grid(&grid_game, move);
		current_player1 = !current_player1;
	}
	ttt_print_grid(&grid_game);
	printf("Jogador %c ganhou!\n\n\n", grid_game.CurrentIsO ? 'X' : 'O');
}

bool want_new_game()
{
	while (true)
	{
		printf("Novo jogo [Y/N]? ");
		char buffer[2];
		get_char_buffer(buffer, 2);
		if (strcmp(buffer, "Y") == 0 || strcmp(buffer, "y") == 0)
			return true;
		if (strcmp(buffer, "N") == 0 || strcmp(buffer, "n") == 0)
			return false;
	}
}

 

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois...
/*
    Nome do programa: Tic Tac Toe
    Objetivo do programa: Fazer um jogo da velha para console
    Nome do programador: Lucas Zottis
    Data de criação: 08/05/2020
*/
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <windows.h>
#include <string.h>
#define TAM 8

// Dados sobre os players (a maquina conta como player e será inicializado no começo do jogo);
typedef struct {
	// Nome do player, a maquina será COM;
	char name[10];
	// Dados sobre partidas, vitórias, empates e derrotas;
	int match, win, tie, lose;
}Player;
// grade do jogo;
char house[TAM];
// Referenciação dos players;
Player player1;
Player player2;
Player com;

/* Declaração das funções */
int Menu(void);
void GameMode(void);
void VersusCOM(void);
void VersusHuman(void);
int ExitProgram(void);
void InitHouses(void);
void Initiate(void);
void ShowHouses(void);
int HumanMove(int turn);
int IAMove(void);
int EmptyHouse(int spot, int turn);
int Verify(void);

int main() {
	// Inicializações;
	Initiate();
	// CONFIGURANDO PARA O IDIOMA PORTUGUES;
	setlocale(LC_ALL, "Portuguese");
	int i, j, leave;
	// Apresentação;
	char intro [5][40] = {
		"\n Olá!",
		"Prazer, eu sou o Cidão.",
		"Sejam bem vindos ao Tic Tac Toe.",
		"Espero que se divirtam.",
		"Tenham um bom jogo e boa sorte.\n",
	};
	printf("* TIC - TAC - TOE *\n");;
	for (i = 0; i < 5; i++) {
		printf(" ");
		for (j = 0; j < 40; j++) {
			printf("%c", intro[i][j]);
		}
		printf("\n");
	}
	system("pause");
	system("CLS");
	do {
        leave = Menu();
	} while (leave == 0);
	return 0;
}
// Menu Principal;
int Menu(void) {
	int menu;
	do{ // Menu principal;
		printf("* TIC - TAC - TOE *\n");
		printf("\n 1 - Jogar");
		printf("\n 2 - Estatísticas");
		printf("\n 0 - Fechar");
		printf("\n\n | Opção: ");
		scanf("%d", &menu);
		if (menu < 0 || menu > 2){
			printf("\n Opção inválida!");
			printf("\n Informe uma opção válida do menu.");
			sleep(2);
		}
		system("CLS");
	}while(menu < 0 || menu > 2);
	switch(menu){
		case 1: // Menu de seleção de modo de jogo;
			GameMode();
		break;
		case 2: // Quadro de dados sobre partidas;
			printf("Aqui terá dados sobre as partidas.");
			Menu();
		break;
		case 0: // Fechar programa;
            return ExitProgram();
		break;
	}
}
// Modo de jogo;
void GameMode(void){
	int menu;
	do{ // Menu modo de Jogo;
		printf("* TIC - TAC - TOE *\n");;
		printf("\n 1 - vs COM");
		printf("\n 2 - vs Player");
		printf("\n 0 - Voltar");
		printf("\n\n | Opção: ");
		scanf("%d", &menu);
		if (menu < 0 || menu > 2){
			printf("\n Opção inválida!");
			printf("\n Informe uma opção válida do menu.");
			sleep(2);
		}
		system("CLS");
	}while(menu < 0 || menu > 2);
	switch (menu){
		case 1: // Jogar vs COM;
			VersusCOM();
		break;
		case 2: // Jogar vs Player;
			VersusHuman();
		break;
		case 0: // Voltar para o menu principal;
			system("CLS");
		break;
	}
}
// Versus COM;
void VersusCOM(void) {
	int winner = 3;
	int turn = 1;
	InitHouses();
	setbuf(stdin, NULL);
	printf("* TIC - TAC - TOE *\n");
	printf("\n\n Player 1: ");
	gets(player1.name);
	system("CLS");
	do { // Execução do jogo;
		printf("* TIC - TAC - TOE *\n");
		ShowHouses();
		switch (turn) {
			case 1:
                turn = HumanMove(turn);
			break;
			case 2:
				turn = IAMove();
			break;
		}
		winner = Verify();
		system("CLS");
	} while (winner > 2);
	switch (winner) { // Verifica quem ganhou;
		case 1: // Player 1 ganhou!!
			printf("* TIC - TAC - TOE *\n");
			ShowHouses();
			printf("\n\n %s ganhou!!", player1.name);
		break;
		case 2: // Player 2 ganhou!!
			printf("* TIC - TAC - TOE *\n");
			ShowHouses();
			printf("\n\n %s ganhou!!", com.name);
		break;
		default: // Deu empate!!
			printf("* TIC - TAC - TOE *\n");
			ShowHouses();
			printf("\n\n %s e %s empataram!!", player1.name, com.name);
		break;
	}
	sleep(2);
	system("CLS");
}
// Versus Humano;
void VersusHuman(void) {
	int winner = 3;
	int turn = 1;
	InitHouses();
	setbuf(stdin, NULL);
	printf("* TIC - TAC - TOE *\n");
	printf("\n\n Player 1: ");
	gets(player1.name);
	printf("\n\n Player 2: ");
	gets(player2.name);
	system("CLS");
	do { // Execução do jogo;
		printf("* TIC - TAC - TOE *\n");
		ShowHouses();
		switch (turn) {
			case 1:
                turn = HumanMove(turn);
			break;
			case 2:
                turn = HumanMove(turn);
			break;
		}
		winner = Verify();
		system("CLS");
	} while (winner > 2);
	switch (winner) { // Verifica quem ganhou;
		case 1: // Player 1 ganhou!!
			printf("* TIC - TAC - TOE *\n");
			ShowHouses();
			printf("\n\n %s ganhou!!", player1.name);
		break;
		case 2: // Player 2 ganhou!!
			printf("* TIC - TAC - TOE *\n");
			ShowHouses();
			printf("\n\n %s ganhou!!", player2.name);
		break;
		default: // Deu empate!!
			printf("* TIC - TAC - TOE *\n");
			ShowHouses();
			printf("\n\n %s e %s empataram!!", player1.name, player2.name);
		break;
	}
	sleep(2);
	system("CLS");
}
// Sair programa;
int ExitProgram(void) {
	char leave;
	int setExit = 0;
	do { // Sair do programa;
		printf("* TIC - TAC - TOE *\n");
		printf("\n Deseja sair [S/N]? ");
		setbuf(stdin, NULL);
		scanf("%c", &leave);
		getchar();
		if ((leave == 's') || (leave == 'S')) {
			system("CLS");
			printf("* TIC - TAC - TOE *\n");
			printf("\n Tchau!!");
			sleep(1);
			return 1;
		} else {
			if ((leave == 'n') || (leave == 'N')) {
				system("CLS");
				return 0;
			} else {
				printf("\n Opção invalida!!");
			}
		}
		Sleep(750);
		system("CLS");
	} while ((leave != 's' && leave != 'S') || (leave != 'n' && leave != 'N'));
}
// Inicializador de grade;
void InitHouses(void) {
	int i;
	// Inicialização da grade;
	for (i = 0; i <= 9; i++) {
		house[i] = ' ';
	}
}
// Mostra grade;
void ShowHouses(void) {
	int i, count;
	printf("\n");
	printf(" ");
	for (i = 0; i <= 2; i++) {
		printf("|%c|", house[i]);
	}
	printf("\n");
	printf(" ");
	for (i = 3; i <= 5; i++) {
		printf("|%c|", house[i]);
	}
	printf("\n");
	printf(" ");
	for (i = 6; i <= 8; i++) {
		printf("|%c|", house[i]);
	}
}
// Inicializações;
void Initiate(void){
	// Player 1;
	player1.match = 0;
	player1.win = 0;
	player1.tie = 0;
	player1.lose = 0;
	// Player 2;
	player2.match = 0;
	player2.win = 0;
	player2.tie = 0;
	player2.lose = 0;
	// COM;
	strcpy(com.name, "Jarvas");
	com.match = 0;
	com.win = 0;
	com.tie = 0;
	com.lose = 0;
	// Inicialização da grade;
	InitHouses();
}
// Jogada humana;
int HumanMove(int turn) {
	int spot, keepItOn;
	switch (turn) {
		case 1:
            printf("\n\n -> %s", player1.name);
            printf("\n Local [1-9]: ");
            scanf("%d", &spot);
            keepItOn = EmptyHouse(spot, turn);
		break;
		case 2:
            printf("\n\n -> %s", player2.name);
            printf("\n Local [1-9]: ");
            scanf("%d", &spot);
            keepItOn = EmptyHouse(spot, turn);
        break;
	}
	return keepItOn;
}
// Jogada IA;
int IAMove(void) {
	int spot, i;
	// Definindo casa para jogar;
	srand(time(NULL));
	spot = rand() % TAM;
	// Verifica se local está ocupado;
	if (house[spot] == ' ') {
		house[spot] = 'O';
        return 1;
	} else {
		char dots[3] = "...";
		char *s = dots;
		printf("\n\n -> %s está Pensando", com.name);
		for (i = 0; i < strlen(dots); i++) {
			printf("%c", *s);
			Sleep(200);
		}
		return 2;
	}
}
// Verifica se local está ocupado;
int EmptyHouse(int spot, int turn) {
	switch (turn) {
		case 1:
            if (house[spot - 1] == ' '){
                house[spot - 1] = 'X';
                // Retorna 2 para passar o turno após jogado com sucesso;
                return 2;
            } else {
                printf(" Ocupado!!");
                Sleep(750);
                // Retorna 1 para não passar o turno sem jogar
                return 1;
            }
		break;

		case 2:
            if (house[spot - 1] == ' '){
                house[spot - 1] = 'O';
                // Retorna 2 para passar o turno após jogado com sucesso;
                return 1;
            } else {
                printf(" Ocupado!!");
                Sleep(750);
                // Retorna 1 para não passar o turno sem jogar
                return 2;
            }
		break;
	}
}
// Verifica se alguem ganhou;
int Verify(void) {
    int i;
    // Verifica linhas;
    for(i=0; i<3; i++){
        if(house[i*3] == house[i*3+1] && house[i*3] == house[i*3+2]){
            if(house[i*3] == 'X') return 1;
            if(house[i*3] == 'O') return 2;
        }
    }
    // Verifica Colunas:
    for(i=0; i<3; i++){
        if(house[i] == house[i+3] && house[i] == house[i+6]){
            if(house[i] == 'X') return 1;
            if(house[i] == 'O') return 2;
        }
    }
    // Verifica Diagonal Principal:
    if(house[0] == house[4] && house[0] == house[8]){
        if(house[0] == 'X') return 1;
        if(house[0] == 'O') return 2;
    }
    // Verifica Diagonal Secundária
    if(house[2] == house[4] && house[2] == house[6]){
        if(house[2] == 'X') return 1;
        if(house[2] == 'O') return 2;
    }
    char tie = 1;
    for (i = 0; i <= TAM; i++) {
    	if (house[i] == ' ') {
    		tie = 0;
    		break;
		}
	}
	if (tie) return 0;
    return 3;
}

E ai, após algum tempo, consegui achar um tempinho para ver as dicas aqui.

Dei uma analisada por cima nos códigos enviados, mas não consegui rodar eles ainda.

Fiz algumas correções nas dicas que deram e alguns problemas que encontrei enquanto testava

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!