-
Tic-tac-toe
I was trying to write a tic-tac-toe game and I came up with this. It *works* but lacks intelligence. I was wondering if anyone could help me make it smart. I was looking at the negamax algorithm but I don't know how to put it to work on my program. Thanks.
Code:
#include <iostream>
#include <string>
#include <cctype>
#include <sstream>
#include <windows.h>
void mostrar_matrix(void);
char movimento_jogador(void);
char movimento_computador(void);
bool posicao_valida(std::string &, int &, int &, char &);
char analizar_matrix(void);
char matrix[3][3];
int main()
{
char resultado = ' ';
// muda o nome do console
SetConsoleTitle("Jogo da velha!");
// coloca um espaço em branco em todas as posições da matrix
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
matrix[i][j] = ' ';
mostrar_matrix();
while(resultado == ' '){
resultado = movimento_jogador();
mostrar_matrix();
if(resultado == 'X')
break;
resultado = movimento_computador();
Sleep(2000);
mostrar_matrix();
}
if(resultado == 'X'){
std::cout << "Voce ganhou! ";
std::cin.get();
}
else{
std::cout << "Eu ganhei! ";
std::cin.get();
}
return 0;
}
void mostrar_matrix(void)
{
// limpa a tela
// funciona no Visual C++ 7.0 e pode não ser portável...
system("cls");
std::cout << " A B C\n\n";
for(int j = 0; j < 3; j++){
std::cout << j + 1 << " "
<< matrix[j][0] << " | "
<< matrix[j][1] << " | "
<< matrix[j][2] << '\n';
if(j != 2)
std::cout << " ---|---|---\n";
}
std::cout << '\n';
}
char movimento_jogador(void)
{
int x, y;
char z;
std::string posicao;
do{
std::cout << "Posicao para o X: ";
std::getline(std::cin, posicao);
}while(!posicao_valida(posicao, x, y, z));
matrix[x][y] = 'X';
return analizar_matrix();
}
bool posicao_valida(std::string &posicao, int &x, int &y, char &z)
{
// testa se foi digitado alguma coisa
if(posicao.length() == 0){
std::cout << "Voce precisa especificar uma posicao para o X ";
std::cin.get();
mostrar_matrix();
return false;
}
// testa se foram digitados mais do que dois caracteres
if(posicao.length() > 2){
std::cout << "Nao digite mais do que dois caracteres ";
std::cin.get();
mostrar_matrix();
return false;
}
// testa o primeiro caractere para ver se ele é um
// número e o segundo para ver se ele é uma letra
if(!isdigit(posicao[0]) || !isalpha(posicao[1])){
std::cout << "Digite um numero e uma letra. Exemplo: 1a ";
std::cin.get();
mostrar_matrix();
return false;
}
// preciso colocar o primeiro caractere da string posicao
// em outra string pois não posso passar só o index (posicao[0])
// para a istringstream pois assim o valor de x não será modificado
std::string foo;
foo.assign(posicao, 0, 1);
// converte o primeiro caractere da string posicao para int
std::istringstream bar(foo);
bar >> x;
// testa pra ver se a parte numérica da posição indicada pelo
// usuário é um número de 1 até 3
if(x < 1 || x > 3){
std::cout << "Numero invalido ";
std::cin.get();
mostrar_matrix();
return false;
}
// subtrai 1 do x pq o array começa a ser contado do 0
x--;
// coloca a parte alfabética da posição indicada pelo usuário no char z
z = posicao[1];
// testa o char z para ver se o que o usuário digitou é uma letra de A até C
if(toupper(z) < 'A' || toupper(z) > 'C'){
std::cout << "Letra invalida ";
std::cin.get();
mostrar_matrix();
return false;
}
// dá o valor para o y de acordo com a letra escolhida
// A = 0, B = 1 e C = 2...
switch(toupper(z)){
case 'A':
y = 0;
break;
case 'B':
y = 1;
break;
case 'C':
y = 2;
break;
}
// testa se o usuário não está tentando marcar um lugar ocupado
if(matrix[x][y] != ' '){
std::cout << "Esta posicao ja esta ocupada ";
std::cin.get();
mostrar_matrix();
return false;
}
return true;
}
char analizar_matrix(void)
{
int i;
// testa as linhas
for(i = 0; i < 3; i++)
if(matrix[i][0] == matrix[i][1] && matrix[i][0] == matrix[i][2])
return matrix[i][0];
// testa as colunas
for(i = 0; i < 3; i++)
if(matrix[0][i] == matrix[1][i] && matrix[0][i] == matrix[2][i])
return matrix[0][i];
// testa as diagonais
if(matrix[0][0] == matrix[1][1] && matrix[1][1] == matrix[2][2])
return matrix[0][0];
if(matrix[0][2] == matrix[1][1] && matrix[1][1] == matrix[2][0])
return matrix[0][2];
return ' ';
}
char movimento_computador(void)
{
int i, j;
static bool flag00 = false; /* matrix[0][0] */
static bool flag01 = false; /* matrix[0][1] */
static bool flag02 = false; /* matrix[0][2] */
static bool flag10 = false; /* matrix[1][0] */
static bool flag11 = false; /* matrix[1][1] */
static bool flag12 = false; /* matrix[1][2] */
static bool flag20 = false; /* matrix[2][0] */
static bool flag21 = false; /* matrix[2][1] */
static bool flag22 = false; /* matrix[2][2] */
if(flag00 == false)
{
if(matrix[0][0] == 'X')
{
while(1)
{
if((matrix[1][0] == 'X') && (matrix[2][0] == ' '))
{
matrix[2][0] = 'O';
break;
}
else if((matrix[2][0] == 'X') && (matrix[1][0] == ' '))
{
matrix[1][0] = 'O';
break;
}
else if((matrix[0][1] == 'X') && (matrix[0][2] == ' '))
{
matrix[0][2] = 'O';
break;
}
else if((matrix[0][2] == 'X') && (matrix[0][1] == ' '))
{
matrix[0][1] = 'O';
break;
}
else if((matrix[1][1] == 'X') && (matrix[2][2] == ' '))
{
matrix[2][2] = 'O';
break;
}
else
{
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
if(matrix[i][j] == ' ')
break;
if(matrix[i][j] == ' ')
break;
}
matrix[i][j] = 'O';
break;
}
}
flag00 = true;
}
}
if(flag01 == false)
{
if(matrix[0][1] == 'X')
{
while(1)
{
if((matrix[0][0] == 'X') && (matrix[0][2] == ' '))
{
matrix[0][2] = 'O';
break;
}
else if((matrix[0][2] == 'X') && (matrix[0][0] == ' '))
{
matrix[0][0] = 'O';
break;
}
else if((matrix[1][1] == 'X') && (matrix[2][1] == ' '))
{
matrix[2][1] = 'O';
break;
}
else
{
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
if(matrix[i][j] == ' ')
break;
if(matrix[i][j] == ' ')
break;
}
matrix[i][j] = 'O';
break;
}
}
flag01 = true;
}
}
if(flag02 == false)
{
if(matrix[0][2] == 'X')
{
while(1)
{
if((matrix[0][1] == 'X') && (matrix[0][0] == ' '))
{
matrix[0][0] = 'O';
break;
}
else if((matrix[0][0] == 'X') && (matrix[0][1] == ' '))
{
matrix[0][1] = 'O';
break;
}
else if((matrix[1][1] == 'X') && (matrix[2][0] == ' '))
{
matrix[2][0] = 'O';
break;
}
else if((matrix[2][0] == 'X') && (matrix[1][1] == ' '))
{
matrix[1][1] = 'O';
break;
}
else if((matrix[1][2] == 'X') && (matrix[2][2] == ' '))
{
matrix[2][2] = 'O';
break;
}
else
{
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
if(matrix[i][j] == ' ')
break;
if(matrix[i][j] == ' ')
break;
}
matrix[i][j] = 'O';
break;
}
}
flag02 = true;
}
}
if(flag10 == false)
{
if(matrix[1][0] == 'X')
{
while(1)
{
if((matrix[0][0] == 'X') && (matrix[2][0] == ' '))
{
matrix[2][0] = 'O';
break;
}
else if((matrix[2][0] == 'X') && (matrix[0][0] == ' '))
{
matrix[0][0] = 'O';
break;
}
else if((matrix[1][1] == 'X') && (matrix[1][2] == ' '))
{
matrix[1][2] = 'O';
break;
}
else
{
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
if(matrix[i][j] == ' ')
break;
if(matrix[i][j] == ' ')
break;
}
matrix[i][j] = 'O';
break;
}
}
flag10 = true;
}
}
if(flag11 == false)
{
if(matrix[1][1] == 'X')
{
while(1)
{
if((matrix[0][1] == 'X') && (matrix[2][1] == ' '))
{
matrix[2][1] = 'O';
break;
}
else if((matrix[2][1] == 'X') && (matrix[0][1] == ' '))
{
matrix[0][1] = 'O';
break;
}
else if((matrix[0][0] == 'X') && (matrix[2][2] == ' '))
{
matrix[2][2] = 'O';
break;
}
else if((matrix[2][2] == 'X') && (matrix[0][0] == ' '))
{
matrix[0][0] = 'O';
break;
}
else if((matrix[0][2] == 'X') && (matrix[2][0] == ' '))
{
matrix[2][0] = 'O';
break;
}
else
{
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
if(matrix[i][j] == ' ')
break;
if(matrix[i][j] == ' ')
break;
}
matrix[i][j] = 'O';
break;
}
}
flag11 = true;
}
}
if(flag12 == false)
{
if(matrix[1][2] == 'X')
{
while(1)
{
if((matrix[0][2] == 'X') && (matrix[2][2] == ' '))
{
matrix[2][2] = 'O';
break;
}
else if((matrix[2][2] == 'X') && (matrix[0][2] == ' '))
{
matrix[0][2] = 'O';
break;
}
else if((matrix[1][1] == 'X') && (matrix[1][0] == ' '))
{
matrix[1][0] = 'O';
break;
}
else
{
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
if(matrix[i][j] == ' ')
break;
if(matrix[i][j] == ' ')
break;
}
matrix[i][j] = 'O';
break;
}
}
flag12 = true;
}
}
if(flag20 == false)
{
if(matrix[2][0] == 'X')
{
while(1)
{
if((matrix[1][0] == 'X') && (matrix[0][0] == ' '))
{
matrix[0][0] = 'O';
break;
}
else if((matrix[0][0] == 'X') && (matrix[1][0] == ' '))
{
matrix[1][0] = 'O';
break;
}
else if((matrix[2][1] == 'X') && (matrix[2][2] == ' '))
{
matrix[2][2] = 'O';
break;
}
else if((matrix[2][2] == 'X') && (matrix[2][1] == ' '))
{
matrix[2][1] = 'O';
break;
}
else if((matrix[1][1] == 'X') && (matrix[0][2] == ' '))
{
matrix[0][2] = 'O';
break;
}
else
{
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
if(matrix[i][j] == ' ')
break;
if(matrix[i][j] == ' ')
break;
}
matrix[i][j] = 'O';
break;
}
}
flag20 = true;
}
}
if(flag21 == false)
{
if(matrix[2][1] == 'X')
{
while(1)
{
if((matrix[2][2] == 'X') && (matrix[2][0] == ' '))
{
matrix[2][0] = 'O';
break;
}
else if((matrix[2][0] == 'X') && (matrix[2][2] == ' '))
{
matrix[2][2] = 'O';
break;
}
else if((matrix[1][1] == 'X') && (matrix[0][1] == ' '))
{
matrix[0][1] = 'O';
break;
}
else
{
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
if(matrix[i][j] == ' ')
break;
if(matrix[i][j] == ' ')
break;
}
matrix[i][j] = 'O';
break;
}
}
flag21 = true;
}
}
if(flag22 == false)
{
if(matrix[2][2] == 'X')
{
while(1)
{
if((matrix[1][2] == 'X') && (matrix[0][2] == ' '))
{
matrix[0][2] = 'O';
break;
}
else if((matrix[0][2] == 'X') && (matrix[1][2] == ' '))
{
matrix[1][2] = 'O';
break;
}
else if((matrix[2][1] == 'X') && (matrix[2][0] == ' '))
{
matrix[2][0] = 'O';
break;
}
else if((matrix[2][0] == 'X') && (matrix[2][1] == ' '))
{
matrix[2][1] = 'O';
break;
}
else if((matrix[1][1] == 'X') && (matrix[0][0] == ' '))
{
matrix[0][0] = 'O';
break;
}
else
{
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
if(matrix[i][j] == ' ')
break;
if(matrix[i][j] == ' ')
break;
}
matrix[i][j] = 'O';
break;
}
}
flag22 = true;
}
}
return analizar_matrix();
}
-
La manera barata y fácil sería de utilizar apenas AI "duro-codificado". He googled el algoritmo nega-máx. No mire excesivamente difícil.
Siempre se preguntó lo que codifica se pareció a en idiomas diferentes. Muy bueno. :)
-
That's portuguese, not spanish. I didn't understand everything you said. Could it write it in english please?
-
oh my bad. I was just saying that most people just hard-code a static AI for tic-tac-toe.. but you obviously want to expand your AI horizons.. I googled for negamax and found many tutorials on the subject.. the code doesn't seem too overly difficult. Also, here is post of someone who was in the same situation as yourself. You will see tic-tac-toe using both the mini-max and nega-max methods of predicting the best move.