Created
August 25, 2017 03:22
-
-
Save luyao795/1c39cf815c30024d05bea95f60925c02 to your computer and use it in GitHub Desktop.
This class controls the flow of the game, both AI and Board will call functions from this class.
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
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
public class GameController { | |
public int[,] boardState; | |
// 8 directions that we need to check | |
public Vector2 up = new Vector2 (0, 1); | |
public Vector2 right = new Vector2(1, 0); | |
public Vector2 left = new Vector2 (-1, 0); | |
public Vector2 down = new Vector2 (0, -1); | |
public Vector2 upright = new Vector2 (1, 1); | |
public Vector2 downleft = new Vector2(-1, -1); | |
public Vector2 upleft = new Vector2 (-1, 1); | |
public Vector2 downright = new Vector2 (1, -1); | |
// public List<Vector2> playerAction; | |
// public List<Vector2> AIAction; | |
// used to record whose turn it is | |
// 1 for human player, 2 for AI | |
public int colorTurn; | |
public void InitBoard() | |
{ | |
boardState = new int[,] { | |
{ 0, 0, 0, 0, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 0, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 0, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 0, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 0, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 0, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 0, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 0, 0, 0, 0, 0 } | |
}; | |
boardState [3, 3] = 2; | |
boardState [4, 4] = 2; | |
boardState [3, 4] = 1; | |
boardState [4, 3] = 1; | |
colorTurn = 1; | |
} | |
// check whether point (x, z) is on board | |
private bool IsInRange(int x, int z) | |
{ | |
if (x >= 0 && x <= 7 && z >= 0 && z <= 7) | |
return true; | |
else | |
return false; | |
} | |
// check whether game is over | |
public bool IsGameOver() | |
{ | |
int playerCount = MoveList (boardState, 1).Count; | |
int AICount = MoveList (boardState, 2).Count; | |
if (playerCount == 0 && AICount == 0) | |
return true; | |
else | |
return false; | |
} | |
// (x, z) is the starting point and dir is the direction we are looking into | |
// human player uses white pieces (1) and AI uses black pieces (2) with white moves first and black moves second | |
// color determines which player is trying to find the flip set | |
// color = [1, 2] where 1 (white) represents human player and 2 (black) represents AI | |
// this will be a private function eventually but for the test purpose it is not set up as public | |
public bool IsFlipSet(int[,] board, int color, int x, int z, Vector2 dir) | |
{ | |
int xcoord = x; | |
int zcoord = z; | |
int hDir = (int)dir.x; // x value of the direction vector | |
int vDir = (int)dir.y; // y value of the direction vector | |
//Debug.Log (hDir + ", " + vDir); | |
//Debug.Log (xcoord + ", " + zcoord); | |
if (!IsInRange (xcoord, zcoord)) { | |
return false; | |
} else if (board [xcoord, zcoord] != 0) { | |
//Debug.Log ("You can't set pieces on another piece!"); | |
return false; // if the starting point is not empty, return false | |
} | |
else { | |
// checking flip set for player 1 | |
if (color == 1) { // this is to check whether the human player can form a flip set on position [x, z] on board | |
if (IsInRange (xcoord + hDir, zcoord + vDir)) { | |
if (board [xcoord + hDir, zcoord + vDir] != 2) { // if the piece next to starting point is not enemy piece | |
//Debug.Log((xcoord + hDir) + ", " + (zcoord + vDir) + " is " + boardState [xcoord + hDir, zcoord + vDir]); | |
//Debug.Log ("There is no way to flip non-enemy pieces!"); | |
return false; | |
} // then return false since you cannot flip your own piece or empty slot | |
else { // if the piece next to starting point is an enemy piece | |
xcoord += hDir; // now our focus is one movement along the direction | |
zcoord += vDir; // to see if on the direction there are more pieces | |
while (IsInRange (xcoord + hDir, zcoord + vDir)) { | |
// case 1 | |
if (board [xcoord + hDir, zcoord + vDir] == 0) { | |
//Debug.Log((xcoord + hDir) + ", " + (zcoord + vDir) + " is " + boardState [xcoord + hDir, zcoord + vDir]); | |
//Debug.Log ((xcoord + hDir) + ", " + (zcoord + vDir) + " is an empty slot!"); | |
return false; // if there is an empty slot before finding our piece | |
//break; // then this is not a flip set | |
// something like: | . . + o o x . | |
// where | is the boundary of the board, o are enemy pieces, x is our starting point, and | |
// + is an empty slot. Apparently we cannot put our piece at x since there is no our piece on | |
// this direction, so there is no way to flip enemy pieces. | |
} | |
// case 2 | |
else if (board [xcoord + hDir, zcoord + vDir] == 1) { | |
//Debug.Log((xcoord + hDir) + ", " + (zcoord + vDir) + " is " + boardState [xcoord + hDir, zcoord + vDir]); | |
//Debug.Log ((xcoord + hDir) + ", " + (zcoord + vDir) + " is an friendly piece!"); | |
return true; // if there is an friendly piece along the direction | |
//break; // then return true since this is a flip set | |
// something like: | . . x o o + . | |
// where | is the boundary of the board, o are enemy pieces, x is our piece, and | |
// + is our starting point. Apparently we can put our piece at + since there is one | |
// friendly piece along the direction so by setting our piece at +, we can flip | |
// those two enemy pieces | |
} | |
// case 3 | |
else if (board [xcoord + hDir, zcoord + vDir] == 2) { | |
//Debug.Log((xcoord + hDir) + ", " + (zcoord + vDir) + " is " + boardState [xcoord + hDir, zcoord + vDir]); | |
//Debug.Log ((xcoord + hDir) + ", " + (zcoord + vDir) + " is an enemy piece!"); | |
xcoord += hDir; // keep checking the direction | |
zcoord += vDir; | |
} | |
} | |
return false; | |
} | |
} else | |
return false; | |
} else if (color == 2) { // this is to check whether the AI player can form a flip set on position [x, z] on board | |
if (IsInRange (xcoord + hDir, zcoord + vDir)) { | |
if (board [xcoord + hDir, zcoord + vDir] != 1) { // if the piece next to starting point is not enemy piece | |
//Debug.Log((xcoord + hDir) + ", " + (zcoord + vDir) + " is " + boardState [xcoord + hDir, zcoord + vDir]); | |
//Debug.Log ("There is no way to flip non-enemy pieces!"); | |
return false; | |
} // then return false since you cannot flip your own piece or empty slot | |
else { // if the piece next to starting point is an enemy piece | |
xcoord += hDir; // now our focus is one movement along the direction | |
zcoord += vDir; // to see if on the direction there are more pieces | |
while (IsInRange (xcoord + hDir, zcoord + vDir)) { | |
// case 1 | |
if (board [xcoord + hDir, zcoord + vDir] == 0) { | |
//Debug.Log((xcoord + hDir) + ", " + (zcoord + vDir) + " is " + boardState [xcoord + hDir, zcoord + vDir]); | |
//Debug.Log ((xcoord + hDir) + ", " + (zcoord + vDir) + " is an empty slot!"); | |
return false; // if there is an empty slot before finding our piece | |
//break; // then this is not a flip set | |
// something like: | . . + o o x . | |
// where | is the boundary of the board, o are enemy pieces, x is our starting point, and | |
// + is an empty slot. Apparently we cannot put our piece at x since there is no our piece on | |
// this direction, so there is no way to flip enemy pieces. | |
} | |
// case 2 | |
else if (board [xcoord + hDir, zcoord + vDir] == 2) { | |
//Debug.Log((xcoord + hDir) + ", " + (zcoord + vDir) + " is " + boardState [xcoord + hDir, zcoord + vDir]); | |
//Debug.Log ((xcoord + hDir) + ", " + (zcoord + vDir) + " is an friendly piece!"); | |
return true; // if there is an friendly piece along the direction | |
//break; // then return true since this is a flip set | |
// something like: | . . x o o + . | |
// where | is the boundary of the board, o are enemy pieces, x is our piece, and | |
// + is our starting point. Apparently we can put our piece at + since there is one | |
// friendly piece along the direction so by setting our piece at +, we can flip | |
// those two enemy pieces | |
} | |
// case 3 | |
else if (board [xcoord + hDir, zcoord + vDir] == 1) { | |
//Debug.Log((xcoord + hDir) + ", " + (zcoord + vDir) + " is " + boardState [xcoord + hDir, zcoord + vDir]); | |
//Debug.Log ((xcoord + hDir) + ", " + (zcoord + vDir) + " is an enemy piece!"); | |
xcoord += hDir; // keep checking the direction | |
zcoord += vDir; | |
} | |
} | |
return false; | |
} | |
} else | |
return false; | |
} else { // The player is neither the human one nor the AI one which is not possible unless Pikachu can evolve into Charizard. | |
Debug.Log ("Invalid player code."); | |
return false; | |
} | |
} | |
} | |
// check whether for player color, whether a piece can be set at [x, z] on board | |
public bool IsValidMove(int[,] board, int color, int x, int z) | |
{ | |
// check all 8 directions for valid flip set | |
bool result1 = IsFlipSet (board, color, x, z, up); | |
bool result2 = IsFlipSet (board, color, x, z, down); | |
bool result3 = IsFlipSet (board, color, x, z, left); | |
bool result4 = IsFlipSet (board, color, x, z, right); | |
bool result5 = IsFlipSet (board, color, x, z, upleft); | |
bool result6 = IsFlipSet (board, color, x, z, upright); | |
bool result7 = IsFlipSet (board, color, x, z, downleft); | |
bool result8 = IsFlipSet (board, color, x, z, downright); | |
if (result1 || result2 || result3 || result4 || result5 || result6 || result7 || result8) | |
return true; // if any of those 8 directions has valid flip set, then this place can be set a piece | |
else | |
return false; // if none of those 8 directions has valid flip set, then this place cannot be set a piece | |
} | |
// all possible moves for current board and color. | |
public List<Vector2> MoveList(int[,] board, int color) | |
{ | |
List<Vector2> list = new List<Vector2> (); | |
if (color == 1) { | |
for (int i = 0; i < 8; i++) { | |
for (int j = 0; j < 8; j++) { | |
if (IsValidMove (board, color, i, j)) { | |
list.Add (new Vector2 (i, j)); | |
} | |
} | |
} | |
} | |
else if (color == 2) { | |
for (int i = 0; i < 8; i++) { | |
for (int j = 0; j < 8; j++) { | |
if (IsValidMove (board, color, i, j)) { | |
list.Add (new Vector2 (i, j)); | |
} | |
} | |
} | |
} | |
return list; | |
} | |
// count how pany pieces belong to color on board | |
public int CountPieces(int[,] board, int color) | |
{ | |
int result = 0; | |
// white player (human) | |
if (color == 1) { | |
for (int i = 0; i < 8; i++) { | |
for (int j = 0; j < 8; j++) { | |
if (board [i, j] == 1) | |
result++; | |
} | |
} | |
} | |
// black player (AI) | |
else if (color == 2) { | |
for (int i = 0; i < 8; i++) { | |
for (int j = 0; j < 8; j++) { | |
if (board [i, j] == 2) | |
result++; | |
} | |
} | |
} | |
return result; | |
} | |
// find directions for valid flip sets | |
public List<Vector2> FindDir(int[,] board, int color, int x, int z) | |
{ | |
List<Vector2> validDir = new List<Vector2> (); | |
if (IsFlipSet (board, color, x, z, up)) { | |
validDir.Add (up); | |
} | |
if (IsFlipSet (board, color, x, z, down)) { | |
validDir.Add (down); | |
} | |
if (IsFlipSet (board, color, x, z, left)) { | |
validDir.Add (left); | |
} | |
if (IsFlipSet (board, color, x, z, right)) { | |
validDir.Add (right); | |
} | |
if (IsFlipSet (board, color, x, z, upleft)) { | |
validDir.Add (upleft); | |
} | |
if (IsFlipSet (board, color, x, z, upright)) { | |
validDir.Add (upright); | |
} | |
if (IsFlipSet (board, color, x, z, downleft)) { | |
validDir.Add (downleft); | |
} | |
if (IsFlipSet (board, color, x, z, downright)) { | |
validDir.Add (downright); | |
} | |
return validDir; | |
} | |
// return the board info after player color makes a move at position (x, z) on board | |
public int[,] GetNextBoard(int[,] board, int color, int x, int z) | |
{ | |
int[,] result = (int[,])board.Clone (); | |
List<Vector2> flipDir; | |
if (result [x, z] == 0) { | |
if (color == 1) { | |
flipDir = FindDir (result, 1, x, z); | |
for (int i = 0; i < flipDir.Count; i++) { | |
int changeX = (int)flipDir.ElementAt (i).x; | |
int changeZ = (int)flipDir.ElementAt (i).y; | |
int posX = x + changeX; | |
int posZ = z + changeZ; | |
while (result [posX, posZ] == 2) { | |
result [posX, posZ] = 1; | |
posX += changeX; | |
posZ += changeZ; | |
} | |
} | |
} | |
if (color == 2) { | |
flipDir = FindDir (result, 2, x, z); | |
for (int i = 0; i < flipDir.Count; i++) { | |
int changeX = (int)flipDir.ElementAt (i).x; | |
int changeZ = (int)flipDir.ElementAt (i).y; | |
int posX = x + changeX; | |
int posZ = z + changeZ; | |
while (result [posX, posZ] == 1) { | |
result [posX, posZ] = 2; | |
posX += changeX; | |
posZ += changeZ; | |
} | |
} | |
} | |
} | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment