Commit 88dfd8af authored by William Babonnaud's avatar William Babonnaud

Corrections solveur unruly + ajout difficulte

parent a9bab7d1
......@@ -15,15 +15,22 @@ abstract class JeuCouleur extends Jeu[MonBouton] {
// Sauvegarde nécessaire pour le redémarrage
protected var sauvegardeMat = ofDim[Color](tailleX,tailleY)
// Difficulte
// 0 : Facile
// 1 : Moyen
// 2 : Difficile
protected var difficulte = 0
// Pour reparamétrer la configuration du terrain
def reparametrage(x: Int, y: Int) = {
def reparametrage(x: Int, y: Int, d: Int) = {
tailleX = x
tailleY = y
difficulte = d
boutons = ofDim[MonBouton](tailleX,tailleY)
sauvegardeMat = ofDim[Color](tailleX,tailleY)
}
def reparametrage(x: Int, y: Int, n: Int) = reparametrage(x,y)
def reparametrage(x: Int, y: Int, d: Int, n: Int) = reparametrage(x,y,d)
def redemarre() = {
for(i <- 0 to (tailleX-1)) {
......
......@@ -29,7 +29,7 @@ class Demineur extends Jeu[MonBouton] {
// 0 : Super Noob
// 1 : Moyem Noob
// 2 : Noob
protected var noobitube = 0
protected var noobitude = 0
// Matrice représentant le champ de mines. Ses valeurs sont comprises entre 0 et 9.
// 0-8 : Nombre de mines autour de la case vide.
......@@ -41,17 +41,17 @@ class Demineur extends Jeu[MonBouton] {
override protected var boutons = ofDim[MonBouton](tailleX,tailleY)
// Réinitialise les paramètres ci-dessus en cas de changement de difficulté.
def reparametrage (x: Int, y: Int,dif : Int, n: Int) = {
def reparametrage (x: Int, y: Int, d: Int, n: Int) = {
tailleX = x
tailleY = y
nb_mines = n
noobitude = diff
noobitude = d
c_restantes = tailleX*tailleY - nb_mines
boutons = ofDim[MonBouton](tailleX, tailleY)
}
// On n'aura normalement pas à utiliser cette fonction, mais elle doit exister
def reparametrage(x: Int, y: Int) = reparametrage(x,y,10)
def reparametrage(x: Int, y: Int, d: Int) = reparametrage(x,y,d,10)
// Focntion de redémarrage
def redemarre() = {
......
......@@ -61,8 +61,8 @@ abstract class Jeu[T<:Button] {
def victoire() : Boolean
def initialise() : Unit
def initialise(n: Int) : Unit
def reparametrage(x: Int, y: Int) : Unit
def reparametrage(x: Int, y: Int, n: Int) : Unit
def reparametrage(x: Int, y: Int, d: Int) : Unit
def reparametrage(x: Int, y: Int, d: Int, n: Int) : Unit
def redemarre() : Unit
def clique_action_droit(x: Int, y: Int) : Boolean
def clique_action_gauche(x: Int, y: Int) : Boolean
......
......@@ -51,27 +51,33 @@ object CercleInvocation extends SimpleSwingApplication {
case 4 => jeu = new Flood
}
group.selected.get match {
case `but_fac` =>
case `but_fac` =>
choix_de_jeu match {
case 1 => jeu.reparametrage(9,9,0,10)
case 2 => jeu.reparametrage(5,5,0)
case 3 => jeu.reparametrage(8,8,0)
case 4 => jeu.reparametrage(8,10,0)
}
case `but_moy` =>
choix_de_jeu match {
case 1 => jeu.reparametrage(16,16,40)
case 2 => jeu.reparametrage(7,7)
case 3 => jeu.reparametrage(10,10)
case 4 => jeu.reparametrage(10,10)
case 1 => jeu.reparametrage(16,16,1,40)
case 2 => jeu.reparametrage(7,7,1)
case 3 => jeu.reparametrage(10,10,1)
case 4 => jeu.reparametrage(10,10,1)
}
case `but_dur` =>
choix_de_jeu match {
case 1 => jeu.reparametrage(16,16,99)
case 2 => jeu.reparametrage(9,9)
case 3 => jeu.reparametrage(14,14)
case 4 => jeu.reparametrage(14,14)
case 1 => jeu.reparametrage(16,16,2,99)
case 2 => jeu.reparametrage(9,9,2)
case 3 => jeu.reparametrage(14,14,2)
case 4 => jeu.reparametrage(14,14,2)
}
case `but_per` =>
choix_de_jeu match {
case 1 => jeu.reparametrage(diff_fr.li,diff_fr.co,diff_fr.aut)
case 2 => jeu.reparametrage(diff_fr.li,diff_fr.co)
case 3 => jeu.reparametrage(2*(diff_fr.li/2),2*(diff_fr.co/2))
case 4 => jeu.reparametrage(2*(diff_fr.li/2),2*(diff_fr.co/2))
case 1 => jeu.reparametrage(diff_fr.li,diff_fr.co,1,diff_fr.aut)
case 2 => jeu.reparametrage(diff_fr.li,diff_fr.co,1)
case 3 => jeu.reparametrage(2*(diff_fr.li/2),2*(diff_fr.co/2),1)
case 4 => jeu.reparametrage(2*(diff_fr.li/2),2*(diff_fr.co/2),1)
}
}
}
......@@ -165,10 +171,10 @@ object CercleInvocation extends SimpleSwingApplication {
if (string_to_int(text_autre.text) > 0) { aut = string_to_int(text_autre.text) } else { aut = cela.jeu.getValeurDefaut(2) }
}
cela.choix_de_jeu match {
case 1 => cela.jeu = new Demineur ; cela.jeu.reparametrage(li,co,aut)
case 2 => cela.jeu = new Flip ; cela.jeu.reparametrage(li,co)
case 3 => cela.jeu = new Unruly ; cela.jeu.reparametrage(2*(li/2),2*(co/2))
case 4 => cela.jeu = new Flood ; cela.jeu.reparametrage(2*(li/2),2*(co/2))
case 1 => cela.jeu = new Demineur ; cela.jeu.reparametrage(li,co,1,aut)
case 2 => cela.jeu = new Flip ; cela.jeu.reparametrage(li,co,1)
case 3 => cela.jeu = new Unruly ; cela.jeu.reparametrage(2*(li/2),2*(co/2),1)
case 4 => cela.jeu = new Flood ; cela.jeu.reparametrage(2*(li/2),2*(co/2),1)
}
cela.jeu.initialise
cela.contents = genContents
......
......@@ -2,28 +2,36 @@ import scala.util.Random
import Array._
import java.awt.Color
import javax.swing.ImageIcon
import scala.util.control.Breaks._
class Unruly extends Jeu[MonBouton] {
valeur_defaut = Array(6,6)
valeur_defaut = Array(8,8)
// Cotés du terrain
tailleX = valeur_defaut(0)
tailleY = valeur_defaut(1)
private var nb_non_occupes = tailleX*tailleY
// Difficulte
// 0 : Facile
// 1 : Moyen
// 2 : Difficile
private var difficulte = 0
// Matrice des boutons.
override var boutons = ofDim[MonBouton](tailleX,tailleY)
// Pour reparamétrer la configuration du terrain
def reparametrage(x: Int, y: Int) = {
def reparametrage(x: Int, y: Int, d: Int) = {
tailleX = x
tailleY = y
tailleY = y
difficulte = 0
boutons = ofDim[MonBouton](tailleX,tailleY)
nb_non_occupes = tailleX*tailleY
}
def reparametrage(x: Int, y: Int, n: Int) = reparametrage(x: Int, y: Int)
def reparametrage(x: Int, y: Int, d: Int, n: Int) = reparametrage(x,y,d)
def redemarre() = {
for (i <- 0 to (tailleX-1)) {
......@@ -77,48 +85,51 @@ class Unruly extends Jeu[MonBouton] {
res
}
// Admissibilité d'une position et une couleur donnée
def compatible(x: Int, y: Int, c: Color) = {
(!trois(x,y,c)) && (nombre_aligne(x,true,c) < tailleY/2) && (nombre_aligne(y,false,c) < tailleX/2)
}
// Génération d'une grille aléatoire
def initialise = {
/* !!! */ for (i <- 0 to (tailleX-1)) {
def initialise : Unit = {
for (i <- 0 to (tailleX-1)) {
for (j <- 0 to (tailleY-1)) {
boutons(i)(j) = new MonBouton(i,j)
boutons(i)(j).desactive_couleur
}
}
var borne = (tailleX*tailleY)/4
var borne = (tailleX*tailleY)/3
var x = Random.nextInt(tailleX)
var y = Random.nextInt(tailleY)
var k = Random.nextBoolean
var im = new ImageIcon
var cl = Color.white
var fini = false
while (!fini) {
for (i <- 0 to borne) {
k = Random.nextBoolean
if (k) {
im = new ImageIcon(getClass.getResource("blanc_inchangeable.png"))
cl = Color.white
}
else {
im = new ImageIcon(getClass.getResource("noir_inchangeable.png"))
cl = Color.black
}
while (boutons(x)(y).estColore || trois(x,y,cl)) {
x = Random.nextInt(tailleX)
y = Random.nextInt(tailleY)
}
boutons(x)(y).setColoration(true)
boutons(x)(y).setCouleur(cl)
boutons(x)(y).chgIconEtEnable(im, false)
nb_non_occupes = nb_non_occupes-1
for (i <- 0 to borne) {
k = Random.nextBoolean
if (k) {
im = new ImageIcon(getClass.getResource("blanc_inchangeable.png"))
cl = Color.white
}
else {
im = new ImageIcon(getClass.getResource("noir_inchangeable.png"))
cl = Color.black
}
fini = solveur(x,y,cl)
}
while (boutons(x)(y).estColore || trois(x,y,cl)) {
x = Random.nextInt(tailleX)
y = Random.nextInt(tailleY)
}
boutons(x)(y).setColoration(true)
boutons(x)(y).setCouleur(cl)
boutons(x)(y).chgIconEtEnable(im, false)
nb_non_occupes = nb_non_occupes-1
}
println("Après construction : "+nb_non_occupes)
if (!solveur()) { redemarre(); initialise } else { nettoyage() }
}
// Génératioàn aléatoire avec graine
def initialise(n: Int) = {
/* !!! */ for (i <- 0 to (tailleX-1)) {
def initialise(n: Int) : Unit = {
for (i <- 0 to (tailleX-1)) {
for (j <- 0 to (tailleY-1)) {
boutons(i)(j) = new MonBouton(i,j)
boutons(i)(j).desactive_couleur
......@@ -149,6 +160,7 @@ class Unruly extends Jeu[MonBouton] {
boutons(x)(y).chgIconEtEnable(im, false)
nb_non_occupes = nb_non_occupes-1
}
if (!solveur()) { redemarre(); initialise(n+1) } else { nettoyage() }
}
// Test de victoire
......@@ -162,7 +174,7 @@ class Unruly extends Jeu[MonBouton] {
boutons(i)(j).desactive_couleur()
nb_non_occupes += 1
} else {
if (!trois(i,j,c) && nombre_aligne(i,true,c)<(tailleY/2) && nombre_aligne(j,false,c)<(tailleX/2)) {
if (compatible(i,j,c)) {
boutons(i)(j).setCouleur(c)
boutons(i)(j).active_couleur()
nb_non_occupes -= 1
......@@ -182,181 +194,130 @@ class Unruly extends Jeu[MonBouton] {
victoire()
}
// Renvoie blanc si on donne noir, et réciproquement
def non_couleur(c: Color) = {
if (c == Color.black) { Color.white } else { Color.black }
}
// Solveur_trivial, détermine les cases dont les règles imposent la couleur.
def sol_trivial(x: Int, y: Int) : Boolean = {
def sol_trivial(x: Int, y: Int) = {
var result = false
var probleme = false
if(trois(x,y,Color.black)){
result = true; boutons(x)(y).setCouleur(Color.white); boutons(x)(y).active_couleur()}
if(compatible(x,y,Color.white)) { result = true; boutons(x)(y).setCouleur(Color.white); boutons(x)(y).active_couleur() }
else { probleme = true }}
if(!result && trois(x,y,Color.white)){
result = true; boutons(x)(y).setCouleur(Color.black); boutons(x)(y).active_couleur()}
if(!result && nombre_aligne(x,true,Color.black)=(tailleY/2)){
result = true; boutons(x)(y).setCouleur(Color.white); boutons(x)(y).active_couleur()}
if(!result && nombre_aligne(x,true,Color.white)=(tailleY/2)){
result = true; boutons(x)(y).setCouleur(Color.black); boutons(x)(y).active_couleur()}
if(!result && nombre_aligne(y,false,Color.black)=(tailleX/2)){
result = true; boutons(x)(y).setCouleur(Color.white); boutons(x)(y).active_couleur()}
if(!result && nombre_aligne(y,false,Color.white)=(tailleX/2)){
result = true; boutons(x)(y).setCouleur(Color.black); boutons(x)(y).active_couleur()}
result
if(compatible(x,y,Color.black)) { result = true; boutons(x)(y).setCouleur(Color.black); boutons(x)(y).active_couleur() }
else { probleme = true }}
if(!result && nombre_aligne(x,true,Color.black)==(tailleY/2)){
if(compatible(x,y,Color.white)) { result = true; boutons(x)(y).setCouleur(Color.white); boutons(x)(y).active_couleur() }
else { probleme = true }}
if(!result && nombre_aligne(x,true,Color.white)==(tailleY/2)){
if(compatible(x,y,Color.black)) { result = true; boutons(x)(y).setCouleur(Color.black); boutons(x)(y).active_couleur() }
else { probleme = true }}
if(!result && nombre_aligne(y,false,Color.black)==(tailleX/2)){
if(compatible(x,y,Color.white)) { result = true; boutons(x)(y).setCouleur(Color.white); boutons(x)(y).active_couleur() }
else { probleme = true }}
if(!result && nombre_aligne(y,false,Color.white)==(tailleX/2)){
if(compatible(x,y,Color.black)) { result = true; boutons(x)(y).setCouleur(Color.black); boutons(x)(y).active_couleur() }
else { probleme = true }}
if (result) {nb_non_occupes -= 1}
(result,probleme)
}
// Vérifie les conditions trivialles après modif.
def checkmodif(x: Int, y: Int) = {
for(i <- 0 to tailleX - 1 ){
if(!boutons(i)(y).estColore){if(sol_trivial(i,y)){checkmodif(i,y)}}
def checkmodif(x: Int, y: Int) : Boolean = {
var pb = false
var i = 0
var j = 0
while(i < tailleX && !pb) {
if(!boutons(i)(y).estColore){
var t = sol_trivial(i,y)
pb = t._2
if(t._1 && !t._2){ checkmodif(i,y) }
}
i = i+1
}
for(j <- 0 to tailleY - 1 ){
if(!boutons(x)(j).estColore){if(sol_trivial(x,j)){checkmodif(x,j)}}
while(j < tailleY && !pb) {
if(!boutons(x)(j).estColore){
var t = sol_trivial(x,j)
pb = t._2
if(t._1 && !t._2){ checkmodif(x,j) }
}
j = j+1
}
pb
}
// Solveur, détermine si une instance donnée admet une solution.
def solveur() = {
def solveur() : Boolean = {
for(i <- 0 to tailleX - 1){
for(j <- 0 to tailleY - 1){
if(sol_trivial(x,y)){checkmodif(x,y)}}}
if(!boutons(i)(j).estColore) {
var t = sol_trivial(i,j)
if (t._2) { println("Zbraa !"); return false }
if (t._1) { if (checkmodif(i,j)) { println("Zbrout !"); return false } }
}
}}
if (victoire()) { return true }
var limite = 0
difficulte match {
case 0 => limite = 4
case 1 => limite = (tailleX*tailleY)/3
case 2 => limite = (tailleX*tailleY)/2
}
if (nb_non_occupes > limite) { println("pas assez : interruption"); false }
else {
var (m,n) = choix()
brutal_solve(m,n)
}
}
// Solveur, détermine si une instance donnée admet une solution.
def solveur(x: Int, y: Int, c: Color) : Boolean = {
boutons(x)(y).setColoration(true)
boutons(x)(y).setCouleur(c)
nb_non_occupes -= 1
println("On compte : " + nb_non_occupes)
var result = false
if (trois(x,y,c)|| nombre_aligne(x,true,c) > (tailleY/2) ||
nombre_aligne(y,false,c) > (tailleX/2)) {
// Toujours revenir à l'état initial en sortie !
nb_non_occupes += 1
boutons(x)(y).setCouleur(Color.gray)
boutons(x)(y).setColoration(false)
false
} else if (victoire()) {
// Toujours revenir à l'état initial en sortie !
nb_non_occupes += 1
boutons(x)(y).setCouleur(Color.gray)
boutons(x)(y).setColoration(false)
true
} else {
var i = 0
var j = 0
var solveur_lance = false
var res = false
while (i < tailleX && !solveur_lance) {
// Il suffit de lancer un seul solveur : s'il échoue, on aura une impossibilité
// immédiate puisque l'on ne teste ici que des cas où les règles imposent une
// unique possibilité.
if (boutons(i)(j).estColore) {
var col = boutons(i)(j).getCouleur
// Cas de deux cases contiguës horizontales.
if (boutons(i)(j+1).estColore(col)) {
if (j>0 && !boutons(i)(j-1).estColore) { // On essaie à gauche.
res = solveur(i,j-1,non_couleur(col))
solveur_lance = true
} else if (j+1<tailleY-1 && !boutons(i)(j+2).estColore) { // On essaie à droite.
res = solveur(i,j+2,non_couleur(col))
solveur_lance = true
}
}
// Cas de deux cases contiguës verticales.
if (!solveur_lance && i < tailleX-1 && boutons(i+1)(j).estColore(col)) {
if (i>0 && !boutons(i-1)(j).estColore) { // On essaie en haut.
res = solveur(i-1,j,non_couleur(col))
solveur_lance = true
} else if (i+1<tailleX-1 && !boutons(i+2)(j).estColore) { // On essaie en bas.
res = solveur(i+2,j,non_couleur(col))
solveur_lance = true
}
}
// Cas de deux cases séparées d'une autre horizontalement.
if (!solveur_lance && j+1 < tailleY-1 && boutons(i)(j+2).estColore(col)) {
if (!boutons(i)(j+1).estColore) { // On teste la case au milieu.
res = solveur(i,j+1,non_couleur(col))
solveur_lance = true
}
}
// Cas de deux cases séparées d'une autre verticalment.
if (!solveur_lance && i+1 < tailleX-1 && boutons(i+2)(j).estColore(col)) {
if (!boutons(i+1)(j).estColore) { // On teste la case au milieu.
res = solveur(i+1,j,non_couleur(col))
solveur_lance = true
}
}
// Incrémentation : parcours des lignes une par une en testant toutes les colonnes.
}
if (j == tailleY-2) { j = 0 ; i = i+1 } else { j = j+1 }
// Choisit les coordonnées d'une case non colorée (on s'assurera qu'il en existe une)
def choix() = {
if (victoire()) { println("Absurde") }
var i = 0
var j = 0
var trouve = false
while (!trouve && i < tailleX) {
if (!boutons(i)(j).estColore) { trouve = true }
else {
if (j == tailleY-1) { j = 0 ; i = i+1 } else { j = j+1 }
}
if (res) { // Si un solveur lancé a renvoyé vrai, on s'arrête : le jeu est résoluble.
result = true
} else if (solveur_lance && !res) { // Si un solveur lancé a renvoyé faux, le jeu n'est pas résoluble.
result = false
} else if (!solveur_lance && !res) { // Sinon on regarde le nombre de couleur par ligne et colonne.
i = 0
j = 0
var nb = 0
solveur_lance = false
while (i < tailleX && !res) {
//if (!boutons(i)(j).estColore) {
// res = solveur(i,j,Color.black) // On essaie en noir.
// if (!res) { res = solveur(i,j,Color.white) } // Si ça n'a pas marché, en blanc.
//}
//if (!res) { // Si ça n'a toujours pas marché ou si la case était colorée, incrémentation.
// if (j == tailleY-1) { j = 0 ; i = i+1 } else { j = j+1 }
//}
nb = nombre_aligne(i,true,Color.black)
if (nb == tailleX/2) {
j = 0
while (boutons(i)(j).estColore && j < tailleY) { j = j+1 }
res = solveur(i,j,Color.white)
solveur_lance = true
} else {
nb = nombre_aligne(i,true,Color.white)
if (nb == tailleX/2) {
j = 0
while(boutons(i)(j).estColore && j < tailleY) { j = j+1 }
res = solveur(i,j,Color.black)
solveur_lance = true
}
}
i = i+1
}
i = 0
j = 0
if (!solveur_lance) {
while (j < tailleY && !res) {
nb = nombre_aligne(i,true,Color.black)
if (nb == tailleY/2) {
i = 0
while (boutons(i)(j).estColore && i < tailleX) { i = i+1 }
res = solveur(i,j,Color.white)
solveur_lance = true
} else {
nb = nombre_aligne(i,true,Color.white)
if (nb == tailleY/2) {
i = 0
while(boutons(i)(j).estColore && i < tailleX) { i = i+1 }
res = solveur(i,j,Color.black)
solveur_lance = true
}
}
i = i+1
}
}
result = res
}
(i,j)
}
// Fonction pour résoudre de façon brute la grille
def brutal_solve(x: Int, y: Int) : Boolean = {
var res = false
if (compatible(x,y,Color.black)) {
boutons(x)(y).setCouleur(Color.black)
boutons(x)(y).active_couleur()
nb_non_occupes -= 1
checkmodif(x,y)
if (!victoire()) {
var (m,n) = choix()
res = brutal_solve(m,n)
} else { res = true }
}
if (!res && compatible(x,y,Color.white)) {
boutons(x)(y).setCouleur(Color.white)
boutons(x)(y).active_couleur()
nb_non_occupes -= 1
checkmodif(x,y)
if (!victoire()) {
var (m,n) = choix()
res = brutal_solve(m,n)
} else { res = true }
}
res
}
// Rétablit la grille initialement traitée par le solveur
def nettoyage() = {
println("Début nettoyage : "+nb_non_occupes)
for (i <- 0 to tailleX-1) {
for (j <- 0 to tailleY-1) {
if (boutons(i)(j).enabled) { boutons(i)(j).desactive_couleur(); nb_non_occupes += 1 }
}
// Toujours revenir à l'état initial en sortie !
nb_non_occupes += 1
boutons(x)(y).setCouleur(Color.gray)
boutons(x)(y).setColoration(false)
result
}
println("Fin nettoyage : "+nb_non_occupes)
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment