Board.cs (4738B)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 5 public class Board { 6 private int _n; // number of columns 7 private int _m; // number of rows 8 private Cell[,] _board; 9 private int[] _height; 10 private Cell _next; 11 private Status _status; 12 13 public enum Cell { 14 Free = 0, // make sure free is the default value 15 PlayerX, 16 PlayerO, 17 None, 18 } 19 20 public enum Status { 21 InProgress, 22 PlayerXWon, 23 PlayerOWon, 24 Draw, 25 } 26 27 /* 28 * Constructs a new board with m rows and n columns. 29 */ 30 public Board( int n, int m ) { 31 _m = m; 32 _n = n; 33 _board = new Cell[ m, n ]; 34 _height = new int[ n ]; 35 _next = Cell.PlayerX; // player X starts 36 _status = Status.InProgress; 37 } 38 39 /* 40 * Constructs a new board with the given board 41 */ 42 public Board( Board board ) { 43 _m = board._m; 44 _n = board._n; 45 _board = new Cell[ _m, _n ]; 46 _height = new int[ _n ]; 47 // why does it have to be so difficult to deep copy a 2d array? 48 for ( int j = 0; j < _m; j ++ ) { 49 for ( int i = 0; i < _n; i ++ ) { 50 _board[ j, i ] = board._board[ j, i ]; 51 } 52 } 53 board._height.CopyTo( _height, 0 ); 54 _next = board._next; 55 _status = board._status; 56 } 57 58 /* 59 * Determines if it is legal to play a piece in the given column 60 */ 61 public bool IsLegal( int column ) { 62 return _height[ column ] < _m; 63 } 64 65 /* 66 * assumes play is legal 67 */ 68 public void Play( int column ) { 69 _board[ _m - _height[ column ] - 1, column ] = _next; 70 _height[ column ] ++; 71 _next = ( _next == Cell.PlayerX ) ? Cell.PlayerO : Cell.PlayerX; 72 ComputeStatus(); 73 } 74 75 /* 76 * returns whos turn it is 77 */ 78 public Cell GetNext() { 79 return _next; 80 } 81 82 /* 83 * returns who just played 84 */ 85 public Cell GetPrevious() { 86 return _next == Cell.PlayerX ? Cell.PlayerO : Cell.PlayerX; 87 } 88 89 /* 90 * Pretty prints the board 91 */ 92 public void PrettyPrint() { 93 char[] prettyChar = { '.', 'X', 'O' }; 94 Console.WriteLine( $"{ _status }:" ); 95 for ( int j = 0; j < _m; j++ ) { 96 for ( int i = 0; i < _n; i++ ) { 97 Console.Write( $" { prettyChar[ (int) _board[ j, i ] ] } " ); 98 } 99 Console.Write( "\n" ); 100 } 101 } 102 103 /* 104 * Returns a list of all legal moves on this board 105 */ 106 public List< int > LegalMoves() { 107 List< int > legalMoves = new List< int >(); 108 if ( _status == Status.InProgress ) { 109 for ( int i = 0; i < _n; i ++ ) { 110 if ( IsLegal( i ) ) { 111 legalMoves.Add( i ); 112 } 113 } 114 } 115 return legalMoves; 116 } 117 118 public Status GetStatus() { 119 return _status; 120 } 121 122 public int GetHeight() { 123 return _m; 124 } 125 126 public int GetWidth() { 127 return _n; 128 } 129 130 /* 131 * Indexer to grant read-only access to the board 132 */ 133 public Cell this[ int j, int i ] { 134 get { 135 if ( 0 <= j && j < _m && 0 <= i && i < _n ) { 136 return _board[ j, i ]; 137 } else { 138 return Cell.None; 139 } 140 } 141 } 142 143 144 /* 145 * Computes the status of this board, ie. has someone won by obtaining four in a row. 146 */ 147 public Status ComputeStatus() { 148 int FourInARow = NumberQInRow( 4, GetPrevious() ); 149 150 if ( FourInARow > 0 ) { 151 _status = _next == Cell.PlayerO ? Status.PlayerXWon : Status.PlayerOWon; 152 } 153 return _status; 154 } 155 156 /* 157 * Returns the number of q in a row for player. 158 * Note: this also counts instance of more than q in a row. 159 */ 160 public int NumberQInRow( int q, Cell player ) { 161 var rows = Enumerable.Range( 0, _m ); 162 var columns = Enumerable.Range( 0, _n ); 163 164 var indices = new Func< int, int, int, ( int, int ) >[] { 165 ( j, i, k ) => ( j + k, i ), 166 ( j, i, k ) => ( j, i + k ), 167 ( j, i, k ) => ( j + k, i + k ), 168 ( j, i, k ) => ( j - k, i + k ), 169 }; 170 171 int count = 172 ( from index in indices 173 from j in rows 174 from i in columns 175 select Enumerable.All( 176 Enumerable.Range( 0, q ), 177 k => { 178 var ( jj, ii ) = index( j, i, k ); 179 return this[ jj, ii ] == player; 180 } 181 ) 182 ).Where( b => b ) 183 .Count(); 184 return count; 185 } 186 }