diff --git a/module1/projects/connect_four/iteration_1.md b/module1/projects/connect_four/iteration_1.md index 03e890a6c..b28186a8e 100644 --- a/module1/projects/connect_four/iteration_1.md +++ b/module1/projects/connect_four/iteration_1.md @@ -1,6 +1,6 @@ --- layout: page -title: Iteration 1 - Game Board +title: Iteration 1 - Cell and Board Render --- _[Back to Connect Four Home](./index)_ @@ -10,30 +10,116 @@ _[Back to Requirements](./requirements)_ In this iteration, you are required to use TDD to create your classes. Use the interaction pattern to determine what a method should do and write one or more tests to verify that expected behavior. Then you can implement the method. You should always write code with the purpose of making a test pass. -## Printing the Board +## Cell -When a user runs the command to start the game, they will see a welcome message, followed by an empty board. The board itself will represent empty spaces with periods and column names with a letter A-G. +A Cell object represents the space where a chip could be placed on the Connect 4 board. We will be able to read its column letter and row number, as well as its display value. It will also have behavior to fill in the cell with a new value. -``` -ABCDEFG -....... -....... -....... -....... -....... -....... +The Cell class should follow this interaction pattern: + +```ruby +pry(main)> require './lib/cell' +# => true +pry(main)> a1 = Cell.new("A1") +# => # +pry(main)> b3 = Cell.new("B3") +# => # +pry(main)> a1.placement +# => "A1" +pry(main)> a1.column +# => "A" +pry(main)> a1.row +# => 1 +pry(main)> a1.value +# => "." +pry(main)> a1.filled? +# => false +pry(main)> a1.fill("X") +# => "X" +pry(main)> a1.value +# => "X" +pry(main)> a1.filled? +# => true +pry(main)> b3.fill("O") +# => "O" +pry(main)> b3.value +# => "O" +pry(main)> b3.filled? +# => true ``` -Player pieces will be represented by X's, while computer pieces will be represented by O's. A board later in the game might look something like the following: +## Board -``` -ABCDEFG -....... -....... -O...... -X.O...O -XXOX..X -XOOXOOX -``` +The Board class is responsible for keeping track of each cell on the board and validating 4 in a row. -For Iteration 1, students should have a program that will print out a welcome message and an empty board. +Follow the interaction pattern below to build out the board's display: + +### Board Display + +```ruby +pry(main)> require './lib/cell' +# => true +pry(main)> require './lib/board' +# => true +pry(main)> a_cells = [Cell.new("A1"),Cell.new("A2"),Cell.new("A3"),Cell.new("A4"),Cell.new("A5"),Cell.new("A6")] +pry(main)> b_cells = [Cell.new("B1"),Cell.new("B2"),Cell.new("B3"),Cell.new("B4"),Cell.new("B5"),Cell.new("B6")] +pry(main)> c_cells = [Cell.new("C1"),Cell.new("C2"),Cell.new("C3"),Cell.new("C4"),Cell.new("C5"),Cell.new("C6")] +pry(main)> d_cells = [Cell.new("D1"),Cell.new("D2"),Cell.new("D3"),Cell.new("D4"),Cell.new("D5"),Cell.new("D6")] +pry(main)> e_cells = [Cell.new("E1"),Cell.new("E2"),Cell.new("E3"),Cell.new("E4"),Cell.new("E5"),Cell.new("E6")] +pry(main)> f_cells = [Cell.new("F1"),Cell.new("F2"),Cell.new("F3"),Cell.new("F4"),Cell.new("F5"),Cell.new("F6")] +pry(main)> g_cells = [Cell.new("G1"),Cell.new("G2"),Cell.new("G3"),Cell.new("G4"),Cell.new("G5"),Cell.new("G6")] +pry(main)> columns = {A: a_cells, B: b_cells, C: c_cells, D: d_cells, E: e_cells, F: f_cells, G: g_cells} +pry(main)> board = Board.new(columns) +# => # +pry(main)> board.columns +# => {:A=> + [#, + #, + #, + #, + #, + #], + :B=> + [#, + #, + #, + #, + #, + #], + :C=> + [#, + #, + #, + #, + #, + #], + :D=> + [#, + #, + #, + #, + #, + #], + :E=> + [#, + #, + #, + #, + #, + #], + :F=> + [#, + #, + #, + #, + #, + #], + :G=> + [#, + #, + #, + #, + #, + #]} +pry(main)> board.render_board +# => "A B C D E F G\n. . . . . . .\n. . . . . . .\n. . . . . . .\n. . . . . . .\n. . . . . . .\n. . . . . . ." +``` diff --git a/module1/projects/connect_four/iteration_2.md b/module1/projects/connect_four/iteration_2.md index 710ddd652..cdc4ad624 100644 --- a/module1/projects/connect_four/iteration_2.md +++ b/module1/projects/connect_four/iteration_2.md @@ -1,6 +1,6 @@ --- layout: page -title: Iteration 2 - Placing Pieces +title: Iteration 2 - Placing Chips and Validating Four Across --- _[Back to Connect Four Home](./index)_ @@ -10,24 +10,148 @@ _[Back to Requirements](./requirements)_ In this iteration, you are required to use TDD to create your classes. Use the interaction pattern to determine what a method should do and write one or more tests to verify that expected behavior. Then you can implement the method. You should always write code with the purpose of making a test pass. -## Placing Pieces +## Board -Update your program to request user input and allow them to place an individual piece. +The Board class is responsible for keeping track of each cell on the board and validating 4 in a row. -Your program should ask the user to enter a letter A-G. -Update the board to display the player's piece in the lowest available position of the selected column with an 'X'. +Follow the interaction pattern below to build out the functionality for placing a chip on the board: -The computer takes its turn by selecting one of the 7 columns at random. Update the board to display the computer's piece in the lowest available position of the selected column with an 'O'. -The player and computer should be able to repeat this sequence and continue taking turns. +### Place Chip On Board -### Invalid Column Selection +```ruby +pry(main)> require './lib/cell' +# => true +pry(main)> require './lib/board' +# => true +pry(main)> a_cells = [Cell.new("A1"),Cell.new("A2"),Cell.new("A3"),Cell.new("A4"),Cell.new("A5"),Cell.new("A6")] +pry(main)> b_cells = [Cell.new("B1"),Cell.new("B2"),Cell.new("B3"),Cell.new("B4"),Cell.new("B5"),Cell.new("B6")] +pry(main)> c_cells = [Cell.new("C1"),Cell.new("C2"),Cell.new("C3"),Cell.new("C4"),Cell.new("C5"),Cell.new("C6")] +pry(main)> d_cells = [Cell.new("D1"),Cell.new("D2"),Cell.new("D3"),Cell.new("D4"),Cell.new("D5"),Cell.new("D6")] +pry(main)> e_cells = [Cell.new("E1"),Cell.new("E2"),Cell.new("E3"),Cell.new("E4"),Cell.new("E5"),Cell.new("E6")] +pry(main)> f_cells = [Cell.new("F1"),Cell.new("F2"),Cell.new("F3"),Cell.new("F4"),Cell.new("F5"),Cell.new("F6")] +pry(main)> g_cells = [Cell.new("G1"),Cell.new("G2"),Cell.new("G3"),Cell.new("G4"),Cell.new("G5"),Cell.new("G6")] +pry(main)> columns = {A: a_cells, B: b_cells, C: c_cells, D: d_cells, E: e_cells, F: f_cells, G: g_cells} +pry(main)> board = Board.new(columns) +pry(main)> board.place_chip("A", "X") +pry(main)> board.render_board +# => "A B C D E F G\n. . . . . . .\n. . . . . . .\n. . . . . . .\n. . . . . . .\n. . . . . . .\nX . . . . . ." +pry(main)> board.place_chip("A", "O") +pry(main)> board.render_board +# => "A B C D E F G\n. . . . . . .\n. . . . . . .\n. . . . . . .\n. . . . . . .\nO . . . . . .\nX . . . . . ." +pry(main)> board.place_chip("D", "X") +pry(main)> board.render_board +# => "A B C D E F G\n. . . . . . .\n. . . . . . .\n. . . . . . .\n. . . . . . .\nO . . . . . .\nX . . X . . ." +pry(main)> board.place_chip("C", "O") +pry(main)> board.render_board +# => "A B C D E F G\n. . . . . . .\n. . . . . . .\n. . . . . . .\n. . . . . . .\nO . . . . . .\nX . O X . . ." -Neither the player nor computer should be able to play in an invalid column. An invalid column is defined as one of the following: -1. Outside the range A-G -1. Full, i.e. there is no available position in the column +``` -If an invalid column is selected by the player, the program should display an error message and ask the player to select a valid column. The program should repeat this process until a valid column is selected. -* The one exception is when there are no valid columns available; i.e. the game board is full. In this case, the game is a draw, an endgame condition. -If an invalid column is selected by the computer, the program should repeat until a valid column is selected. No error message should display to the user when the computer selects an invalid column. +### Validate 4 Across + +```ruby +pry(main)> require './lib/cell' +# => true +pry(main)> require './lib/board' +# => true +pry(main)> a_cells = [Cell.new("A1"),Cell.new("A2"),Cell.new("A3"),Cell.new("A4"),Cell.new("A5"),Cell.new("A6")] +pry(main)> b_cells = [Cell.new("B1"),Cell.new("B2"),Cell.new("B3"),Cell.new("B4"),Cell.new("B5"),Cell.new("B6")] +pry(main)> c_cells = [Cell.new("C1"),Cell.new("C2"),Cell.new("C3"),Cell.new("C4"),Cell.new("C5"),Cell.new("C6")] +pry(main)> d_cells = [Cell.new("D1"),Cell.new("D2"),Cell.new("D3"),Cell.new("D4"),Cell.new("D5"),Cell.new("D6")] +pry(main)> e_cells = [Cell.new("E1"),Cell.new("E2"),Cell.new("E3"),Cell.new("E4"),Cell.new("E5"),Cell.new("E6")] +pry(main)> f_cells = [Cell.new("F1"),Cell.new("F2"),Cell.new("F3"),Cell.new("F4"),Cell.new("F5"),Cell.new("F6")] +pry(main)> g_cells = [Cell.new("G1"),Cell.new("G2"),Cell.new("G3"),Cell.new("G4"),Cell.new("G5"),Cell.new("G6")] +pry(main)> columns = {A: a_cells, B: b_cells, C: c_cells, D: d_cells, E: e_cells, F: f_cells, G: g_cells} +pry(main)> board = Board.new(columns) +pry(main)> c3 = board.columns[:C][2] +pry(main)> e2 = board.columns[:E][1] +pry(main)> board.row_for(c3) +# => [#, + #, + #, + #, + #, + #, + #] +pry(main)> board.row_for(e2) +# => [#, + #, + #, + #, + #, + #, + #] +pry(main)> board.column_for(c3) +# => [#, + #, + #, + #, + #, + #] +pry(main)> board.column_for(e2) +# => [#, + #, + #, + #, + #, + #] +pry(main)> board.diagonal_for(c3) +# => [#, + #, + #, + #, + #, + #] +pry(main)> board.diagonal_for(e2) +# => [#, + #, + #, + #] + + +# Check for connect 4 in a column: +pry(main)> a1 = board.columns[:A][0] +pry(main)> a2 = board.columns[:A][1] +pry(main)> a3 = board.columns[:A][2] +pry(main)> a4 = board.columns[:A][3] +pry(main)> column_a = board.column_for(a1) # we could have also used any cell from column A here. +pry(main)> a1.fill("X") +pry(main)> a2.fill("X") +pry(main)> a3.fill("X") +pry(main)> board.check_for_four(column_a) +# => false +pry(main)> a4.fill("X") +pry(main)> board.check_for_four(column_a) +# => true + +# Check for connect 4 in a row: +pry(main)> b1 = board.columns[:B][0] +pry(main)> c1 = board.columns[:C][0] +pry(main)> d1 = board.columns[:D][0] +pry(main)> e1 = board.columns[:E][0] +pry(main)> b1.fill("O") +pry(main)> c1.fill("O") +pry(main)> d1.fill("O") +pry(main)> row_1 = board.row_for(e1) # we could have also used any cell from row 1 here. +pry(main)> board.check_for_four(row_1) +# => false +pry(main)> e1.fill("O") +pry(main)> board.check_for_four(row_1) +# => true + +# Check for connect 4 in a diagonal: +pry(main)> b2 = board.columns[:B][1] +pry(main)> c3 = board.columns[:C][2] +pry(main)> d4 = board.columns[:D][3] +pry(main)> b2.fill("X") +pry(main)> c3.fill("X") +pry(main)> diagonal = board.diagonal_for(d4) # we could have also used any cell that would have been on this diagonal. +pry(main)> board.check_for_four(diagonal) +# => false +pry(main)> d4.fill("X") +pry(main)> board.check_for_four(diagonal) #note: a1 was already filled in with "X" earlier in this interaction pattern +# => true +``` + diff --git a/module1/projects/connect_four/iteration_3.md b/module1/projects/connect_four/iteration_3.md index 66b113d42..4e3750be6 100644 --- a/module1/projects/connect_four/iteration_3.md +++ b/module1/projects/connect_four/iteration_3.md @@ -6,7 +6,7 @@ title: Iteration 3 - Playing the Game _[Back to Connect Four Home](./index)_ _[Back to Requirements](./requirements)_ -Now it's time to put together the components you've built in the last two iterations to make a working game. You are allowed to build any additional classes or methods you think may be useful to accomplish this. However, this project will be assessed on the spec outlined in the last two iterations, so don't remove any of the functionality from previously built classes. +Now it's time to put together the components you've built in the last two iterations to make a working game. You are allowed to build any additional classes or methods you think may be useful to accomplish this. You might also run into instances where it would make sense to refactor some methods that you already built in the first two iterations. You are not expected to test anything related to user input and output in this iteration, but try to use TDD as much as possible to help you design your solution. @@ -29,7 +29,18 @@ Once the User has chosen to play, display a new game board and ask the player to ### Placing Pieces -The player starts the game by placing their first piece in a valid column. The computer then places their first piece in a randomly selected valid column. The player and computer should repeat this sequence and continue taking turns until an endgame condition is met. +Your program will request user input and allow them to place an individual piece. + +Your program should ask the user to enter a letter A-G. +Update the board to display the player's piece in the lowest available position of the selected column with an 'X'. + +The computer takes its turn by selecting one of the 7 columns at random. Update the board to display the computer's piece in the lowest available position of the selected column with an 'O'. + +The player and computer should be able to repeat this sequence and continue taking turns. + +If an invalid column is selected by the player, the program should display an error message and ask the player to select a valid column. The program should repeat this process until a valid column is selected. + +If an invalid column is selected by the computer, the program should repeat until a valid column is selected. No error message should display to the user when the computer selects an invalid column. ### End of Game @@ -75,3 +86,4 @@ This checklist summarizes all of the functionality you are expected to build. Th * The player cannot select a valid column. * The program reports the appropriate endgame status * Game returns user back to the Main Menu +