Skip to content

Instantly share code, notes, and snippets.

@vietnt
Created June 10, 2015 09:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vietnt/95e9038b7f37a9729c1e to your computer and use it in GitHub Desktop.
Save vietnt/95e9038b7f37a9729c1e to your computer and use it in GitHub Desktop.
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