Comme le sujet l'indique, j'écris un programme sensé implémenter l'algorithme minimax dans le jeu du morpion, sauf quand je l’exécute la grille se remplie instantanément..
Je n'arrive pas à écrire la condition qui me permettrais de détecter le clic du joueur dans un des box collider, afin d'y instancier une croix et d'ensuite appeler l'algorithme minmax pour jouer le coup de l'IA en conséquence.
Si quelqu'un pouvait m'aider , je vous remercie par avance et vous fais part de mon code :
Condition_Victoire :
Code : Tout sélectionner
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MNode
{
public int x;
public int y;
public int player;
}
public class MovesAndScores
{
public int score;
public MNode point;
public MovesAndScores(int score, MNode point)
{
this.score = score;
this.point = point;
}
}
public class Condition_Victoire : MonoBehaviour {
public int nb_coup = 0;
public Gestion_Click[] case_morpion = new Gestion_Click[9];
public GameObject text_j1;
public GameObject text_j2;
public GameObject Interface_fin_de_partie;
public Text text_Gagnant;
public GameObject croix;
public GameObject rond;
MNode[,] grid = new MNode[3, 3];
public List<MovesAndScores> rootsChildrenScores;
public GameObject ui;
// Use this for initialization
void Start () {
}
public void Gestion_Affichage(int joueur)
{
if(joueur != 1)
{
text_j1.SetActive(true);
text_j2.SetActive(false);
}
else if(joueur != 2)
{
text_j1.SetActive(false);
text_j2.SetActive(true);
}
}
private void Victoire (int gagnant)
{
//Debug.Log("Le joueur " + gagnant + " a gagné ! Bravo !!");
this.transform.Rotate(-90, 0, 0);
text_j1.SetActive(false);
text_j2.SetActive(false);
if(gagnant == 0)
{
text_Gagnant.text = "Match nul ! Il n'y a pas de gagnant..";
}
else
{
text_Gagnant.text = "Le joueur " + gagnant + " a gagné ! Bravo !!";
}
Interface_fin_de_partie.SetActive(true);
}
public void Verif_Victoire()
{
if(case_morpion[0].etat_joueur == case_morpion[1].etat_joueur && case_morpion[0].etat_joueur == case_morpion[2].etat_joueur && case_morpion[0].etat_joueur != 0)// Ligne 1
{
this.Victoire(case_morpion[0].etat_joueur);
}
else if (case_morpion[3].etat_joueur == case_morpion[4].etat_joueur && case_morpion[3].etat_joueur == case_morpion[5].etat_joueur && case_morpion[3].etat_joueur != 0)// Ligne 2
{
this.Victoire(case_morpion[3].etat_joueur);
}
else if (case_morpion[6].etat_joueur == case_morpion[7].etat_joueur && case_morpion[6].etat_joueur == case_morpion[8].etat_joueur && case_morpion[6].etat_joueur != 0)// Ligne 3
{
this.Victoire(case_morpion[6].etat_joueur);
}
else if (case_morpion[0].etat_joueur == case_morpion[3].etat_joueur && case_morpion[0].etat_joueur == case_morpion[6].etat_joueur && case_morpion[0].etat_joueur != 0)// Colonne 1
{
this.Victoire(case_morpion[0].etat_joueur);
}
else if (case_morpion[1].etat_joueur == case_morpion[4].etat_joueur && case_morpion[1].etat_joueur == case_morpion[7].etat_joueur && case_morpion[1].etat_joueur != 0)// Colonne 2
{
this.Victoire(case_morpion[1].etat_joueur);
}
else if (case_morpion[2].etat_joueur == case_morpion[5].etat_joueur && case_morpion[2].etat_joueur == case_morpion[8].etat_joueur && case_morpion[2].etat_joueur != 0)// Colonne 3
{
this.Victoire(case_morpion[2].etat_joueur);
}
else if (case_morpion[0].etat_joueur == case_morpion[4].etat_joueur && case_morpion[0].etat_joueur == case_morpion[8].etat_joueur && case_morpion[0].etat_joueur != 0)// Diagonnale descendante
{
this.Victoire(case_morpion[0].etat_joueur);
}
else if (case_morpion[2].etat_joueur == case_morpion[4].etat_joueur && case_morpion[2].etat_joueur == case_morpion[6].etat_joueur && case_morpion[2].etat_joueur != 0)// Diagonale montante
{
this.Victoire(case_morpion[2].etat_joueur);
}
else if (nb_coup >= 9)
{
this.Victoire(0);
}
}
// Update is called once per frame
void Update () {
if (!isGameOver())
{
if(case_morpion[0].OnMouseDown()/*GetMouseButtonDown(0)*/ == true && isValidMove(0,0))
{
case_morpion[0].GetComponent<BoxCollider>().enabled = false;
Instantiate(croix, new Vector3((float)- 3.5, (float)-0.5,(float)3.5), Quaternion.identity);
MNode node = new MNode();
node.x = 0;
node.y = 0;
node.player = 1;
grid[node.x, node.y] = node;
callMinimax(0, 1);
MNode best = returnBestMove();
if(isValidMove(best.x, best.y))
{
Instantiate(rond, correspondance(best.x, best.y), Quaternion.identity);
best.player = 2;
grid[best.x, best.y] = best;
}
}
if (case_morpion[1].OnMouseDown()/*GetMouseButtonDown(0)*/ == true && isValidMove(0, 1))
{
case_morpion[1].GetComponent<BoxCollider>().enabled = false;
Instantiate(croix, new Vector3(0, (float)-0.5, (float)3.5), Quaternion.identity);
MNode node = new MNode();
node.x = 0;
node.y = 1;
node.player = 1;
grid[node.x, node.y] = node;
callMinimax(0, 1);
MNode best = returnBestMove();
if (isValidMove(best.x, best.y))
{
Instantiate(rond, correspondance(best.x, best.y), Quaternion.identity);
best.player = 2;
grid[best.x, best.y] = best;
}
}
if (case_morpion[2].OnMouseDown()/*GetMouseButtonDown(0)*/ == true && isValidMove(0, 2))
{
case_morpion[2].GetComponent<BoxCollider>().enabled = false;
Instantiate(croix, new Vector3((float)3.5, (float)-0.5, (float)3.5), Quaternion.identity);
MNode node = new MNode();
node.x = 0;
node.y = 2;
node.player = 1;
grid[node.x, node.y] = node;
callMinimax(0, 1);
MNode best = returnBestMove();
if (isValidMove(best.x, best.y))
{
Instantiate(rond, correspondance(best.x, best.y), Quaternion.identity);
best.player = 2;
grid[best.x, best.y] = best;
}
}
if (case_morpion[3].OnMouseDown()/*GetMouseButtonDown(0)*/ == true && isValidMove(1, 0))
{
case_morpion[3].GetComponent<BoxCollider>().enabled = false;
Instantiate(croix, new Vector3((float)-3.5, (float)-0.5, 0), Quaternion.identity);
MNode node = new MNode();
node.x = 1;
node.y = 0;
node.player = 1;
grid[node.x, node.y] = node;
callMinimax(0, 1);
MNode best = returnBestMove();
if (isValidMove(best.x, best.y))
{
Instantiate(rond, correspondance(best.x, best.y), Quaternion.identity);
best.player = 2;
grid[best.x, best.y] = best;
}
}
if (case_morpion[4].OnMouseDown()/*GetMouseButtonDown(0)*/ == true && isValidMove(1, 1))
{
case_morpion[4].GetComponent<BoxCollider>().enabled = false;
Instantiate(croix, new Vector3(0, (float)-0.5, 0), Quaternion.identity);
MNode node = new MNode();
node.x = 1;
node.y = 1;
node.player = 1;
grid[node.x, node.y] = node;
callMinimax(0, 1);
MNode best = returnBestMove();
if (isValidMove(best.x, best.y))
{
Instantiate(rond, correspondance(best.x, best.y), Quaternion.identity);
best.player = 2;
grid[best.x, best.y] = best;
}
}
if (case_morpion[5].OnMouseDown()/*GetMouseButtonDown(0)*/ == true && isValidMove(1, 2))
{
case_morpion[5].GetComponent<BoxCollider>().enabled = false;
Instantiate(croix, new Vector3((float)3.5, (float)-0.5, 0), Quaternion.identity);
MNode node = new MNode();
node.x = 1;
node.y = 2;
node.player = 1;
grid[node.x, node.y] = node;
callMinimax(0, 1);
MNode best = returnBestMove();
if (isValidMove(best.x, best.y))
{
Instantiate(rond, correspondance(best.x, best.y), Quaternion.identity);
best.player = 2;
grid[best.x, best.y] = best;
}
}
if (case_morpion[6].OnMouseDown()/*GetMouseButtonDown(0)*/ == true && isValidMove(2, 0))
{
case_morpion[6].GetComponent<BoxCollider>().enabled = false;
Instantiate(croix, new Vector3((float)-3.5, (float)-0.5, (float)-3.5), Quaternion.identity);
MNode node = new MNode();
node.x = 2;
node.y = 0;
node.player = 1;
grid[node.x, node.y] = node;
callMinimax(0, 1);
MNode best = returnBestMove();
if (isValidMove(best.x, best.y))
{
Instantiate(rond, correspondance(best.x, best.y), Quaternion.identity);
best.player = 2;
grid[best.x, best.y] = best;
}
}
if (case_morpion[7].OnMouseDown()/*GetMouseButtonDown(0)*/ == true && isValidMove(2, 1))
{
case_morpion[7].GetComponent<BoxCollider>().enabled = false;
Instantiate(croix, new Vector3(0, (float)-0.5, (float)-3.5), Quaternion.identity);
MNode node = new MNode();
node.x = 2;
node.y = 1;
node.player = 1;
grid[node.x, node.y] = node;
callMinimax(0, 1);
MNode best = returnBestMove();
if (isValidMove(best.x, best.y))
{
Instantiate(rond, correspondance(best.x, best.y), Quaternion.identity);
best.player = 2;
grid[best.x, best.y] = best;
}
}
if (case_morpion[8].OnMouseDown()/*GetMouseButtonDown(0)*/ == true && isValidMove(2, 2))
{
case_morpion[8].GetComponent<BoxCollider>().enabled = false;
Instantiate(croix, new Vector3((float)3.5, (float)-0.5, (float)-3.5), Quaternion.identity);
MNode node = new MNode();
node.x = 2;
node.y = 2;
node.player = 1;
grid[node.x, node.y] = node;
callMinimax(0, 1);
MNode best = returnBestMove();
if (isValidMove(best.x, best.y))
{
Instantiate(rond, correspondance(best.x, best.y), Quaternion.identity);
best.player = 2;
grid[best.x, best.y] = best;
}
}
}
}
private Vector3 correspondance(int a, int b)
{
double z = 0;
double x = 0;
if(a == 0)
{
z = 3.5;
}
else if(a == 1)
{
z = 0;
}
else
{
z = -3.5;
}
if(b == 0)
{
x = -3.5;
}
else if(b == 1)
{
x = 0;
}
else
{
x = 3.5;
}
return new Vector3((float)x, 0, (float)z);
}
public MNode returnBestMove()
{
int MAX = -100000;
int best = -1;
//iterates through rootsChildrenScores to get the best move
for (int i = 0; i < rootsChildrenScores.Count; i++)
{
//also makes sure that the position in the grid is not occupied
if (MAX < rootsChildrenScores[i].score && isValidMove(rootsChildrenScores[i].point.x, rootsChildrenScores[i].point.y))
{
MAX = rootsChildrenScores[i].score;
best = i;
}
}
if (best > -1)
return rootsChildrenScores[best].point;
MNode blank = new MNode();
blank.x = 0;
blank.y = 0;
return blank;
}
private bool isValidMove(int x, int y)
{
if (grid[x, y] == null)
return true;
return false;
}
public bool hasOWon()
{
//check to see if the positions you're about to check actually exist in the grid
if (grid[0, 0] != null && grid[1, 1] != null && grid[2, 2] != null)
{
//check to see if there is a diagonal win for the O player
if (grid[0, 0].player == grid[1, 1].player && grid[0, 0].player == grid[2, 2].player && grid[0, 0].player == 1)
return true;
}
if (grid[0, 2] != null && grid[1, 1] != null && grid[2, 0] != null)
{
//diagonal win
if (grid[0, 2].player == grid[1, 1].player && grid[0, 2].player == grid[2, 0].player && grid[0, 2].player == 1)
return true;
}
//Column Wins
for (int i = 0; i < 3; ++i)
{
if (grid[i, 0] != null && grid[i, 1] != null && grid[i, 2] != null)
{
if (grid[i, 0].player == grid[i, 1].player && grid[i, 0].player == grid[i, 2].player && grid[i, 0].player == 1)
return true;
}
if (grid[0, i] != null && grid[1, i] != null && grid[2, i] != null)
{
if (grid[0, i].player == grid[1, i].player && grid[0, i].player == grid[2, i].player && grid[0, i].player == 1)
return true;
}
}
return false; //there are no winning solutions on the board for O
}
public bool hasXWon()
{
if (grid[0, 0] != null && grid[1, 1] != null && grid[2, 2] != null)
{
if (grid[0, 0].player == grid[1, 1].player && grid[0, 0].player == grid[2, 2].player && grid[0, 0].player == 2)
return true;
}
if (grid[0, 2] != null && grid[1, 1] != null && grid[2, 0] != null)
{
if (grid[0, 2].player == grid[1, 1].player && grid[0, 2].player == grid[2, 0].player && grid[0, 2].player == 2)
return true;
}
for (int i = 0; i < 3; ++i)
{
if (grid[i, 0] != null && grid[i, 1] != null && grid[i, 2] != null)
{
if (grid[i, 0].player == grid[i, 1].player && grid[i, 0].player == grid[i, 2].player && grid[i, 0].player == 2)
return true;
}
if (grid[0, i] != null && grid[1, i] != null && grid[2, i] != null)
{
if (grid[0, i].player == grid[1, i].player && grid[0, i].player == grid[2, i].player && grid[0, i].player == 2)
return true;
}
}
return false; //there are no winning solutions on the board for X
}
//game is over is someone has won, or board is full
public bool isGameOver()
{
Text text = ui.GetComponent<Text>();
if (getMoves().Capacity == 0)
{
//this.transform.Rotate(-90, 0, 0);
//text_j1.SetActive(false);
//text_j2.SetActive(false);
//text_Gagnant.text = "Match nul ! Il n'y a pas de gagnant..";
//Interface_fin_de_partie.SetActive(true);
//return true;
text.text = "c'est un match nul !";
return true;
}
if (hasOWon())
{
//this.transform.Rotate(-90, 0, 0);
//text_j1.SetActive(false);
//text_j2.SetActive(false);
//text_Gagnant.text = "L'IA a gagné.. Prenez votre revanche !";
//Interface_fin_de_partie.SetActive(true);
//return true;
text.text = "Vous avez gagné !";
return true;
}
if (hasXWon())
{
//this.transform.Rotate(-90, 0, 0);
//text_j1.SetActive(false);
//text_j2.SetActive(false);
//text_Gagnant.text = "Bravo vous venez de réaliser l'impossible !";
//Interface_fin_de_partie.SetActive(true);
//return true;
text.text = "Vous avez perdu!";
return true;
}
return false;
}
List<MNode> getMoves()
{
List<MNode> result = new List<MNode>();
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (grid[row, col] == null)
{
MNode newNode = new MNode();
newNode.x = row;
newNode.y = col;
result.Add(newNode); //if the space is empty, add it to the list of results
}
}
}
return result;
}
//returns the minimum element of the list passed to it
public int returnMin(List<int> list)
{
int min = 100000;
int index = -1;
for (int i = 0; i < list.Count; ++i)
{
if (list[i] < min)
{
min = list[i];
index = i;
}
}
return list[index];
}
//returns the maximum element of the list passed to it
public int returnMax(List<int> list)
{
int max = -100000;
int index = -1;
for (int i = 0; i < list.Count; ++i)
{
if (list[i] > max)
{
max = list[i];
index = i;
}
}
return list[index];
}
private void callMinimax(int depth, int turn)
{
rootsChildrenScores = new List<MovesAndScores>();
minimax(depth, turn);
}
public int minimax(int depth, int turn)
{
if (hasXWon()) return +1; //+1 for a player win
if (hasOWon()) return -1; //-1 for a computer win
List<MNode> pointsAvailable = getMoves();
if (pointsAvailable.Capacity == 0) return 0;
List<int> scores = new List<int>();
for (int i = 0; i < pointsAvailable.Count; i++)
{
MNode point = pointsAvailable[i];
//Select the highest from the minimax call on X's turn
if (turn == 1)
{
MNode x = new MNode();
x.x = point.x;
x.y = point.y;
x.player = 2;
grid[point.x, point.y] = x;
int currentScore = minimax(depth + 1, 2);
scores.Add(currentScore);
if (depth == 0)
{
MovesAndScores m = new MovesAndScores(currentScore, point);
m.point = point;
m.score = currentScore;
rootsChildrenScores.Add(m);
}
}
//Select the lowest from the minimax call on O's turn
else if (turn == 2)
{
MNode o = new MNode();
o.x = point.x;
o.y = point.y;
o.player = 1;
grid[point.x, point.y] = o;
int currentScore = minimax(depth + 1, 1);
scores.Add(currentScore);
}
grid[point.x, point.y] = null; //reset the point
}
return turn == 1 ? returnMax(scores) : returnMin(scores);
}
}
Gestion_Click :
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gestion_Click : MonoBehaviour {
public GameObject croix;
public GameObject rond;
static public bool joueur1 = true;
public int etat_joueur = 0; // 0 = case non jouée // 1 = joueur1 // 2 = IA
public Condition_Victoire lien_scripts;
public Gestion_Click[] case_morpion;
public bool IA_enabled = true;
public int maxi = 0;
public bool hasClicked = false;
public bool OnMouseDown()
{
Debug.Log("clic gauche détecté !");
hasClicked = true;
return hasClicked;
// this.GetComponent<BoxCollider>().enabled = false;
//if (joueur1)
//{
// // Instantiate(croix, this.transform.position, Quaternion.identity);
// joueur1 = false;
// etat_joueur = 1;
// lien_scripts.nb_coup++;
// lien_scripts.Gestion_Affichage(etat_joueur);
// lien_scripts.Verif_Victoire();
// }
//else
//{
//// Instantiate(rond, this.transform.position, Quaternion.identity);
// joueur1 = true;
// etat_joueur = 2;
// lien_scripts.nb_coup++;
// lien_scripts.Gestion_Affichage(etat_joueur);
// lien_scripts.Verif_Victoire();
//}
}
internal bool GetMouseButtonDown(int v)
{
if(v == 0)
{
Debug.Log("clic gauche détecté !");
return true;
}
else
{
return false;
}
}
}
Gestion_Partie :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Gestion_Parties : MonoBehaviour {
public void Lancer_Partie_1v1()
{
SceneManager.LoadScene(1);
}
public void Lancer_Partie_1vIA()
{
SceneManager.LoadScene(1);
}
public void Quitter()
{
Application.Quit();
}
public void Menu()
{
SceneManager.LoadScene(0);
}
}
Les balises code SVP
Merci de lire la Netiquette du forum.