Skip to content

Instantly share code, notes, and snippets.

@daleth90
Created April 29, 2018 10:17
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 daleth90/03dafe3b943ed48f9ceca5e6fb2e33e9 to your computer and use it in GitHub Desktop.
Save daleth90/03dafe3b943ed48f9ceca5e6fb2e33e9 to your computer and use it in GitHub Desktop.
almost final version
using System;
using System.Collections.Generic;
using UnityEngine;
using Zenject;
public class OthelloGame : IInitializable {
private static readonly Vector2Int[] checkDirections = new Vector2Int[] {
new Vector2Int( -1, 0 ), new Vector2Int( 1, 0 ),
new Vector2Int( 0, -1 ), new Vector2Int( 0, 1 ),
new Vector2Int( -1, -1 ), new Vector2Int( 1, 1 ),
new Vector2Int( -1, 1 ), new Vector2Int( 1, -1 )
};
public event Action<int, int> OnUpdateScore = delegate { };
public event Action<Disk> OnGameEnd = delegate { };
private readonly OthelloBoardModel othelloBoard;
private int numberOfDarkDisk;
private int numberOfLightDisk;
public OthelloGame( OthelloBoardModel othelloBoard ) {
this.othelloBoard = othelloBoard;
}
public void Initialize() {
StartNewGame();
}
public void StartNewGame() {
othelloBoard.SetSide( Disk.DARK );
othelloBoard.PlaceDisk( 4, 5 );
othelloBoard.PlaceDisk( 5, 4 );
othelloBoard.SetSide( Disk.LIGHT );
othelloBoard.PlaceDisk( 4, 4 );
othelloBoard.PlaceDisk( 5, 5 );
othelloBoard.SetSide( Disk.DARK );
UpdateScoreBoard();
othelloBoard.OnRequestDisk += ValidatePlacement;
}
public bool IsValidPlace( int x, int y, Disk disk ) {
if ( othelloBoard.GetDisk( x, y ) != Disk.NONE ) {
return false;
}
Disk oppositeSide = GetOpponentSide( disk );
for ( int d = 0; d < checkDirections.Length; d++ ) {
if ( othelloBoard.GetDisk( x + checkDirections[ d ].x, y + checkDirections[ d ].y ) != oppositeSide ) {
continue;
}
for ( int i = x + checkDirections[ d ].x * 2, j = y + checkDirections[ d ].y * 2; i >= 1 && j >= 1 && i <= 8 && j <= 8;
i += checkDirections[ d ].x, j += checkDirections[ d ].y ) {
if ( othelloBoard.GetDisk( i, j ) == disk ) {
return true;
}
}
}
return false;
}
private void ValidatePlacement( int x, int y, Disk disk ) {
Disk oppositeSide = GetOpponentSide( disk );
List<Vector2Int> flipPositions = new List<Vector2Int>();
for ( int d = 0; d < checkDirections.Length; d++ ) {
bool isValidDirection = false;
for ( int i = x + checkDirections[ d ].x, j = y + checkDirections[ d ].y; i >= 1 && j >= 1 && i <= 8 && j <= 8;
i += checkDirections[ d ].x, j += checkDirections[ d ].y ) {
if ( othelloBoard.GetDisk( i, j ) == disk ) {
isValidDirection = true;
}
}
if ( isValidDirection == false ) {
continue;
}
for ( int i = x + checkDirections[ d ].x, j = y + checkDirections[ d ].y; i >= 1 && j >= 1 && i <= 8 && j <= 8;
i += checkDirections[ d ].x, j += checkDirections[ d ].y ) {
if ( othelloBoard.GetDisk( i, j ) == oppositeSide ) {
flipPositions.Add( new Vector2Int( i, j ) );
}
else {
break;
}
}
}
if ( flipPositions.Count > 0 ) {
othelloBoard.PlaceDisk( x, y );
for ( int i = 0; i < flipPositions.Count; i++ ) {
othelloBoard.FlipDisk( flipPositions[ i ].x, flipPositions[ i ].y );
}
UpdateScoreBoard();
CheckEndOfGameOrSwitchSide( disk );
}
}
private void UpdateScoreBoard() {
numberOfDarkDisk = GetNumberOfDisk( Disk.DARK );
numberOfLightDisk = GetNumberOfDisk( Disk.LIGHT );
OnUpdateScore.Invoke( numberOfDarkDisk, numberOfLightDisk );
}
private int GetNumberOfDisk( Disk disk ) {
int number = 0;
for ( int i = 1; i <= 8; i++ ) {
for ( int j = 1; j <= 8; j++ ) {
if ( othelloBoard.GetDisk( i, j ) == disk ) {
++number;
}
}
}
return number;
}
private void CheckEndOfGameOrSwitchSide( Disk lastSide ) {
Disk oppositeSide = GetOpponentSide( lastSide );
if ( IsAvailableToPlace( oppositeSide ) ) {
othelloBoard.SetSide( oppositeSide );
}
else if ( IsAvailableToPlace( lastSide ) ) {
// The original side keeps going. Intentionally write this comment for readability
}
else {
if ( numberOfDarkDisk > numberOfLightDisk ) {
OnGameEnd.Invoke( Disk.DARK );
}
else if ( numberOfLightDisk > numberOfDarkDisk ) {
OnGameEnd.Invoke( Disk.LIGHT );
}
else { // Draw
OnGameEnd.Invoke( Disk.NONE );
}
}
}
private bool IsAvailableToPlace( Disk disk ) {
for ( int i = 1; i <= 8; i++ ) {
for ( int j = 1; j <= 8; j++ ) {
if ( IsValidPlace( i, j, disk ) ) {
return true;
}
}
}
return false;
}
private Disk GetOpponentSide( Disk disk ) {
if ( disk == Disk.DARK ) {
return Disk.LIGHT;
}
else if ( disk == Disk.LIGHT ) {
return Disk.DARK;
}
else {
throw new ArgumentException( "\"None\" disk is impossible in the game" );
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment