Skip to content

Instantly share code, notes, and snippets.

@luyao795
Created August 25, 2017 03:22
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 luyao795/1c39cf815c30024d05bea95f60925c02 to your computer and use it in GitHub Desktop.
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.
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