这里展示了一个有AI的重力四子棋的C#程序。 AI采用alpha beta剪枝的方法。
界面代码MainWindow.xaml:
/*
* This program is a gravity connect four game. AI uses the alpha beta pruning search.
* */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Forms;
namespace ConnectFour
{
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
private const int column = 4; // The column of chess board
private const int row = 5; // The row of chess board
private const bool HUMAN = true; // Human turn
private const bool PROGRAM = false; // Program turn
private bool player = HUMAN;
private double width;
private double height;
private double gridWidth;
private double gridHeight;
private int maxDepth = 10;
private bool canClick = true;
private Position board = new Position();
private int nodeNumber = 0;
private int maxCut = 0;
private int minCut = 0;
public MainWindow()
{
InitializeComponent();
AddHandler(FrameworkElement.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(ChessBorad_MouseLeftButtonDown), true);
AddHandler(FrameworkElement.PreviewMouseRightButtonDownEvent, new MouseButtonEventHandler(ChessBorad_MouseRightButtonDown), true);
}
private void DrawChessBoard()
{
chessBoard.Children.Clear();
width = chessBoard.ActualWidth;
height = chessBoard.ActualHeight;
gridWidth = width * 0.9 / column;
gridHeight = height * 0.9 / row;
for (int i = 0; i <= row; i++)
{
DrawingLine(width * 0.05, height * 0.05 + i * gridHeight, width * 0.95, height * 0.05 + i * gridHeight);
}
for (int i = 0; i <= column; i++)
{
DrawingLine(width * 0.05 + i * gridWidth, height * 0.05, width * 0.05 + i * gridWidth, height * 0.95);
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
if (board.chess[i, j] == Position.HUMAN_CHESS)
DrawingEllipse(gridWidth * 0.9, gridHeight * 0.9, width * 0.05 + j * gridWidth + 0.5 * gridWidth, height * 0.05 + i * gridHeight + 0.5 * gridHeight, HUMAN);
else if (board.chess[i, j] == Position.PROGRAM_CHESS)
DrawingEllipse(gridWidth * 0.9, gridHeight * 0.9, width * 0.05 + j * gridWidth + 0.5 * gridWidth, height * 0.05 + i * gridHeight + 0.5 * gridHeight, PROGRAM);
}
}
}
protected void DrawingLine(double x1, double y1, double x2, double y2)
{
Line myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.Black;
myLine.X1 = x1;
myLine.Y1 = y1;
myLine.X2 = x2;
myLine.Y2 = y2;
myLine.StrokeThickness = 1;
chessBoard.Children.Add(myLine);
}
protected void DrawingEllipse(double widthEllipse, double heightEllipse, double centerX, double centerY, bool currentPlayer)
{
Ellipse myEllipse = new Ellipse();
if (currentPlayer) myEllipse.Stroke = System.Windows.Media.Brushes.DarkBlue;
else myEllipse.Stroke = System.Windows.Media.Brushes.Red;
myEllipse.Width = widthEllipse;
myEllipse.Height = heightEllipse;
myEllipse.StrokeThickness = 2;
myEllipse.Fill = myEllipse.Stroke;
myEllipse.Margin = new Thickness(centerX - widthEllipse / 2, centerY - heightEllipse / 2, 0, 0);
chessBoard.Children.Add(myEllipse);
}
private bool isInChessBoundary(double x, double y)
{
return x >= chessBoard.ActualWidth * 0.05 && x <= chessBoard.ActualWidth * 0.95 && y >= chessBoard.ActualHeight * 0.05 && y <= chessBoard.ActualHeight * 0.95;
}
private void ConnectFourForm_SizeChanged(object sender, SizeChangedEventArgs e)
{
DrawChessBoard();
}
private void ChessBorad_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (!canClick) return;
Point mousePosition = e.GetPosition(chessBoard);
double x = mousePosition.X;
double y = mousePosition.Y;
if (!isInChessBoundary(x, y)) return;
int columnIndex = (int)((x - width * 0.05) / gridWidth);
bool canNext = mouseLeftClickedInColumn(columnIndex);
DrawChessBoard();
testEndOfGame();
if (canNext)
{
player = PROGRAM;
programTurn();
testEndOfGame();
}
e.Handled = true;
}
private void ChessBorad_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
if (!canClick) return;
Point mousePosition = e.GetPosition(chessBoard);
double x = mousePosition.X;
double y = mousePosition.Y;
if (!isInChessBoundary(x, y)) return;
int columnIndex = (int)((x - width * 0.05) / gridWidth);
bool canNext = mouseRightClickedInColumn(columnIndex);
DrawChessBoard();
testEndOfGame();
if (canNext)
{
player = PROGRAM;
programTurn();
testEndOfGame();
}
e.Handled = true;
}
private void testEndOfGame()
{
if(wonPosition(board, HUMAN)) {
canClick = false;
System.Windows.MessageBox.Show("Human won!");
return;
}
else if(wonPosition(board, PROGRAM)) {
canClick = false;
System.Windows.MessageBox.Show("Program won!");
return;
}
else if (drawnPosition(board))
{
canClick = false;
System.Windows.MessageBox.Show("Draw game!");
return;
}
}
private void programTurn()
{
ArrayList v = alphaBeta(0, board, PROGRAM);
board = (Position)v[1];
DrawChessBoard();
player = HUMAN;
txbMessage.Text = "Node Number: " + nodeNumber + ", Max Cut Number: " + maxCut + ", Min Cut Number: " + minCut;
}
private bool mouseLeftClickedInColumn(int columnIndex)
{
int rowIndex = 0;
if (isFullColumn(board.chess, columnIndex)) return false;
if (isEmptyColumn(board.chess, columnIndex)) rowIndex = row - 1;
else
{
for (int i = 0; i < row; i++)
{
if (board.chess[i, columnIndex] != Position.EMPTY)
{
rowIndex = i - 1;
break;
}
}
}
if (player == HUMAN) board.chess[rowIndex, columnIndex] = Position.HUMAN_CHESS;
else board.chess[rowIndex, columnIndex] = Position.PROGRAM_CHESS;
return true;
}
private bool mouseRightClickedInColumn(int columnIndex)
{
if (board.chess[row - 1, columnIndex] != Position.EMPTY)
{
if (player)
{
if (board.chess[row - 1, columnIndex] != Position.HUMAN_CHESS) return false;
}
else
{
if (board.chess[row - 1, columnIndex] != Position.PROGRAM_CHESS) return false;
}
for (int i = row - 1; i > 0; i--)
board.chess[i, columnIndex] = board.chess[i - 1, columnIndex];
board.chess[0, columnIndex] = 0;
return true;
}
return false;
}
//judge whether the column ie empty
private static bool isEmptyColumn(short[,] aChess, int columnIndex)
{
for (int i = 0; i < aChess.GetLength(0); i++)
{
if (aChess[i, columnIndex] != Position.EMPTY) return false;
}
return true;
}
//judge whether the column is full
private static bool isFullColumn(short[,] aChess, int columnIndex)
{
for (int i = 0; i < aChess.GetLength(0); i++)
{
if (aChess[i, columnIndex] == Position.EMPTY) return false;
}
return true;
}
// alpha beta pruning search
private ArrayList alphaBeta(int depth, Position p, bool currentPlayer)
{
nodeNumber = 0;
minCut = 0;
maxCut = 0;
ArrayList v = alphaBetaHelper(depth, p, currentPlayer, float.PositiveInfinity, float.NegativeInfinity);
return v;
}
// The recursive method of alpha beta pruning search
private ArrayList alphaBetaHelper(int depth, Position p, bool currentPlayer, float alpha, float beta)
{
nodeNumber++;
if (reachedMaxDepth(p, depth))
{
ArrayList v = new ArrayList(2);
float value = positionEvaluation(p, currentPlayer);
v.Add(value);
v.Add(null);
return v;
}
ArrayList best = new ArrayList();
Position[] moves = possibleMoves(p, currentPlayer);
for (int i = 0; i < moves.GetLength(0); i++)
{
ArrayList v2 = alphaBetaHelper(depth + 1, moves[i], !currentPlayer, -beta, -alpha);
float value = -(float)v2[0];
if (value > beta)
{
beta = value;
best = new ArrayList();
best.Add(moves[i]);
IEnumerator enum2 = v2.GetEnumerator();
enum2.MoveNext(); // skip previous value
while (enum2.MoveNext())
{
Object o = enum2.Current;
if (o != null) best.Add(o);
}
}
/**
* Use the alpha-beta cutoff test to abort search if we
* found a move that proves that the previous move in the
* move chain was dubious
*/
if (beta >= alpha)
{
if (currentPlayer == player)
maxCut++;
else
minCut++;
break;
}
}
ArrayList v3 = new ArrayList();
v3.Add(beta);
IEnumerator enum3 = best.GetEnumerator();
while (enum3.MoveNext())
{
v3.Add(enum3.Current);
}
return v3;
}
private bool drawnPosition(Position p)
{
Position position = p;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
if (position.chess[i, j] == Position.EMPTY)
return false;
}
}
return true;
}
private Position[] possibleMoves(Position pos, bool player)
{
int count = 0;
for (int j = 0; j < column; j++)
{
if (!isFullColumn(pos.chess, j)) count++;
}
for (int j = 0; j < column; j++)
{
if (!isEmptyColumn(pos.chess, j))
{
int indexRow = row - 1;
if (pos.chess[indexRow, j] == Position.HUMAN_CHESS && player == HUMAN) count++;
if (pos.chess[indexRow, j] == Position.PROGRAM_CHESS && player == PROGRAM) count++;
}
}
Position[] ret = new Position[count];
count = 0;
for (int j = 0; j < column; j++)
{
if (!isFullColumn(pos.chess, j))
{
Position pos2 = new Position();
pos2.chess = getNewArray(pos.chess);
int indexRow = 0;
if (isEmptyColumn(pos.chess, j)) indexRow = row - 1;
else
{
for (int i = 0; i < row; i++)
{
if (pos.chess[i, j] != Position.EMPTY)
{
indexRow = i;
break;
}
}
indexRow--;
}
if (player) pos2.chess[indexRow, j] = Position.HUMAN_CHESS;
else pos2.chess[indexRow, j] = Position.PROGRAM_CHESS;
ret[count++] = pos2;
}
}
for (int j = 0; j < column; j++)
{
if (!isEmptyColumn(pos.chess, j))
{
int row = pos.chess.GetLength(0) - 1;
if ((pos.chess[row, j] == Position.HUMAN_CHESS && player == HUMAN) || (pos.chess[row, j] == Position.PROGRAM_CHESS && player == PROGRAM))
{
Position pos2 = new Position();
pos2.chess = getNewArray(pos.chess);
for (int i = pos2.chess.GetLength(0) - 1; i > 0; i--)
{
pos2.chess[i, j] = pos2.chess[i - 1, j];
}
pos2.chess[0, j] = 0;
ret[count++] = pos2;
}
}
}
return ret;
}
private bool reachedMaxDepth(Position p, int depth)
{
// TODO Auto-generated method stub
bool ret = false;
if (wonPosition(p, false)) ret = true;
else if (wonPosition(p, true)) ret = true;
else if (drawnPosition(p)) ret = true;
else if (depth >= maxDepth) ret = true;
return ret;
}
private bool wonPosition(Position pos, bool player)
{
int b;
if (player) b = Position.HUMAN_CHESS;
else b = Position.PROGRAM_CHESS;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
if (j + 3 < column)
if (pos.chess[i, j] == b && pos.chess[i, j] == pos.chess[i, j + 1] && pos.chess[i, j] == pos.chess[i, j + 2] && pos.chess[i, j] == pos.chess[i, j + 3]) return true;
if (i + 3 < row)
if (pos.chess[i, j] == b && pos.chess[i, j] == pos.chess[i + 1, j] && pos.chess[i, j] == pos.chess[i + 2, j] && pos.chess[i, j] == pos.chess[i + 3, j]) return true;
if (i + 3 < row && j + 3 < column)
if (pos.chess[i, j] == b && pos.chess[i, j] == pos.chess[i + 1, j + 1] && pos.chess[i, j] == pos.chess[i + 2, j + 2] && pos.chess[i, j] == pos.chess[i + 3, j + 3]) return true;
if (i + 3 < row && j - 3 >= 0)
if (pos.chess[i, j] == b && pos.chess[i, j] == pos.chess[i + 1, j - 1] && pos.chess[i, j] == pos.chess[i + 2, j - 2] && pos.chess[i, j] == pos.chess[i + 3, j - 3]) return true;
}
}
return false;
}
private short[,] getNewArray(short[,] aChess)
{
short[,] newArray = new short[aChess.GetLength(0), aChess.GetLength(1)];
for (int i = 0; i < aChess.GetLength(0); i++)
for (int j = 0; j < aChess.GetLength(1); j++)
newArray[i, j] = aChess[i, j];
return newArray;
}
private float positionEvaluation(Position pos, bool player)
{
// TODO Auto-generated method stub
if (wonPosition(pos, player)) {
return float.PositiveInfinity;
}
if (wonPosition(pos, !player)) {
return float.NegativeInfinity;
}
int ret= 0;
int myChessman;
int enemyChessman;
if(player) {
myChessman = Position.HUMAN_CHESS;
enemyChessman = Position.PROGRAM_CHESS;
}
else {
myChessman = Position.PROGRAM_CHESS;
enemyChessman = Position.HUMAN_CHESS;
}
int[] myConnect3 = connect3(pos, player);
int[] enemyConnect3 = connect3(pos , !player);
int[] myConnect2 = connect2(pos, player);
int[] enemyConnect2 = connect2(pos, !player);
for(int i = 0; i < board.chess.GetLength(0); i++) {
for(int j = 0; j < board.chess.GetLength(1); j++) {
if(board.chess[i, j] == myChessman)
ret += 5;
else if(board.chess[i, j] == enemyChessman)
ret -= 5;
}
}
//evaluation function
ret += (myConnect2[1] * 30 + myConnect2[2] * 50);
ret += (myConnect2[0] - myConnect2[1] - myConnect2[2]) * 15;
ret -= (enemyConnect2[0] - enemyConnect2[1] - enemyConnect2[2]) * 15;
ret -= (enemyConnect2[1] * 30 + enemyConnect2[2] * 50);
ret += (myConnect3[0] - myConnect3[1] - myConnect3[2]) * 50;
ret -= (enemyConnect3[0] - enemyConnect3[1] - enemyConnect3[2]) * 50;
ret += myConnect3[1] * 100;
ret -= enemyConnect3[1] * 100;
return ret;
}
private int[] connect2(Position pos, bool player)
{
short b;
if(player) b = Position.HUMAN_CHESS;
else b = Position.PROGRAM_CHESS;
int[] n = {0, 0, 0};
for(int i = 0; i < pos.chess.GetLength(0); i++) {
for(int j = 0; j < pos.chess.GetLength(1); j++) {
if (i + 1 < pos.chess.GetLength(0))
{
if(pos.chess[i, j] == b && pos.chess[i, j] == pos.chess[i+1, j]) {
while(true) {
if (i + 2 < pos.chess.GetLength(0))
if(pos.chess[i+2, j] == b) break;
if(i-1 >= 0)
if(pos.chess[i-1, j] == b) break;
n[0]++;
if (i - 1 >= 0 && i + 2 >= pos.chess.GetLength(0))
{
if(pos.chess[i-1, j] == Position.EMPTY)
n[1]++;
}
else if (i - 1 < 0 && i + 2 < pos.chess.GetLength(0))
{
if(pos.chess[i+2, j] == Position.EMPTY)
n[1]++;
}
else if (i - 1 >= 0 && i + 2 < pos.chess.GetLength(0))
{
if(pos.chess[i-1, j] == Position.EMPTY && pos.chess[i+2, j] != Position.EMPTY)
n[1]++;
if(pos.chess[i+2, j] == Position.EMPTY && pos.chess[i-1, j] != Position.EMPTY)
n[1]++;
if(pos.chess[i-1, j] == Position.EMPTY && pos.chess[i+2, j] == Position.EMPTY)
n[2]++;
}
break;
}
}
}
if (j + 1 < pos.chess.GetLength(1))
{
if(pos.chess[i, j] == b && pos.chess[i, j] == pos.chess[i, j+1]) {
while(true) {
if (j + 2 < pos.chess.GetLength(1))
if(pos.chess[i, j+2] == b) break;
if(j-1 >= 0)
if(pos.chess[i, j-1] == b) break;
n[0]++;
if (j - 1 >= 0 && j + 2 >= pos.chess.GetLength(1))
{
if(pos.chess[i, j-1] == Position.EMPTY)
n[1]++;
}
else if (j - 1 < 0 && j + 2 < pos.chess.GetLength(1))
{
if(pos.chess[i, j+2] == Position.EMPTY)
n[1]++;
}
else if (j - 1 >= 0 && j + 2 < pos.chess.GetLength(1))
{
if(pos.chess[i, j-1] == Position.EMPTY && pos.chess[i, j+2] != Position.EMPTY)
n[1]++;
if(pos.chess[i, j+2] == Position.EMPTY && pos.chess[i, j-1] != Position.EMPTY)
n[1]++;
if(pos.chess[i, j-1] == Position.EMPTY && pos.chess[i, j+2] == Position.EMPTY)
n[2]++;
}
break;
}
}
}
if (i + 1 < pos.chess.GetLength(0) && j + 1 < pos.chess.GetLength(1))
{
if(pos.chess[i, j] == b && pos.chess[i, j] == pos.chess[i+1, j+1]) {
while(true) {
if (i + 2 < pos.chess.GetLength(0) && j + 2 < pos.chess.GetLength(1))
if(pos.chess[i+2, j+2] == b) break;
if(i-1 >= 0 && j-1 >= 0)
if(pos.chess[i-1, j-1] == b) break;
n[0]++;
if ((i - 1 >= 0 && j - 1 >= 0) && (i + 2 >= pos.chess.GetLength(0) || j + 2 >= pos.chess.GetLength(1)))
{
if(pos.chess[i-1, j-1] == Position.EMPTY)
n[1]++;
}
else if ((i - 1 < 0 || j - 1 < 0) && (i + 2 < pos.chess.GetLength(0) && j + 2 < pos.chess.GetLength(1)))
{
if(pos.chess[i+2, j+2] == Position.EMPTY)
n[1]++;
}
else if ((i - 1 >= 0 && j - 1 >= 0) && (i + 2 < pos.chess.GetLength(0) && j + 2 < pos.chess.GetLength(1)))
{
if(pos.chess[i-1, j-1] == Position.EMPTY && pos.chess[i+2, j+2] != Position.EMPTY)
n[1]++;
if(pos.chess[i+2, j+2] == Position.EMPTY && pos.chess[i-1, j-1] != Position.EMPTY)
n[1]++;
if(pos.chess[i-1, j-1] == Position.EMPTY && pos.chess[i+2, j+2] == Position.EMPTY)
n[2]++;
}
break;
}
}
}
if(i-1 >= 0 && j+1 < pos.chess.GetLength(1)) {
if(pos.chess[i, j] == b && pos.chess[i, j] == pos.chess[i-1, j+1]) {
while(true) {
if (i - 2 >= 0 && j + 2 < pos.chess.GetLength(1))
if(pos.chess[i-2, j+2] == b) break;
if(i+1 < pos.chess.GetLength(0) && j-1 >= 0)
if(pos.chess[i+1, j-1] == b) break;
n[0]++;
if ((i - 2 >= 0 && j + 2 < pos.chess.GetLength(1)) && (i + 1 >= pos.chess.GetLength(0) || j - 1 < 0))
{
if(pos.chess[i-2, j+2] == Position.EMPTY)
n[1]++;
}
else if ((i - 2 < 0 || j + 2 > pos.chess.GetLength(1)) && (i + 1 < pos.chess.GetLength(0) && j - 1 >= 0))
{
if(pos.chess[i+1, j-1] == Position.EMPTY)
n[1]++;
}
else if ((i - 2 >= 0 && j + 2 < pos.chess.GetLength(1)) && (i + 1 < pos.chess.GetLength(0) && j - 1 >= 0))
{
if(pos.chess[i-2, j+2] == Position.EMPTY && pos.chess[i+1, j-1] != Position.EMPTY)
n[1]++;
if(pos.chess[i+1, j-1] == Position.EMPTY && pos.chess[i-2, j+2] != Position.EMPTY)
n[1]++;
if(pos.chess[i-2, j+2] == Position.EMPTY && pos.chess[i+1, j-1] == Position.EMPTY)
n[2]++;
}
break;
}
}
}
}
}
return n;
}
private int[] connect3(Position pos, bool player) {
short b;
if(player) b = Position.HUMAN_CHESS;
else b = Position.PROGRAM_CHESS;
int[] n = {0, 0, 0};
for(int i = 0; i < pos.chess.GetLength(0); i++) {
for(int j = 0; j < pos.chess.GetLength(1); j++) {
if (i + 2 < pos.chess.GetLength(0))
{
if(pos.chess[i, j] == b
&& pos.chess[i, j] == pos.chess[i+1, j]
&& pos.chess[i, j] == pos.chess[i+2, j]) {
while(true) {
if(i+3 < pos.chess.GetLength(0))
if(pos.chess[i+3, j] == b) break;
if(i-1 >= 0)
if(pos.chess[i-1, j] == b) break;
n[0]++;
if (i - 1 >= 0 && i + 3 >= pos.chess.GetLength(0))
{
if(pos.chess[i-1, j] == Position.EMPTY)
n[1]++;
}
else if(i-1 < 0 && i+3 < pos.chess.GetLength(0)) {
if(pos.chess[i+3, j] == Position.EMPTY)
n[1]++;
}
else if(i-1 >= 0 && i+3 < pos.chess.GetLength(0)) {
if(pos.chess[i-1, j] == Position.EMPTY
&& pos.chess[i+3, j] != Position.EMPTY)
n[1]++;
if(pos.chess[i+3, j] == Position.EMPTY
&& pos.chess[i-1, j] != Position.EMPTY)
n[1]++;
if(pos.chess[i-1, j] == Position.EMPTY
&& pos.chess[i+3, j] == Position.EMPTY)
n[2]++;
}
break;
}
}
}
if(j+2 < pos.chess.GetLength(1)) {
if(pos.chess[i, j] == b
&& pos.chess[i, j] == pos.chess[i, j+1]
&& pos.chess[i, j] == pos.chess[i, j+2]) {
while(true) {
if(j+3 < pos.chess.GetLength(1))
if(pos.chess[i, j+3] == b) break;
if(j-1 >= 0)
if(pos.chess[i, j-1] == b) break;
n[0]++;
if(j-1 >= 0 && j+3 >= pos.chess.GetLength(1)) {
if(pos.chess[i, j-1] == Position.EMPTY)
n[1]++;
}
else if(j-1 < 0 && j+3 < pos.chess.GetLength(1)) {
if(pos.chess[i, j+3] == Position.EMPTY)
n[1]++;
}
else if(j-1 >= 0 && j+3 < pos.chess.GetLength(1)) {
if(pos.chess[i, j-1] == Position.EMPTY
&& pos.chess[i, j+3] != Position.EMPTY)
n[1]++;
if(pos.chess[i, j+3] == Position.EMPTY
&& pos.chess[i, j-1] != Position.EMPTY)
n[1]++;
if(pos.chess[i, j-1] == Position.EMPTY
&& pos.chess[i, j+3] == Position.EMPTY)
n[2]++;
}
break;
}
}
}
if (i + 2 < pos.chess.GetLength(0) && j + 2 < pos.chess.GetLength(1))
{
if(pos.chess[i, j] == b
&& pos.chess[i, j] == pos.chess[i+1, j+1]
&& pos.chess[i, j] == pos.chess[i+2, j+2]) {
while(true) {
if(i+3 < pos.chess.GetLength(0) && j+3 < pos.chess.GetLength(1))
if(pos.chess[i+3, j+3] == b) break;
if(i-1 >= 0 && j-1 >= 0)
if(pos.chess[i-1, j-1] == b) break;
n[0]++;
if((i-1 >= 0 && j-1 >= 0) && (i+3 >= pos.chess.GetLength(0) || j+3 >= pos.chess.GetLength(1))) {
if(pos.chess[i-1, j-1] == Position.EMPTY)
n[1]++;
}
else if((i-1 < 0 || j-1 < 0) && (i+3 < pos.chess.GetLength(0) && j+3 < pos.chess.GetLength(1))) {
if(pos.chess[i+3, j+3] == Position.EMPTY)
n[1]++;
}
else if((i-1 >= 0 && j-1 >= 0) && (i+3 < pos.chess.GetLength(0) && j+3 < pos.chess.GetLength(1))) {
if(pos.chess[i-1, j-1] == Position.EMPTY
&& pos.chess[i+3, j+3] != Position.EMPTY)
n[1]++;
if(pos.chess[i+3, j+3] == Position.EMPTY
&& pos.chess[i-1, j-1] != Position.EMPTY)
n[1]++;
if(pos.chess[i-1, j-1] == Position.EMPTY && pos.chess[i+3, j+3] == Position.EMPTY)
n[2]++;
}
break;
}
}
}
if(i-2 >= 0 && j+2 < pos.chess.GetLength(1)) {
if(pos.chess[i, j] == b
&& pos.chess[i, j] == pos.chess[i-1, j+1]
&& pos.chess[i, j] == pos.chess[i-2, j+2]) {
while(true) {
if(i-3 >= 0 && j+3 < pos.chess.GetLength(1))
if(pos.chess[i-3, j+3] == b) break;
if(i+1 < pos.chess.GetLength(0) && j-1 >= 0)
if(pos.chess[i+1, j-1] == b) break;
n[0]++;
if((i-3 >= 0 && j+3 < pos.chess.GetLength(1)) && (i+1 >= pos.chess.GetLength(0) || j-1 < 0)) {
if(pos.chess[i-3, j+3] == Position.EMPTY)
n[1]++;
}
else if((i-3 < 0 || j+3 > pos.chess.GetLength(1)) && (i+1 < pos.chess.GetLength(0) && j-1 >= 0)) {
if(pos.chess[i+1, j-1] == Position.EMPTY)
n[1]++;
}
else if((i-3 >= 0 && j+3 < pos.chess.GetLength(1)) && (i+1 < pos.chess.GetLength(0) && j-1 >= 0)) {
if(pos.chess[i-3, j+3] == Position.EMPTY
&& pos.chess[i+1, j-1] != Position.EMPTY)
n[1]++;
if(pos.chess[i+1, j-1] == Position.EMPTY
&& pos.chess[i-3, j+3] != Position.EMPTY)
n[1]++;
if(pos.chess[i-3, j+3] == Position.EMPTY && pos.chess[i+1, j-1] == Position.EMPTY)
n[2]++;
}
break;
}
}
}
}
}
return n;
}
class Position
{
public const byte EMPTY = 0;
public const byte HUMAN_CHESS = 1;
public const byte PROGRAM_CHESS = 2;
public short[,] chess = new short[row, column];
public Position()
{
for (int i = 0; i < row; i++)
for (int j = 0; j < column; j++)
chess[i, j] = EMPTY;
}
}
private void btn_Human_Click(object sender, RoutedEventArgs e)
{
board = new Position();
if (txbSearchDepth.Text != "") maxDepth = Convert.ToInt32(txbSearchDepth.Text);
player = HUMAN;
canClick = true;
DrawChessBoard();
}
private void btn_Program_First(object sender, RoutedEventArgs e)
{
board = new Position();
if (txbSearchDepth.Text != "")
{
try { maxDepth = Convert.ToInt32(txbSearchDepth.Text); }
catch (Exception) { }
}
player = PROGRAM;
canClick = false;
programTurn();
DrawChessBoard();
canClick = true;
player = HUMAN;
}
}
}