Introduction to Black and white chess
Black and white, also known as Apple Chess, was first popular in western countries. The game by flipping each other's pieces, and finally on the chessboard who more to judge the outcome. Black and white is very easy to use, but mastery needs to take into account a number of factors, such as the corner of the special position, stability, driving force and so on. This game name is black and white chess master, provided 8 kinds of difficulty level choice, from rookie, novice, get started, chess player to chess, Master, Guru, Qisheng, help you continuously enhance chess force.
Othello Game Rules
The rules of the game see a screenshot of the Master of Othello.
Black and white chess master game screenshot
Game start interface.
A screenshot of the game process.
The option to open the new Bureau, the choice of hand and AI level.
A few key classes
Rule
The rule class implements game-related methods, including
1. Determining whether a step is legal
2. Get all the legal walks
3. Take one step and flip the enemy pieces
4. Statistics of the number of two-side pieces
Algorithm
The algorithm class implements Minimax algorithms, including
1. The situation assessment function, the current situation rating, the higher the more favorable to Max, the lower the more favorable for the min
2.min () method
3.max () method
4. Get a good walk
Reversiview
Reversiview inherits from the Surfaceview, realizes the board interface, in this class defines the board interface the drawing, the renewal and so on the operation.
Renderthread
Renderthread inherits from thread, is the thread that controls the Reversiview to update and redraw the interface with a certain FPS.
Concrete implementation
Board representation
byte[][]
Two-dimensional array storage chessboard,-1 indicates that there are sunspots, 1 indicates a white child, 0 means that the chess grid is empty
The realization of rule of game rules
Provides a few static methods about the rules of the game.
Determine if a position is in the chessboard
public static Boolean islegal (int row, int col) {return
row >= 0 && Row < 8 && Col >= 0 ;& Col < 8;
}
Determine whether a party is drop legal at a certain location
That is to determine whether the son can be in a certain direction with their own pieces of the enemy pieces.
public static Boolean Islegalmove (byte[][] chessboard, move move, byte chesscolor) {
int i, J, DirX, diry, row = move. Row, col = Move.col;
if (!islegal (row, col) | | | chessboard[row][col]!= constant.null) return
false;
for (DirX =-1; DirX < 2, dirx++) {for
(DirY =-1; diry < 2; diry++) {
if (DirX = 0 && diry = 0) Continue;
int x = col + DirX, y = row + DirY;
if (Islegal (y, x) && chessboard[y][x] = = (-chesscolor)) {
for (i = row + DirY * 2, J = col + DirX * 2; islegal (I, j); i + = DirY, j + = DirX) {
if (chessboard[i][j] = = (-chesscolor)) {
continue;
} else if (chessboard[i][j] = C Hesscolor) {return
true;
} else {break
;
}}}} return false;
}
One side, one step.
The
Changes the color of the pieces that are flipped in all directions, and returns the positions of the pieces on the board, which facilitates the display of rollover animations.
public static list<move> Move (byte[][] chessboard, move move, byte chesscolor) {int row = Move.row;
int col = Move.col;
int I, J, temp, M, N, DirX, DirY;
List<move> moves = new arraylist<move> (); for (DirX =-1; DirX < 2, dirx++) {for (DirY =-1; diry < 2; diry++) {if (DirX = 0 && diry = 0
) continue;
temp = 0;
int x = col + DirX, y = row + DirY;
if (Islegal (y, x) && chessboard[y][x] = = (-chesscolor)) {temp++; for (i = row + DirY * 2, J = col + DirX * 2; Islegal (i, j); i + = DirY, j + + DirX) {if (chessboard[i][j) = = (-ch
Esscolor)) {temp++;
Continue else if (chessboard[i][j] = = Chesscolor) {for (M = row + DirY, n = col + DirX; m <= row + temp && ; M >= row-temp && n <= col + temp && n >= col-temp;
M + = DirY, n + = DirX) {Chessboard[m][n] = Chesscolor; Moves.add (New Move (M, N));
} break;
else break;
}}} Chessboard[row][col] = Chesscolor;
return moves; }
Get the drop position of a party that is currently all valid
public static list<move> getlegalmoves (byte[][] chessboard, byte chesscolor) {
list<move> moves = new ARR Aylist<move> ();
Move move = null;
for (int row = 0; row < 8; row++) {for
(int col = 0; col < 8; col++) {Move
= new Move (row, col);
if (Rule.islegalmove (chessboard, move, Chesscolor)) {
moves.add (move);
}}} return moves;
}
Count the number of players and AI pieces
public static statistic analyse (byte[][] chessboard, byte playercolor) {
int PLAYER = 0;
int AI = 0;
for (int i = 0; i < 8; i++) {for
(int j = 0; J < 8; J +) {
if (chessboard[i][j] = = Playercolor) Play
ER + 1;
else if (chessboard[i][j] = = (byte)-playercolor)
AI = 1
;
}
return new statistic (PLAYER, AI);
}
Implementation of Game algorithm class algorithm
Maximum process and minimum process
The functions of these two procedures are as follows:
Copy Code code as follows:
private static Minimaxresult Max (byte[][] chessboard, int depth, int alpha, int beta, byte chesscolor, int difficulty);
private static Minimaxresult min (byte[][] chessboard, int depth, int alpha, int beta, byte chesscolor, int difficulty);
Chessboard is a chessboard; depth for game tree search depth; Alpha and beta for Alpha-beta pruning, in the Max Method Alpha is constantly updated to the larger value of the situation score, and Beta is constantly updated in the Min method for the smaller value of the situation score, when Alpha >= in Beta, Chesscolor represents the color of the pieces, difficulty means the difficulty of the game, corresponding to different AI levels.
Because sunspots first, sunspots always call the Max () method, and the white Child calls the Min () method.
Here's an example of a great process.
If the depth is 0, just return to the current situation score. If both sides have no steps to go, they have reached the final stage and returned to the situation to score. If there is only unilateral nowhere to go, call min recursion can be.
Normally there are steps to walk through each of the legitimate walks, if Alpha is greater than or equal to beta, prune the direct break, otherwise move and recursion.
Best is an optimal value for the current max node maintenance, and the called Min Method's alpha is a larger value for Alpha and best.
private static Minimaxresult Max (byte[][] chessboard, int depth, int alpha, int beta, byte chesscolor, int difficulty) {
if (depth = = 0) {return new Minimaxresult (Evaluate (chessboard, difficulty), NULL);
} list<move> legalmovesme = Rule.getlegalmoves (chessboard, chesscolor); if (legalmovesme.size () = = 0) {if (Rule.getlegalmoves (chessboard, (byte)-chesscolor). Size () = 0) {return new
Minimaxresult (Evaluate (chessboard, difficulty), NULL);
return min (chessboard, depth, alpha, beta, (byte)-chesscolor, difficulty);
} byte[][] tmp = new BYTE[8][8];
Util.copybinaryarray (chessboard, TMP);
int best = Integer.min_value;
Move move = NULL;
for (int i = 0; i < legalmovesme.size (); i++) {alpha = Math.max (best, Alpha);
if (Alpha >= beta) {break;
} rule.move (Chessboard, Legalmovesme.get (i), chesscolor);
int value = min (chessboard, depth-1, Math.max (best, Alpha), Beta, (byte)-chesscolor, difficulty). Mark; if (VAlue > Best) {best = value;
move = Legalmovesme.get (i);
} util.copybinaryarray (TMP, chessboard);
Return to New Minimaxresult (best, move); private static Minimaxresult min (byte[][] chessboard, int depth, int alpha, int beta, byte chesscolor, int difficulty)
{if (depth = = 0) {return new Minimaxresult (Evaluate (chessboard, difficulty), NULL);
} list<move> legalmovesme = Rule.getlegalmoves (chessboard, chesscolor); if (legalmovesme.size () = = 0) {if (Rule.getlegalmoves (chessboard, (byte)-chesscolor). Size () = 0) {return new
Minimaxresult (Evaluate (chessboard, difficulty), NULL);
Return Max (chessboard, depth, alpha, beta, (byte)-chesscolor, difficulty);
} byte[][] tmp = new BYTE[8][8];
Util.copybinaryarray (chessboard, TMP);
int best = Integer.max_value;
Move move = NULL;
for (int i = 0; i < legalmovesme.size (); i++) {beta = math.min (best, beta);
if (Alpha >= beta) {break; } rule.move(Chessboard, Legalmovesme.get (i), chesscolor);
int value = max (chessboard, depth-1, Alpha, math.min (best, Beta), (byte)-chesscolor, difficulty). Mark;
if (value < best) {best = value;
move = Legalmovesme.get (i);
} util.copybinaryarray (TMP, chessboard);
Return to New Minimaxresult (best, move); }
The principle of Alpha-beta pruning
To explain the physical meaning of alpha and beta first, Alpha represents the best situation score so far for the Max node, and Beta indicates the best situation score to date for the Min node.
For example, see the following figure (a fictitious number), assuming that the depth is two layers, each node has two lines of numbers, and the top two numbers are alpha and beta, representing the alpha and beta of the layer as parameters. The number below represents the best update process for the node.
Look at the first Red fork in the picture, where the lower value of beta positive infinity and 2 is updated, that is, 2, which causes Alpha to be greater than or equal to beta, resulting in pruning, corresponding to the break operation at the corresponding position in the Min method.
Get the best walk from AI calculations
This method is used for AI walking and prompting function.
public static Move getgoodmove (byte[][] chessboard, int depth, byte chesscolor, int difficulty) {
if (Chesscolor = Co Nstant. Black) return to
Max (chessboard, depth, Integer.min_value, Integer.max_value, Chesscolor, difficulty). Move;
else return
min (chessboard, depth, Integer.min_value, Integer.max_value, Chesscolor, difficulty). Move;
Situation assessment function
The evaluation function of the situation determines the level of AI. Corresponding to different AI levels, different evaluation functions are designed.
Rookie level only focus on the number of pieces, beginners, beginners, chess player 3 levels not only focus on the number of pieces, and pay attention to the special position of the pieces (edge, angle), chess and master level in the number of pieces, the corner also considered the action Force, that is, the other side of the next optional position of the number of positions, the guru and Qisheng consider stability and action Force. The degree of stability will be described in the next section.
private static int Evaluate (byte[][] chessboard, int difficulty) {int whiteevaluate = 0;
int blackevaluate = 0;
Switch (difficulty) {case 1:for (int i = 0; i < 8; i++) {for (int j = 0; J < 8; J +) {
if (chessboard[i][j] = white) {whiteevaluate + + 1;
else if (chessboard[i][j] = black) {blackevaluate = 1;
}} break;
Case 2:case 3:case 4:for (int i = 0; i < 8; i++) {for (int j = 0; J < 8; J +) { if ((i = = 0 | | | i = = 7) && (j = = 0 | | j = = 7)) {if (chessboard[i][j] = white) {Whiteev
Aluate + 5;
else if (chessboard[i][j] = black) {blackevaluate = 5;
Or else if (i = = 0 | | i = = 7 | | | = = 0 | | j = = 7) {if (chessboard[i][j] = white) {
Whiteevaluate + 2;
else if (chessboard[i][j] = black) { Blackevaluate + 2;
} else {if (chessboard[i][j] = white) {whiteevaluate = 1;
else if (chessboard[i][j] = black) {blackevaluate = 1;
Break in}}}; Case 5:case 6:for (int i = 0; i < 8; i++) {for (int j = 0; J < 8; J +) {if (i = = 0 ||
i = = 7) && (j = = 0 | | | j = = 7)) {if (chessboard[i][j] = white) {whiteevaluate + = 5;
else if (chessboard[i][j] = black) {blackevaluate = 5;
Or else if (i = = 0 | | i = = 7 | | | = = 0 | | j = = 7) {if (chessboard[i][j] = white) {
Whiteevaluate + 2;
else if (chessboard[i][j] = black) {blackevaluate = 2;
} else {if (chessboard[i][j] = white) {whiteevaluate = 1; else if (ChessboaRD[I][J] = = Black) {blackevaluate + + 1;
}} blackevaluate = Blackevaluate * 2 + rule.getlegalmoves (chessboard, black). Size ();
Whiteevaluate = whiteevaluate * 2 + rule.getlegalmoves (chessboard, white). Size ();
Break Case 7:case 8:/** * stability * * (int i = 0; i < 9; i++) {for (int j = 0; J < 9;
J + +) {int weight[] = new int[] {2, 4, 6, 10, 15};
if (chessboard[i][j] = white) {whiteevaluate + = Weight[getstabilizationdegree (chessboard, new Move (I, j))]; else if (chessboard[i][j] = black) {blackevaluate + = Weight[getstabilizationdegree (chessboard, n
EW Move (i, j))];
}}/** * Action Force * * blackevaluate + = rule.getlegalmoves (chessboard, black). Size ();
Whiteevaluate + = rule.getlegalmoves (chessboard, white). Size ();
Break Return blackevaluate-wHiteevaluate; }
Calculation of stability
We know that in Black-and-white chess, the position of the four corners of the chessboard once occupy is impossible to be flipped again, so the son of these positions is bound to be stable, and the edge of the child can only be reversed along the direction of the edge, the degree of stability than the middle of the position of the child
Therefore, an attempt is made to define a degree of stability for each child, describing how stable the child is not to be flipped.
A total of four directions, namely left-right, up-down, upper left-right, upper right-lower left. For example, the following code (DROW[0][0], dcol[0][0]) represents a vector that moves one unit to the left (Drow[0][1], dcol[0][1) to the vector that moves one unit to the right.
For the position of a child in the chessboard, find the first position that is not the color to the left (can be out of bounds), and then to the right to find the first location that is not the color (can be out of bounds), if the two positions at least one out of bounds, or two are enemy pieces, stability plus 1.
Do the same for the other three directions. You can see that the angle of the pieces of the stability must be 4, other positions according to the specific situation is not constant.
private static int Getstabilizationdegree (byte[][] chessboard, move move) {int chesscolor = Chessboard[move.row][mov
E.col];
int drow[][], dcol[][];
int row[] = new int[2], col[] = new INT[2];
int degree = 0;
Drow = new int[][] {{0, 0}, {-1, 1}, {-1, 1}, {1,-1}};
Dcol = new int[][] {{-1, 1}, {0, 0}, {-1, 1}, {-1, 1}};
for (int k = 0; k < 4; k++) {row[0] = row[1] = Move.row;
Col[0] = col[1] = Move.col; for (int i = 0; i < 2 i++) {while (Rule.islegal (row[i) + drow[k][i], Col[i] + dcol[k][i]) &&A mp
Chessboard[row[i] + drow[k][i]][col[i] + dcol[k][i]] = = Chesscolor) {Row[i] + = Drow[k][i];
Col[i] + = Dcol[k][i]; } if (! Rule.islegal (Row[0] + drow[k][0], col[0] + dcol[k][0]) | | !
Rule.islegal (Row[1] + drow[k][1], col[1] + dcol[k][1)) {degree = 1; else if (Chessboard[row[0] + drow[k][0]][col[0] + dcol[k][0]] = = = (-chesscoloR) && Chessboard[row[1] + drow[k][1]][col[1] + dcol[k][1] = = = (-chesscolor)) {degree = 1;
} return degree; }
The above is the Android black and white game realization process and the entire content of the code resolution, I believe this article for everyone to develop the Android black and white game is very helpful, thank you for the cloud Habitat Community support.