Created
June 10, 2015 09:41
-
-
Save vietnt/95e9038b7f37a9729c1e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class UChecker:IDisposable | |
{ | |
public int[,] CardSet; | |
public int[,] PhomMark; | |
private int _countNotPickedCard; | |
private int _countCardNotInPhom; | |
public int CountCardNotInPhom { get { return _countCardNotInPhom;} set{ _countCardNotInPhom = value;}} | |
private int _countEatenCardInHand; | |
public int CountEatenCardInHand { get { return _countEatenCardInHand; } set { _countEatenCardInHand = value; }} | |
private int _countPhom; | |
private bool _foundU; | |
private int[,] _countPhomNgang; | |
private int[,] _countPhomDoc; | |
public List<List<int>> Phoms { get; private set; } | |
public UChecker() | |
{ | |
Phoms = | |
new List<List<int>>(); | |
} | |
private const short CardEaten = 2; | |
private readonly short[][,] _loangDoc = { | |
new short[,] {{0, 1, 2}, {0, 0, 0}}, | |
new short[,] {{0, 1, 3}, {0, 0, 0}}, | |
new short[,] {{0, 2, 3}, {0, 0, 0}}, | |
new short[,] {{0, 1, 2, 3}, {0, 0, 0, 0}} | |
}; | |
public short[][,] LoangDoc | |
{ | |
get { return _loangDoc; } | |
} | |
private readonly short[][,] _loangNgang = | |
{ | |
new short[,] {{0, 0, 0}, {0, 1, 2}}, | |
new short[,] {{0, 0, 0, 0}, {0, 1, 2, 3}}, | |
new short[,] {{0, 0, 0, 0, 0}, {0, 1, 2, 3, 4}} | |
}; | |
public short[][,] LoangNgang | |
{ | |
get { return _loangNgang; } | |
} | |
public bool Check(int[,] cardSet) | |
{ | |
CardSet = cardSet; | |
Init(); | |
InnerCheck(0, 0); | |
return _foundU; | |
} | |
public void Init() | |
{ | |
PhomMark = new int[4, 13]; | |
_countPhomNgang = new int[4, 13]; | |
_countPhomDoc = new int[4, 13]; | |
_countNotPickedCard = 0; | |
_countCardNotInPhom = 0; | |
_countPhom = 0; | |
_countEatenCardInHand = 0; | |
_foundU = false; | |
for (int i = 3; i >= 0; i--) | |
{ | |
for (int j = 12; j >= 0; j--) | |
{ | |
int countNgang = 0; | |
int countDoc = 0; | |
int rightColumn = j + 1; | |
int belowRow = i + 1; | |
if (rightColumn < 13) | |
{ | |
countNgang = _countPhomNgang[i, rightColumn]; | |
} | |
if (belowRow < 4) | |
{ | |
countDoc = _countPhomDoc[belowRow, j]; | |
} | |
if (CardSet[i, j] != 0) | |
{ | |
_countPhomNgang[i, j] = countNgang + 1; | |
_countPhomDoc[i, j] = countDoc + 1; | |
} | |
else | |
{ | |
_countPhomNgang[i, j] = 0; | |
_countPhomDoc[i, j] = countDoc; | |
} | |
_countCardNotInPhom += CardSet[i, j] > 0 ? 1 : 0; | |
_countEatenCardInHand += CardSet[i, j] == CardEaten ? 1 : 0; | |
} | |
} | |
} | |
private void InnerCheck(int row, int column) | |
{ | |
if (_foundU) return; | |
bool foundNextCard = false; | |
while (row < 4) | |
{ | |
while (column < 13 && (CardSet[row, column] == 0 || PhomMark[row, column] != 0)) | |
{ | |
column++; | |
} | |
if (column < 13) | |
{ | |
foundNextCard = true; | |
break; | |
} | |
column = 0; | |
row++; | |
} | |
if (!foundNextCard) return; | |
if (_countPhomDoc[row, column] >= 3) | |
{ | |
for (int i = LoangDoc.Length - 1; i >= 0; i--) | |
{ | |
if (IsValidPhom(row, column, LoangDoc[i])) | |
{ | |
_countPhom++; | |
_countCardNotInPhom -= LoangDoc[i].GetLength(1); | |
MarkPhom(row, column, LoangDoc[i], _countPhom); | |
if (ListPhomUValid()) | |
{ | |
_foundU = true; | |
PrintPhom(); | |
return; | |
} | |
InnerCheck(row, column + 1); | |
if (_foundU) return; | |
UnmarkPhom(row, column, LoangDoc[i]); | |
_countCardNotInPhom += LoangDoc[i].GetLength(1); | |
_countPhom--; | |
} | |
} | |
} | |
if (_countPhomNgang[row, column] >= 3) | |
{ | |
for (int i = LoangNgang.Length - 1; i >= 0; i--) | |
{ | |
bool isValidPhom = IsValidPhom(row, column, LoangNgang[i]); | |
if (isValidPhom) | |
{ | |
_countPhom++; | |
_countCardNotInPhom -= LoangNgang[i].GetLength(1); | |
MarkPhom(row, column, LoangNgang[i], _countPhom); | |
if (ListPhomUValid()) | |
{ | |
_foundU = true; | |
PrintPhom(); | |
return; | |
} | |
InnerCheck(row, column + LoangNgang[i].GetLength(1)); | |
if (_foundU) return; | |
UnmarkPhom(row, column, LoangNgang[i]); | |
_countCardNotInPhom += LoangNgang[i].GetLength(1); | |
_countPhom--; | |
} | |
} | |
} | |
if (_countNotPickedCard == 0) | |
{ | |
_countNotPickedCard++; // skip one card, u 9 cay | |
InnerCheck(row, column + 1); | |
if (_foundU) return; | |
_countNotPickedCard--; | |
} | |
} | |
public bool ListPhomUValid() | |
{ | |
if (_countCardNotInPhom > 1) return false; | |
var countEatenCardInPhom = 0; | |
for (var i = 0; i < 4; i++) | |
{ | |
for (var j = 0; j < 13; j++) | |
{ | |
if (PhomMark[i, j] != 0 && CardSet[i, j] == CardEaten) | |
{ | |
countEatenCardInPhom++; | |
} | |
} | |
} | |
if (countEatenCardInPhom != _countEatenCardInHand) return false; | |
return true; | |
} | |
private void UnmarkPhom(int row, int column, short[,] loang) | |
{ | |
MarkPhom(row, column, loang, 0); | |
} | |
private void MarkPhom(int row, int column, short[,] loang, int phomNumber) | |
{ | |
for (int i = 0; i < loang.GetLength(1); i++) | |
{ | |
int nextRow = row + loang[0, i]; | |
int nextColumn = column + loang[1, i]; | |
PhomMark[nextRow, nextColumn] = phomNumber; | |
} | |
} | |
public bool IsValidPhom(int row, int column, short[,] loang) | |
{ | |
var countEatenCard = 0; | |
for (var i = 0; i < loang.GetLength(1); i++) | |
{ | |
int nextRow = row + loang[0, i]; | |
int nextColumn = column + loang[1, i]; | |
if (nextRow >= 4 || nextColumn >= 13) return false; | |
if (CardSet[nextRow, nextColumn] == 0 || PhomMark[nextRow, nextColumn] != 0) | |
{ | |
return false; | |
} | |
if (CardSet[nextRow, nextColumn] == CardEaten) | |
{ | |
countEatenCard++; | |
} | |
} | |
if (countEatenCard > 1) | |
{ | |
return false; // 1 phỏm không thể có 2 cây ăn | |
} | |
return true; | |
} | |
public static bool CheckUKhan(int[,] cardSet) | |
{ | |
for (var i = 0; i < 13; i++) | |
{ | |
var count = cardSet[0, i] + cardSet[1, i] + cardSet[2, i] + cardSet[3, i]; | |
if (count >= 2) | |
{ | |
// found ca. ngang | |
return false; | |
} | |
} | |
for (var i = 0; i < 4; i++) | |
{ | |
var j = 0; | |
while (j < 12) | |
{ | |
if (cardSet[i, j] == 1) | |
{ | |
if (cardSet[i, j + 1] == 1) | |
{ | |
// found ca. do.c kieu 5 tep, 6 tep | |
return false; | |
} | |
if (j < 11 && cardSet[i, j + 2] == 1) | |
{ | |
// found ca. do.c kieu 5 tep, 7 tep | |
return false; | |
} | |
} | |
j++; | |
} | |
} | |
return true; | |
} | |
public static bool CheckUKhan(IList<int> cards) | |
{ | |
var cardSet = new int[4, 13]; | |
for (var i = 0; i < 4; i++) | |
{ | |
for (var j = 0; j < 13; j++) | |
{ | |
cardSet[i, j] = 0; | |
} | |
} | |
for (var i = 0; i < cards.Count; i++) | |
{ | |
var card = new Card(cards[i]); | |
cardSet[(int)card.Class, card.Value] = 1; | |
} | |
return CheckUKhan(cardSet); | |
} | |
public bool Check(IList<int> cards, IList<int> eatenCards) | |
{ | |
var cardSet = new int[4, 13]; | |
for (var i = 0; i < 4; i++) | |
{ | |
for (var j = 0; j < 13; j++) | |
{ | |
cardSet[i, j] = 0; | |
} | |
} | |
for (var i = 0; i < cards.Count; i++) | |
{ | |
var card = new Card(cards[i]); | |
if (eatenCards.Contains(cards[i])) | |
{ | |
cardSet[(int)card.Class, card.Value] = CardEaten; | |
} | |
else | |
{ | |
cardSet[(int)card.Class, card.Value] = 1; | |
} | |
} | |
return Check(cardSet); | |
} | |
[Obsolete("Now to check U, must pass in eaten card list. Call Check(IList<int>, IList<int>) instead.")] | |
public bool Check(IList<int> cards) | |
{ | |
return Check(cards, new List<int>()); | |
} | |
private void ClearPhomMarks() | |
{ | |
for (var i = 0; i < 4; i++) | |
{ | |
for (var j = 0; j < 13; j++) | |
{ | |
PhomMark[i, j] = 0; | |
} | |
} | |
} | |
private void PrintPhom() | |
{ | |
var phomA = new List<int>(); | |
var phomB = new List<int>(); | |
var phomC = new List<int>(); | |
for (var i = 0; i < 4; i++) | |
{ | |
for (var j = 0; j < 13; j++) | |
{ | |
var rawCard = i * 13 + j; | |
switch (PhomMark[i, j]) | |
{ | |
case 1: | |
phomA.Add(rawCard); | |
break; | |
case 2: | |
phomB.Add(rawCard); | |
break; | |
case 3: | |
phomC.Add(rawCard); | |
break; | |
} | |
} | |
} | |
if (phomA.Count > 0) | |
{ | |
Phoms.Add(phomA); | |
} | |
if (phomB.Count > 0) | |
{ | |
Phoms.Add(phomB); | |
} | |
if (phomC.Count > 0) | |
{ | |
Phoms.Add(phomC); | |
} | |
ClearPhomMarks(); | |
} | |
public void Dispose() | |
{ | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment