Created
December 12, 2025 17:09
-
-
Save constructor-s/cad23e715e8b7e223801a4c99139fed5 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Gomoku Project - Complete Test Suite</title> | |
| <style> | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | |
| line-height: 1.6; | |
| color: #333; | |
| max-width: 1000px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| background-color: #f9f9f9; | |
| } | |
| header { | |
| border-bottom: 2px solid #0056b3; | |
| margin-bottom: 30px; | |
| padding-bottom: 10px; | |
| } | |
| h1 { | |
| color: #0056b3; | |
| margin-bottom: 5px; | |
| } | |
| .instructions { | |
| background-color: #e9ecef; | |
| padding: 15px; | |
| border-radius: 5px; | |
| margin-bottom: 25px; | |
| border-left: 5px solid #0056b3; | |
| } | |
| details { | |
| background-color: #fff; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| margin-bottom: 15px; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.05); | |
| overflow: hidden; | |
| } | |
| summary { | |
| padding: 15px; | |
| background-color: #f1f3f5; | |
| cursor: pointer; | |
| font-weight: bold; | |
| font-family: monospace; | |
| font-size: 1.1em; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| summary:hover { | |
| background-color: #e2e6ea; | |
| } | |
| .code-wrapper { | |
| position: relative; | |
| background-color: #282c34; | |
| } | |
| pre { | |
| margin: 0; | |
| padding: 20px; | |
| overflow-x: auto; | |
| color: #abb2bf; | |
| font-family: 'Consolas', 'Monaco', 'Andale Mono', monospace; | |
| font-size: 14px; | |
| line-height: 1.5; | |
| } | |
| .copy-btn { | |
| position: absolute; | |
| top: 10px; | |
| right: 10px; | |
| background-color: rgba(255, 255, 255, 0.1); | |
| color: #fff; | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| border-radius: 4px; | |
| padding: 5px 10px; | |
| font-size: 12px; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| } | |
| .copy-btn:hover { | |
| background-color: rgba(255, 255, 255, 0.2); | |
| } | |
| .test-description { | |
| padding: 15px 20px 0 20px; | |
| font-style: italic; | |
| color: #666; | |
| font-size: 0.9em; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <h1>Gomoku Project Test Suite</h1> | |
| <p>ESC 180 - Fall 2025</p> | |
| </header> | |
| <div class="instructions"> | |
| <strong>How to use these tests:</strong> | |
| <ol> | |
| <li>Expand a test file section below.</li> | |
| <li>Click the "Copy" button.</li> | |
| <li>Create a new file in your project folder (where <code>gomoku.py</code> is located, so it can be imported) with the filename shown in the header (e.g., <code>test_detect_row_student.py</code>).</li> | |
| <li>Paste the code and save.</li> | |
| <li>Run the file using Pyzo or the command line (e.g., <code>python3 test_detect_row_student.py</code>).</li> | |
| </ol> | |
| </div> | |
| <!-- TEST 1: detect_row --> | |
| <details> | |
| <summary>test_detect_row_student.py</summary> | |
| <div class="test-description"> | |
| Tests for the <code>detect_row</code> function. Covers basic open sequences, bound sequences, semi-open sequences, and edge cases. | |
| </div> | |
| <div class="code-wrapper"> | |
| <button class="copy-btn" onclick="copyCode(this)">Copy</button> | |
| <pre><code>""" | |
| TestDetectRow Student Test Suite | |
| Test Cases: | |
| 1. test_len2_unbound_x | |
| 2. test_len2_unbound_y_white | |
| 3. test_len2_unbound_y | |
| 4. test_len3_unbound_y_constrained | |
| 5. test_len4_unbound_d_constrained | |
| 6. test_len2_unbound_rd | |
| 7. test_len2_bound_y | |
| 8. test_len2_bound_x | |
| 9. test_len3_bound_x_boarder | |
| 10. test_len4_bound_d_boarder | |
| 11. test_len4_bound_d_boarder_lower_right_white | |
| 12. test_len2_bound_rd | |
| 13. test_len3_bound_rd_boundry | |
| 14. test_len2_semi_y | |
| 15. test_len2_semi_rd | |
| 16. test_len2_semi_x | |
| 17. test_len3_semi_x_boarder | |
| 18. test_len4_semi_d_boarder | |
| 19. test_len4_semi_d_boarder_lower_right_white | |
| """ | |
| import gomoku | |
| def test_len2_unbound_x(): | |
| """Test Case 1: Length 2 open sequence in x direction (black)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',1, 0, 2, 0, 1) | |
| expected = (1,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_unbound_x PASSED") | |
| def test_len2_unbound_y_white(): | |
| """Test Case 2: Length 2 open sequence in y direction (white)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'w',0, 4, 2, 1, 0) | |
| expected = (1,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_unbound_y_white PASSED") | |
| def test_len2_unbound_y(): | |
| """Test Case 3: Length 2 open sequence in y direction (black)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ','b',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 1, 2, 1, 0) | |
| expected = (1,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_unbound_y PASSED") | |
| def test_len3_unbound_y_constrained(): | |
| """Test Case 4: Length 3 open sequence in y direction with surrounding stones""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ','b','b','b',' ',' ',' '], | |
| [' ',' ','b','b','w','w','w',' '], | |
| [' ',' ','b','w','b',' ',' ',' '], | |
| [' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ','w',' '], | |
| [' ',' ',' ',' ',' ',' ','w',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 2, 3, 1, 0) | |
| expected = (1,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len3_unbound_y_constrained PASSED") | |
| def test_len4_unbound_d_constrained(): | |
| """Test Case 5: Length 4 open sequence in diagonal (1,1) direction""" | |
| board = [[' ','w',' ',' ',' ',' ',' ',' '], | |
| ['w','b','b',' ','w',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ',' ',' ','b','w',' ',' ',' '], | |
| ['b',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 0, 4, 1, 1) | |
| expected = (1,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len4_unbound_d_constrained PASSED") | |
| def test_len2_unbound_rd(): | |
| """Test Case 6: Length 2 open sequence in reverse diagonal (1,-1) direction""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ','b','w',' ',' ',' ',' '], | |
| [' ','b','w','b',' ',' ',' ',' '], | |
| [' ','w',' ',' ',' ',' ',' ',' '], | |
| ['w','b',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 3, 2, 1, -1) | |
| expected = (1,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_unbound_rd PASSED") | |
| def test_len2_bound_y(): | |
| """Test Case 7: Length 2 closed sequence in y direction""" | |
| board = [[' ','w',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| ['b','b',' ',' ',' ',' ',' ',' '], | |
| [' ','w',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 1, 2, 1, 0) | |
| expected = (0,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_bound_y PASSED") | |
| def test_len2_bound_x(): | |
| """Test Case 8: Length 2 closed sequence in x direction""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| ['w','b','b','w',' ',' ',' ',' '], | |
| [' ','b',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',1, 0, 2, 0, 1) | |
| expected = (0,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_bound_x PASSED") | |
| def test_len3_bound_x_boarder(): | |
| """Test Case 9: Length 3 closed sequence in x direction (border)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| ['b','b','b','w',' ',' ',' ',' '], | |
| ['w','b',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',1, 0, 3, 0, 1) | |
| expected = (0,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len3_bound_x_boarder PASSED") | |
| def test_len4_bound_d_boarder(): | |
| """Test Case 10: Length 4 closed sequence in diagonal direction (border)""" | |
| board = [['b','b','b','b',' ',' ',' ',' '], | |
| ['w','b','b',' ','w',' ',' ',' '], | |
| [' ',' ','b',' ',' ',' ',' ',' '], | |
| [' ',' ',' ','b',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ','w',' ',' '], | |
| [' ',' ',' ',' ',' ',' ','w',' '], | |
| ['w','w','w',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 0, 4, 1, 1) | |
| expected = (0,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len4_bound_d_boarder PASSED") | |
| def test_len4_bound_d_boarder_lower_right_white(): | |
| """Test Case 11: Length 4 closed sequence in diagonal direction (black stones)""" | |
| board = [['b',' ','b','b',' ','b',' ',' '], | |
| [' ',' ',' ','b','b',' ',' ',' '], | |
| [' ','b',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ','b',' ','b',' ',' '], | |
| [' ','b','b',' ','w','w','w','w'], | |
| [' ',' ',' ','b','w','w',' ',' '], | |
| [' ',' ',' ','b','w',' ','w',' '], | |
| ['w','w','b','w','w',' ',' ','w']] | |
| result = gomoku.detect_row(board,'b',0, 0, 4, 1, 1) | |
| expected = (0,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len4_bound_d_boarder_lower_right_white PASSED") | |
| def test_len2_bound_rd(): | |
| """Test Case 12: Length 2 closed sequence in reverse diagonal direction""" | |
| board = [[' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| [' ','b','w',' ',' ',' ',' ',' '], | |
| ['w','w',' ',' ',' ',' ',' ',' '], | |
| [' ','b',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 3, 2, 1, -1) | |
| expected = (0,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_bound_rd PASSED") | |
| def test_len3_bound_rd_boundry(): | |
| """Test Case 13: Length 3 closed sequence in reverse diagonal direction (boundary)""" | |
| board = [[' ',' ',' ','b','w',' ',' ',' '], | |
| [' ',' ','b',' ','b',' ',' ',' '], | |
| [' ','b','w',' ',' ',' ',' ',' '], | |
| ['w','w',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 3, 3, 1, -1) | |
| expected = (0,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len3_bound_rd_boundry PASSED") | |
| def test_len2_semi_y(): | |
| """Test Case 14: Length 2 semi-open sequence in y direction""" | |
| board = [[' ','w',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| ['b','b','w',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 1, 2, 1, 0) | |
| expected = (0,1) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_semi_y PASSED") | |
| def test_len2_semi_rd(): | |
| """Test Case 15: Length 2 semi-open sequence in reverse diagonal direction""" | |
| board = [[' ','w',' ',' ',' ',' ',' ',' '], | |
| [' ',' ','b','b',' ',' ',' ',' '], | |
| [' ','b','w',' ',' ',' ',' ',' '], | |
| ['w','w',' ',' ',' ',' ',' ',' '], | |
| [' ','b',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 3, 2, 1, -1) | |
| expected = (0,1) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_semi_rd PASSED") | |
| def test_len2_semi_x(): | |
| """Test Case 16: Length 2 semi-open sequence in x direction""" | |
| board = [[' ',' ','b',' ',' ',' ',' ',' '], | |
| ['w','b','b',' ',' ',' ',' ',' '], | |
| [' ',' ','w',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',1, 0, 2, 0, 1) | |
| expected = (0,1) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_semi_x PASSED") | |
| def test_len3_semi_x_boarder(): | |
| """Test Case 17: Length 3 semi-open sequence in x direction (border)""" | |
| board = [['b',' ','b',' ',' ',' ',' ',' '], | |
| ['w','b','b','w','w',' ',' ',' '], | |
| ['b','b','b',' ',' ',' ',' ',' '], | |
| [' ',' ','w','w','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',2, 0, 3, 0, 1) | |
| expected = (0,1) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len3_semi_x_boarder PASSED") | |
| def test_len4_semi_d_boarder(): | |
| """Test Case 18: Length 4 semi-open sequence in diagonal direction (border)""" | |
| board = [['b',' ',' ','b',' ',' ',' ',' '], | |
| ['w','b','b','b','w',' ',' ',' '], | |
| [' ',' ','b','b',' ',' ',' ',' '], | |
| ['b','b','b','b','w',' ',' ',' '], | |
| [' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ','w',' ','w',' ',' '], | |
| [' ',' ',' ','w',' ',' ','w',' '], | |
| ['w','w','w','w',' ',' ',' ',' ']] | |
| result = gomoku.detect_row(board,'b',0, 0, 4, 1, 1) | |
| expected = (0,1) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len4_semi_d_boarder PASSED") | |
| def test_len4_semi_d_boarder_lower_right_white(): | |
| """Test Case 19: Length 4 semi-open sequence in diagonal direction (white stones)""" | |
| board = [['b',' ','b','b',' ',' ',' ',' '], | |
| [' ',' ',' ','b','b',' ',' ',' '], | |
| [' ',' ',' ','b',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','b',' ',' ',' '], | |
| [' ',' ',' ','b','w','w','w','w'], | |
| [' ',' ',' ','b','w','w',' ',' '], | |
| [' ',' ',' ','b','w',' ','w',' '], | |
| ['w','w','b','b','w',' ',' ','w']] | |
| result = gomoku.detect_row(board,'w',0, 0, 4, 1, 1) | |
| expected = (0,1) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len4_semi_d_boarder_lower_right_white PASSED") | |
| if __name__ == '__main__': | |
| test_len2_unbound_x() | |
| test_len2_unbound_y_white() | |
| test_len2_unbound_y() | |
| test_len3_unbound_y_constrained() | |
| test_len4_unbound_d_constrained() | |
| test_len2_unbound_rd() | |
| test_len2_bound_y() | |
| test_len2_bound_x() | |
| test_len3_bound_x_boarder() | |
| test_len4_bound_d_boarder() | |
| test_len4_bound_d_boarder_lower_right_white() | |
| test_len2_bound_rd() | |
| test_len3_bound_rd_boundry() | |
| test_len2_semi_y() | |
| test_len2_semi_rd() | |
| test_len2_semi_x() | |
| test_len3_semi_x_boarder() | |
| test_len4_semi_d_boarder() | |
| test_len4_semi_d_boarder_lower_right_white() | |
| print("All tests passed for test_detect_row_student.py!") | |
| </code></pre> | |
| </div> | |
| </details> | |
| <!-- TEST 2: detect_rows --> | |
| <details> | |
| <summary>test_detect_rows_student.py</summary> | |
| <div class="test-description"> | |
| Tests for the <code>detect_rows</code> function. Checks aggregation of rows across the whole board. | |
| </div> | |
| <div class="code-wrapper"> | |
| <button class="copy-btn" onclick="copyCode(this)">Copy</button> | |
| <pre><code>""" | |
| TestDetectRows Student Test Suite | |
| Test Cases: | |
| 1. test_len2_single_unbound_x | |
| 2. test_len2_multiple1_unbound_x | |
| 3. test_len2_multiple2_unbound_x | |
| 4. test_len2_single_unbound_y_white | |
| 5. test_len2_unbound_multi_dir2 | |
| 6. test_unbound_y_include_bound | |
| 7. test_unbound_multi_dir_include_bound | |
| 8. test_len2_unbound_d_include_semi | |
| 9. test_len2_board_boundry | |
| 10. test_len2_only_semi_board_boundry_bouind | |
| 11. test_len2_only_semi | |
| """ | |
| import gomoku | |
| def test_len2_single_unbound_x(): | |
| """Test Case 1: Single length 2 open sequence in x direction""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'b', 2) | |
| expected = (1,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_single_unbound_x PASSED") | |
| def test_len2_multiple1_unbound_x(): | |
| """Test Case 2: Multiple sequences, count only specific length (2)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w','w','w',' '], | |
| [' ',' ',' ',' ','w','w','w',' '], | |
| [' ','b','b','b',' ','w','w',' '], | |
| [' ',' ',' ',' ',' ',' ','w',' '], | |
| [' ','b','b','b','b',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'b', 2) | |
| expected = (1,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_multiple1_unbound_x PASSED") | |
| def test_len2_multiple2_unbound_x(): | |
| """Test Case 3: Multiple length 2 open sequences""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w','w','w',' '], | |
| [' ',' ',' ',' ','w','w','w',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'b', 2) | |
| expected = (3,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_multiple2_unbound_x PASSED") | |
| def test_len2_single_unbound_y_white(): | |
| """Test Case 4: Single length 2 open sequence in y direction (white)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'w', 2) | |
| expected = (1,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_single_unbound_y_white PASSED") | |
| def test_len2_unbound_multi_dir2(): | |
| """Test Case 5: Length 2 open sequences in multiple directions""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ','b',' ',' ','w',' ',' ',' '], | |
| [' ',' ','b',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'b', 2) | |
| expected = (4,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_unbound_multi_dir2 PASSED") | |
| def test_unbound_y_include_bound(): | |
| """Test Case 6: Open sequences vs closed sequences (y direction)""" | |
| board = [[' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ','b',' ','b','w',' ',' ',' '], | |
| [' ','b',' ','b','w',' ',' ',' '], | |
| [' ','b',' ','b','w',' ',' ',' '], | |
| [' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'b', 3) | |
| expected = (1,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_unbound_y_include_bound PASSED") | |
| def test_unbound_multi_dir_include_bound(): | |
| """Test Case 7: Open sequences vs closed sequences (multiple directions)""" | |
| board = [[' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ','w','b','b','b','w',' ',' '], | |
| [' ',' ','b','b','w','w','w',' '], | |
| [' ',' ','b','b','b',' ',' ',' '], | |
| [' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'b', 3) | |
| expected = (4,0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_unbound_multi_dir_include_bound PASSED") | |
| def test_len2_unbound_d_include_semi(): | |
| """Test Case 8: Open and semi-open sequences (diagonal)""" | |
| board = [[' ','w',' ',' ',' ',' ',' ',' '], | |
| ['w','b','b',' ','w',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ',' ',' ','b','w',' ',' ',' '], | |
| ['b',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'b', 2) | |
| expected = (3,2) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_unbound_d_include_semi PASSED") | |
| def test_len2_board_boundry(): | |
| """Test Case 9: Open and semi-open sequences at board boundary""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ','b','w',' ',' ',' ',' '], | |
| ['b','b','w',' ',' ',' ',' ',' '], | |
| [' ','w','w',' ','w',' ',' ',' '], | |
| ['b','b',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'b',2) | |
| expected = (1,1) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_board_boundry PASSED") | |
| def test_len2_only_semi_board_boundry_bouind(): | |
| """Test Case 10: Only semi-open sequences (blocked by stones and boundary)""" | |
| board = [[' ','w','w','w','b',' ',' ',' '], | |
| ['w','b','b',' ',' ',' ',' ',' '], | |
| ['b','b',' ',' ',' ',' ',' ',' '], | |
| [' ','w',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'b', 2) | |
| expected = (0,3) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_only_semi_board_boundry_bouind PASSED") | |
| def test_len2_only_semi(): | |
| """Test Case 11: Only semi-open sequences""" | |
| board = [[' ','w',' ','w',' ',' ',' ',' '], | |
| [' ','b','b','w',' ',' ',' ',' '], | |
| [' ','b',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.detect_rows(board,'b', 2) | |
| expected = (0,3) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_only_semi PASSED") | |
| if __name__ == '__main__': | |
| test_len2_single_unbound_x() | |
| test_len2_multiple1_unbound_x() | |
| test_len2_multiple2_unbound_x() | |
| test_len2_single_unbound_y_white() | |
| test_len2_unbound_multi_dir2() | |
| test_unbound_y_include_bound() | |
| test_unbound_multi_dir_include_bound() | |
| test_len2_unbound_d_include_semi() | |
| test_len2_board_boundry() | |
| test_len2_only_semi_board_boundry_bouind() | |
| test_len2_only_semi() | |
| print("All tests passed for test_detect_rows_student.py!") | |
| </code></pre> | |
| </div> | |
| </details> | |
| <!-- TEST 3: hidden --> | |
| <details> | |
| <summary>test_hidden_student.py</summary> | |
| <div class="test-description"> | |
| Comprehensive tests covering complex board states and edge cases previously used as hidden grading tests. | |
| </div> | |
| <div class="code-wrapper"> | |
| <button class="copy-btn" onclick="copyCode(this)">Copy</button> | |
| <pre><code>""" | |
| TestHidden Student Test Suite | |
| This file contains additional comprehensive test cases that verify: | |
| 1. detect_rows on complex board states for specific lengths. | |
| 2. search_max logic on specific board configurations. | |
| Test Cases: | |
| 1. test_detect_rows_complex_1_black | |
| 2. test_detect_rows_complex_1_white | |
| 3. test_detect_rows_complex_2_black | |
| 4. test_detect_rows_complex_2_white | |
| 5. test_detect_rows_complex_3_black | |
| 6. test_detect_rows_complex_3_white | |
| 7. test_search_max_complex_1 | |
| 8. test_search_max_complex_2 | |
| """ | |
| import gomoku | |
| def test_detect_rows_complex_1_black(): | |
| """Test Case 1: Complex board 1, Player Black""" | |
| board = [[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', 'w', ' ', ' ', 'b', ' ', ' '], | |
| [' ', ' ', ' ', 'w', 'b', ' ', ' ', ' '], | |
| [' ', ' ', ' ', 'b', ' ', ' ', ' ', ' '], | |
| [' ', ' ', 'w', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']] | |
| player = 'b' | |
| expected = { | |
| 2 : (0, 0) , | |
| 3 : (0, 1) , | |
| 4 : (0, 0) , | |
| 5 : (0, 0) , | |
| } | |
| print("\nRunning test_detect_rows_complex_1_black...") | |
| gomoku.print_board(board) | |
| for length, exp_val in expected.items(): | |
| result = gomoku.detect_rows(board, player, length) | |
| assert result == exp_val, f"Length {length}: Expected {exp_val}, got {result}" | |
| print("PASSED") | |
| def test_detect_rows_complex_1_white(): | |
| """Test Case 2: Complex board 1, Player White""" | |
| board = [[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', 'w', ' ', ' ', 'b', ' ', ' '], | |
| [' ', ' ', ' ', 'w', 'b', ' ', ' ', ' '], | |
| [' ', ' ', ' ', 'b', ' ', ' ', ' ', ' '], | |
| [' ', ' ', 'w', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']] | |
| player = 'w' | |
| expected = { | |
| 2 : (1, 0) , | |
| 3 : (0, 0) , | |
| 4 : (0, 0) , | |
| 5 : (0, 0) , | |
| } | |
| print("\nRunning test_detect_rows_complex_1_white...") | |
| # Board is same as above, skipping print to reduce noise | |
| for length, exp_val in expected.items(): | |
| result = gomoku.detect_rows(board, player, length) | |
| assert result == exp_val, f"Length {length}: Expected {exp_val}, got {result}" | |
| print("PASSED") | |
| def test_detect_rows_complex_2_black(): | |
| """Test Case 3: Complex board 2, Player Black""" | |
| board = [['w', 'b', ' ', ' ', ' ', ' ', 'w', ' '], | |
| ['w', ' ', ' ', 'w', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', ' ', ' ', ' ', 'b', 'w'], | |
| [' ', ' ', ' ', ' ', ' ', ' ', ' ', 'b'], | |
| ['b', ' ', 'b', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', ' ', 'b', ' ', 'w', ' '], | |
| ['b', ' ', ' ', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', 'w', 'w', ' ', ' ', ' ']] | |
| player = 'b' | |
| expected = { | |
| 2 : (0, 1) , | |
| 3 : (0, 0) , | |
| 4 : (0, 0) , | |
| 5 : (0, 0) , | |
| } | |
| print("\nRunning test_detect_rows_complex_2_black...") | |
| gomoku.print_board(board) | |
| for length, exp_val in expected.items(): | |
| result = gomoku.detect_rows(board, player, length) | |
| assert result == exp_val, f"Length {length}: Expected {exp_val}, got {result}" | |
| print("PASSED") | |
| def test_detect_rows_complex_2_white(): | |
| """Test Case 4: Complex board 2, Player White""" | |
| board = [['w', 'b', ' ', ' ', ' ', ' ', 'w', ' '], | |
| ['w', ' ', ' ', 'w', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', ' ', ' ', ' ', 'b', 'w'], | |
| [' ', ' ', ' ', ' ', ' ', ' ', ' ', 'b'], | |
| ['b', ' ', 'b', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', ' ', 'b', ' ', 'w', ' '], | |
| ['b', ' ', ' ', ' ', ' ', ' ', ' ', ' '], | |
| [' ', ' ', ' ', 'w', 'w', ' ', ' ', ' ']] | |
| player = 'w' | |
| expected = { | |
| 2 : (1, 1) , | |
| 3 : (0, 0) , | |
| 4 : (0, 0) , | |
| 5 : (0, 0) , | |
| } | |
| print("\nRunning test_detect_rows_complex_2_white...") | |
| for length, exp_val in expected.items(): | |
| result = gomoku.detect_rows(board, player, length) | |
| assert result == exp_val, f"Length {length}: Expected {exp_val}, got {result}" | |
| print("PASSED") | |
| def test_detect_rows_complex_3_black(): | |
| """Test Case 5: Complex board 3, Player Black""" | |
| board = [['w', ' ', 'b', 'w', ' ', 'w', ' ', 'b'], | |
| ['w', ' ', 'w', 'w', 'b', 'w', 'w', 'b'], | |
| ['b', 'b', ' ', 'b', ' ', ' ', 'b', 'w'], | |
| [' ', 'b', 'w', ' ', 'w', 'b', 'b', 'b'], | |
| ['b', 'b', 'w', 'b', 'w', 'b', ' ', 'w'], | |
| ['w', 'w', 'w', 'w', ' ', 'w', ' ', ' '], | |
| [' ', 'b', 'w', 'b', 'w', ' ', 'w', 'w'], | |
| [' ', ' ', 'w', 'b', ' ', 'b', 'w', 'w']] | |
| player = 'b' | |
| expected = { | |
| 2 : (0, 5) , | |
| 3 : (0, 1) , | |
| 4 : (0, 0) , | |
| 5 : (0, 0) , | |
| } | |
| print("\nRunning test_detect_rows_complex_3_black...") | |
| gomoku.print_board(board) | |
| for length, exp_val in expected.items(): | |
| result = gomoku.detect_rows(board, player, length) | |
| assert result == exp_val, f"Length {length}: Expected {exp_val}, got {result}" | |
| print("PASSED") | |
| def test_detect_rows_complex_3_white(): | |
| """Test Case 6: Complex board 3, Player White""" | |
| board = [['w', ' ', 'b', 'w', ' ', 'w', ' ', 'b'], | |
| ['w', ' ', 'w', 'w', 'b', 'w', 'w', 'b'], | |
| ['b', 'b', ' ', 'b', ' ', ' ', 'b', 'w'], | |
| [' ', 'b', 'w', ' ', 'w', 'b', 'b', 'b'], | |
| ['b', 'b', 'w', 'b', 'w', 'b', ' ', 'w'], | |
| ['w', 'w', 'w', 'w', ' ', 'w', ' ', ' '], | |
| [' ', 'b', 'w', 'b', 'w', ' ', 'w', 'w'], | |
| [' ', ' ', 'w', 'b', ' ', 'b', 'w', 'w']] | |
| player = 'w' | |
| expected = { | |
| 2 : (2, 6) , | |
| 3 : (0, 1) , | |
| 4 : (0, 2) , | |
| 5 : (0, 1) , | |
| } | |
| print("\nRunning test_detect_rows_complex_3_white...") | |
| for length, exp_val in expected.items(): | |
| result = gomoku.detect_rows(board, player, length) | |
| assert result == exp_val, f"Length {length}: Expected {exp_val}, got {result}" | |
| print("PASSED") | |
| def test_search_max_complex_1(): | |
| """Test Case 7: Search Max Complex Scenario 1""" | |
| board = [['w', ' ', 'b', 'w', ' ', 'w', ' ', 'b'], | |
| ['w', ' ', 'w', 'w', 'b', 'w', 'w', 'b'], | |
| ['b', 'b', ' ', 'b', ' ', ' ', 'b', 'w'], | |
| [' ', 'b', 'w', ' ', 'w', 'b', 'b', 'b'], | |
| ['b', 'b', 'w', 'b', 'w', 'b', ' ', 'w'], | |
| ['w', 'w', 'w', 'w', ' ', 'w', ' ', ' '], | |
| [' ', 'b', 'w', 'b', 'w', ' ', 'w', 'w'], | |
| [' ', ' ', 'w', 'b', ' ', 'b', 'w', 'w']] | |
| print("\nRunning test_search_max_complex_1...") | |
| gomoku.print_board(board) | |
| result = gomoku.search_max(board) | |
| expected = (2, 2) | |
| assert result == expected, f"Expected {expected}, got {result}" | |
| print("PASSED") | |
| def test_search_max_complex_2(): | |
| """Test Case 8: Search Max Complex Scenario 2""" | |
| board = [['w', 'w', 'b', 'b', ' ', 'b', ' ', 'w'], | |
| [' ', ' ', 'b', 'w', 'b', ' ', ' ', ' '], | |
| [' ', 'b', ' ', ' ', 'w', 'b', 'w', 'b'], | |
| ['w', 'w', 'w', 'w', ' ', 'w', 'b', 'b'], | |
| ['b', 'b', 'b', 'b', ' ', 'b', ' ', 'w'], | |
| ['b', 'b', 'w', 'b', ' ', ' ', ' ', ' '], | |
| ['w', ' ', 'b', 'b', 'b', ' ', 'w', ' '], | |
| ['b', ' ', ' ', 'b', 'b', 'w', 'b', ' ']] | |
| print("\nRunning test_search_max_complex_2...") | |
| gomoku.print_board(board) | |
| result = gomoku.search_max(board) | |
| expected = (5, 4) | |
| assert result == expected, f"Expected {expected}, got {result}" | |
| print("PASSED") | |
| if __name__ == '__main__': | |
| test_detect_rows_complex_1_black() | |
| test_detect_rows_complex_1_white() | |
| test_detect_rows_complex_2_black() | |
| test_detect_rows_complex_2_white() | |
| test_detect_rows_complex_3_black() | |
| test_detect_rows_complex_3_white() | |
| test_search_max_complex_1() | |
| test_search_max_complex_2() | |
| print("\nAll hidden tests passed for test_hidden_student.py!") | |
| </code></pre> | |
| </div> | |
| </details> | |
| <!-- TEST 4: is_bounded --> | |
| <details> | |
| <summary>test_is_bounded_student.py</summary> | |
| <div class="test-description"> | |
| Tests for <code>is_bounded</code>. Checks OPEN, SEMIOPEN, and CLOSED states in various directions. | |
| </div> | |
| <div class="code-wrapper"> | |
| <button class="copy-btn" onclick="copyCode(this)">Copy</button> | |
| <pre><code>""" | |
| TestIsBounded Student Test Suite | |
| Test Cases: | |
| 1. test_len2_unbound_x | |
| 2. test_len2_unbound_x_white | |
| 3. test_len2_unbound_y | |
| 4. test_len3_unbound_y_constrained | |
| 5. test_len4_unbound_d_constrained | |
| 6. test_len2_bound_y | |
| 7. test_len2_bound_x | |
| 8. test_len3_bound_x_boarder | |
| 9. test_len4_bound_d_boarder | |
| 10. test_len4_bound_d_boarder_lower_right_white | |
| 11. test_len2_semi_y | |
| 12. test_len2_semi_x | |
| 13. test_len3_semi_x_boarder | |
| 14. test_len4_semi_d_boarder | |
| 15. test_len4_semi_d_boarder_lower_right_white | |
| """ | |
| import gomoku | |
| def test_len2_unbound_x(): | |
| """Test Case 1: Length 2 open sequence in x direction""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,1, 2, 2, 0, 1).upper() | |
| expected = "OPEN" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_unbound_x PASSED") | |
| def test_len2_unbound_x_white(): | |
| """Test Case 2: Length 2 open sequence in x direction (white)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,2, 4, 2, 1, 0).upper() | |
| expected = "OPEN" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_unbound_x_white PASSED") | |
| def test_len2_unbound_y(): | |
| """Test Case 3: Length 2 open sequence in y direction""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ','b',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,2, 1, 2, 1, 0).upper() | |
| expected = "OPEN" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_unbound_y PASSED") | |
| def test_len3_unbound_y_constrained(): | |
| """Test Case 4: Length 3 open sequence in y direction (constrained by other pieces)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| ['b',' ','b',' ','w','w',' ',' '], | |
| [' ','b','b',' ','w','w',' ',' '], | |
| ['b','b','b','w','w',' ',' ',' '], | |
| [' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,3, 2, 3, 1, 0).upper() | |
| expected = "OPEN" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len3_unbound_y_constrained PASSED") | |
| def test_len4_unbound_d_constrained(): | |
| """Test Case 5: Length 4 open sequence in diagonal direction""" | |
| board = [[' ','w',' ',' ',' ',' ',' ',' '], | |
| ['w','b','b',' ','w',' ',' ',' '], | |
| [' ','b','b',' ','w',' ',' ',' '], | |
| [' ',' ',' ','b','w',' ',' ',' '], | |
| ['b',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,4, 4, 4, 1, 1).upper() | |
| expected = "OPEN" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len4_unbound_d_constrained PASSED") | |
| def test_len2_bound_y(): | |
| """Test Case 6: Length 2 closed sequence in y direction""" | |
| board = [[' ','w',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| ['b','b',' ',' ',' ',' ',' ',' '], | |
| [' ','w',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,2, 1, 2, 1, 0).upper() | |
| expected = "CLOSED" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_bound_y PASSED") | |
| def test_len2_bound_x(): | |
| """Test Case 7: Length 2 closed sequence in x direction""" | |
| board = [[' ',' ','b',' ',' ',' ',' ',' '], | |
| ['w','b','b','w',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,1, 2, 2, 0, 1).upper() | |
| expected = "CLOSED" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_bound_x PASSED") | |
| def test_len3_bound_x_boarder(): | |
| """Test Case 8: Length 3 closed sequence in x direction (border)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| ['b','b','b','w',' ',' ',' ',' '], | |
| ['w','b',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,1, 2, 3, 0, 1).upper() | |
| expected = "CLOSED" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len3_bound_x_boarder PASSED") | |
| def test_len4_bound_d_boarder(): | |
| """Test Case 9: Length 4 closed sequence in diagonal direction (border)""" | |
| board = [['b',' ',' ',' ',' ',' ',' ',' '], | |
| ['w','b','b',' ','w',' ',' ',' '], | |
| [' ',' ','b',' ',' ',' ',' ',' '], | |
| ['b','b','b','b',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ','w',' ',' '], | |
| [' ',' ',' ',' ',' ',' ','w',' '], | |
| ['w','w','w',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,3, 3, 4, 1, 1).upper() | |
| expected = "CLOSED" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len4_bound_d_boarder PASSED") | |
| def test_len4_bound_d_boarder_lower_right_white(): | |
| """Test Case 10: Length 4 closed sequence in diagonal direction (lower right, white)""" | |
| board = [['b',' ','b','b',' ','b',' ',' '], | |
| [' ',' ',' ','b','b',' ',' ',' '], | |
| [' ','b',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ','b','b',' ',' ',' '], | |
| [' ','b',' ','b','w','w','w','w'], | |
| [' ',' ',' ','b','w','w',' ',' '], | |
| [' ',' ',' ','b','w',' ','w',' '], | |
| ['w','w','b','w','w',' ',' ','w']] | |
| result = gomoku.is_bounded(board,7, 7, 4, 1, 1).upper() | |
| expected = "CLOSED" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len4_bound_d_boarder_lower_right_white PASSED") | |
| def test_len2_semi_y(): | |
| """Test Case 11: Length 2 semi-open sequence in y direction""" | |
| board = [[' ','w',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| ['b','b','w',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,2, 1, 2, 1, 0).upper() | |
| expected = "SEMIOPEN" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_semi_y PASSED") | |
| def test_len2_semi_x(): | |
| """Test Case 12: Length 2 semi-open sequence in x direction""" | |
| board = [[' ',' ','b',' ',' ',' ',' ',' '], | |
| ['w','b','b',' ',' ',' ',' ',' '], | |
| [' ',' ','w',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,1, 2, 2, 0, 1).upper() | |
| expected = "SEMIOPEN" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len2_semi_x PASSED") | |
| def test_len3_semi_x_boarder(): | |
| """Test Case 13: Length 3 semi-open sequence in x direction (border)""" | |
| board = [['b',' ','b',' ',' ',' ',' ',' '], | |
| ['w','b','b','w','w',' ',' ',' '], | |
| ['b','b','b',' ',' ',' ',' ',' '], | |
| [' ',' ','w','w','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,2, 2, 3, 0, 1).upper() | |
| expected = "SEMIOPEN" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len3_semi_x_boarder PASSED") | |
| def test_len4_semi_d_boarder(): | |
| """Test Case 14: Length 4 semi-open sequence in diagonal direction (border)""" | |
| board = [['b',' ',' ','b',' ',' ',' ',' '], | |
| ['w','b','b','b','w',' ',' ',' '], | |
| [' ',' ','b','b',' ',' ',' ',' '], | |
| ['b','b','b','b','w',' ',' ',' '], | |
| [' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ','w',' ','w',' ',' '], | |
| [' ',' ',' ','w',' ',' ','w',' '], | |
| ['w','w','w','w',' ',' ',' ',' ']] | |
| result = gomoku.is_bounded(board,3, 3, 4, 1, 1).upper() | |
| expected = "SEMIOPEN" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len4_semi_d_boarder PASSED") | |
| def test_len4_semi_d_boarder_lower_right_white(): | |
| """Test Case 15: Length 4 semi-open sequence in diagonal direction (lower right, white)""" | |
| board = [['b',' ','b','b',' ',' ',' ',' '], | |
| [' ',' ',' ','b','b',' ',' ',' '], | |
| [' ',' ',' ','b',' ',' ',' ',' '], | |
| [' ',' ',' ',' ','b',' ',' ',' '], | |
| [' ',' ',' ','b','w','w','w','w'], | |
| [' ',' ',' ','b','w','w',' ',' '], | |
| [' ',' ',' ','b','w',' ','w',' '], | |
| ['w','w','b','b','w',' ',' ','w']] | |
| result = gomoku.is_bounded(board,7, 7, 4, 1, 1).upper() | |
| expected = "SEMIOPEN" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_len4_semi_d_boarder_lower_right_white PASSED") | |
| if __name__ == '__main__': | |
| test_len2_unbound_x() | |
| test_len2_unbound_x_white() | |
| test_len2_unbound_y() | |
| test_len3_unbound_y_constrained() | |
| test_len4_unbound_d_constrained() | |
| test_len2_bound_y() | |
| test_len2_bound_x() | |
| test_len3_bound_x_boarder() | |
| test_len4_bound_d_boarder() | |
| test_len4_bound_d_boarder_lower_right_white() | |
| test_len2_semi_y() | |
| test_len2_semi_x() | |
| test_len3_semi_x_boarder() | |
| test_len4_semi_d_boarder() | |
| test_len4_semi_d_boarder_lower_right_white() | |
| print("All tests passed for test_is_bounded_student.py!") | |
| </code></pre> | |
| </div> | |
| </details> | |
| <!-- TEST 5: is_empty --> | |
| <details> | |
| <summary>test_is_empty_student.py</summary> | |
| <div class="test-description"> | |
| Basic validation for the <code>is_empty</code> function. | |
| </div> | |
| <div class="code-wrapper"> | |
| <button class="copy-btn" onclick="copyCode(this)">Copy</button> | |
| <pre><code>""" | |
| TestIsEmpty Student Test Suite | |
| Test Cases: | |
| 1. test_with_empty_board | |
| 2. test_with_non_empty_board | |
| """ | |
| import gomoku | |
| def test_with_empty_board(): | |
| """Test Case 1: Check if an empty board returns True""" | |
| empty_board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_empty(empty_board) | |
| expected = True | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_with_empty_board PASSED") | |
| def test_with_non_empty_board(): | |
| """Test Case 2: Check if a non-empty board returns False""" | |
| not_empty_board = [[' ',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_empty(not_empty_board) | |
| expected = False | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_with_non_empty_board PASSED") | |
| if __name__ == '__main__': | |
| test_with_empty_board() | |
| test_with_non_empty_board() | |
| print("All tests passed for test_is_empty_student.py!") | |
| </code></pre> | |
| </div> | |
| </details> | |
| <!-- TEST 6: is_win --> | |
| <details> | |
| <summary>test_is_win_student.py</summary> | |
| <div class="test-description"> | |
| Tests for win conditions ("White won", "Black won", "Draw", "Continue playing"). | |
| </div> | |
| <div class="code-wrapper"> | |
| <button class="copy-btn" onclick="copyCode(this)">Copy</button> | |
| <pre><code>""" | |
| TestIsWin Student Test Suite | |
| Test Cases: | |
| 1. test_simple_unbound_b_win | |
| 2. test_simple_unbound_w_win | |
| 3. test_simple_continue | |
| 4. test_draw | |
| 5. test_semi_bound_b_win1 | |
| 6. test_semi_bound_b_win2 | |
| 7. test_semi_w_win1 | |
| 8. test_semi_w_win2 | |
| 9. test_closed_win_b | |
| 10. test_closed_win_w | |
| 11. test_closed_win_complicated_board_b | |
| """ | |
| import gomoku | |
| def test_simple_unbound_b_win(): | |
| """Test Case 1: Simple unbound Black win (horizontal)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b','b','b','b',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "BLACK WON" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_simple_unbound_b_win PASSED") | |
| def test_simple_unbound_w_win(): | |
| """Test Case 2: Simple unbound White win (vertical)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ','w',' '], | |
| [' ',' ',' ',' ',' ',' ','w',' '], | |
| [' ',' ',' ','b',' ',' ','w',' '], | |
| [' ',' ',' ',' ',' ',' ','w',' '], | |
| ['b','b','b','b',' ',' ','w',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "WHITE WON" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_simple_unbound_w_win PASSED") | |
| def test_simple_continue(): | |
| """Test Case 3: No winner, continue playing""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ','w','w','w',' '], | |
| [' ',' ',' ',' ','w','w','w',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "CONTINUE PLAYING" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_simple_continue PASSED") | |
| def test_draw(): | |
| """Test Case 4: Full board with no winner (Draw)""" | |
| board = [['b','w','b','w','w','b','w','b'], | |
| ['b','w','b','w','w','b','w','b'], | |
| ['b','w','b','w','w','b','w','b'], | |
| ['b','w','b','w','w','b','w','b'], | |
| ['w','b','w','b','b','w','b','w'], | |
| ['w','b','w','b','b','w','b','w'], | |
| ['w','b','w','b','b','w','b','w'], | |
| ['w','b','w','b','b','w','b','w']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "DRAW" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_draw PASSED") | |
| def test_semi_bound_b_win1(): | |
| """Test Case 5: Semi-bounded Black win (vertical, top edge blocked)""" | |
| board = [[' ','b',' ',' ',' ',' ',' ',' '], | |
| [' ','b',' ',' ','w',' ',' ',' '], | |
| [' ','b',' ',' ','w',' ',' ',' '], | |
| [' ','b',' ',' ','w',' ',' ',' '], | |
| [' ','b',' ',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "BLACK WON" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_semi_bound_b_win1 PASSED") | |
| def test_semi_bound_b_win2(): | |
| """Test Case 6: Semi-bounded Black win (vertical, blocked by white)""" | |
| board = [[' ',' ',' ','w',' ',' ',' ',' '], | |
| [' ',' ',' ','b','w',' ',' ',' '], | |
| [' ',' ',' ','b','w',' ',' ',' '], | |
| [' ',' ',' ','b','w',' ',' ',' '], | |
| [' ',' ',' ','b',' ',' ',' ',' '], | |
| [' ',' ',' ','b',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "BLACK WON" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_semi_bound_b_win2 PASSED") | |
| def test_semi_w_win1(): | |
| """Test Case 7: Semi-bounded White win (vertical)""" | |
| board = [[' ','w',' ',' ',' ',' ',' ',' '], | |
| [' ','w',' ',' ','b',' ',' ',' '], | |
| [' ','w',' ',' ','b',' ',' ',' '], | |
| [' ','w',' ',' ','b',' ',' ',' '], | |
| [' ','w',' ',' ','b',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "WHITE WON" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_semi_w_win1 PASSED") | |
| def test_semi_w_win2(): | |
| """Test Case 8: Semi-bounded White win (vertical, blocked by black)""" | |
| board = [[' ','b',' ',' ',' ',' ',' ',' '], | |
| [' ','w',' ',' ','b',' ',' ',' '], | |
| [' ','w',' ',' ','b',' ',' ',' '], | |
| [' ','w',' ',' ','b',' ',' ',' '], | |
| [' ','w',' ',' ','b',' ',' ',' '], | |
| [' ','w',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "WHITE WON" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_semi_w_win2 PASSED") | |
| def test_closed_win_b(): | |
| """Test Case 9: Closed Black win (horizontal)""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ','w',' ',' ',' ',' '], | |
| ['b','b','b','b','b','w',' ',' '], | |
| [' ','w','w',' ','w',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "BLACK WON" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_closed_win_b PASSED") | |
| def test_closed_win_w(): | |
| """Test Case 10: Closed White win (horizontal)""" | |
| board = [['w','w','w','w','w','b',' ',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| ['b','b',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "WHITE WON" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_closed_win_w PASSED") | |
| def test_closed_win_complicated_board_b(): | |
| """Test Case 11: Closed Black win (vertical, complicated board)""" | |
| board = [[' ','w',' ',' ',' ',' ',' ',' '], | |
| [' ','b',' ',' ',' ',' ',' ',' '], | |
| [' ','b','w','w','w','w',' ',' '], | |
| [' ','b','b',' ',' ',' ',' ',' '], | |
| [' ','b',' ','b',' ',' ',' ',' '], | |
| [' ','b','w',' ',' ',' ',' ',' '], | |
| [' ','w',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| result = gomoku.is_win(board).upper() | |
| expected = "BLACK WON" | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_closed_win_complicated_board_b PASSED") | |
| if __name__ == '__main__': | |
| test_simple_unbound_b_win() | |
| test_simple_unbound_w_win() | |
| test_simple_continue() | |
| test_draw() | |
| test_semi_bound_b_win1() | |
| test_semi_bound_b_win2() | |
| test_semi_w_win1() | |
| test_semi_w_win2() | |
| test_closed_win_b() | |
| test_closed_win_w() | |
| test_closed_win_complicated_board_b() | |
| print("All tests passed for test_is_win_student.py!") | |
| </code></pre> | |
| </div> | |
| </details> | |
| <!-- TEST 7: public --> | |
| <details> | |
| <summary>test_public_student.py</summary> | |
| <div class="test-description"> | |
| Tests corresponding specifically to the figures (1-5) provided in the project PDF description. | |
| </div> | |
| <div class="code-wrapper"> | |
| <button class="copy-btn" onclick="copyCode(this)">Copy</button> | |
| <pre><code>""" | |
| TestPublic Student Test Suite | |
| These tests correspond to the figures provided in the project description. | |
| Test Cases: | |
| 1. test_public_figure_1: Open sequence with 3 white stones (1,0) | |
| 2. test_public_figure_2: Semi-open sequence with 3 black stones (0,1) | |
| 3. test_public_figure_3: Closed sequence with 4 white stones (0,1) | |
| 4. test_public_figure_4: Closed sequence with 3 black stones (1,1) | |
| 5. test_public_figure_5: Semi-open sequence with 4 white stones (1,-1) | |
| """ | |
| import gomoku | |
| def b2s(board): | |
| """Helper to convert board to string for debugging""" | |
| s = "*" | |
| for i in range(len(board[0])-1): | |
| s += str(i%10) + "|" | |
| s += str((len(board[0])-1)%10) | |
| s += "*\n" | |
| for i in range(len(board)): | |
| s += str(i%10) | |
| for j in range(len(board[0])-1): | |
| s += str(board[i][j]) + "|" | |
| s += str(board[i][len(board[0])-1]) | |
| s += "*\n" | |
| s += (len(board[0])*2 + 1)*"*" | |
| return s | |
| def test_public_figure_1(): | |
| """ | |
| Figure 1: An open sequence with 3 white stones. The direction is (1,0). | |
| The last stone is at location (6,1). | |
| """ | |
| print("\nRunning test_public_figure_1...") | |
| # 0 1 2 3 4 5 6 7 | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], # 0 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 1 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 2 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 3 | |
| [' ','w',' ',' ',' ',' ',' ',' '], # 4 | |
| [' ','w',' ',' ',' ',' ',' ',' '], # 5 | |
| [' ','w',' ',' ',' ',' ',' ',' '], # 6 | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] # 7 | |
| # 1. Check is_empty | |
| assert gomoku.is_empty(board) == False, f"Board is not empty, but is_empty returned True. \n{b2s(board)}" | |
| # 2. Check is_bounded | |
| # Sequence ends at (6,1), length 3, direction (1,0) [vertical] | |
| res_bounded = gomoku.is_bounded(board, 6, 1, 3, 1, 0) | |
| assert res_bounded == "OPEN", f"The sequence should be OPEN, got {res_bounded} \n{b2s(board)}" | |
| # 3. Check detect_row | |
| # Check column 1 starting at (0,1) going down (1,0) | |
| res_row = gomoku.detect_row(board, 'w', 0, 1, 3, 1, 0) | |
| assert res_row == (1, 0), f"There should be one open sequence of length 3 for white in column 1, got {res_row} \n{b2s(board)}" | |
| # 4. Check detect_rows | |
| res_rows = gomoku.detect_rows(board, 'w', 3) | |
| assert res_rows == (1, 0), f"There should be one open sequence of length 3 for white on the board, got {res_rows} \n{b2s(board)}" | |
| print("PASSED") | |
| def test_public_figure_2(): | |
| """ | |
| Figure 2: A semi-open sequence with 3 black stones. The direction is (0,1). | |
| The last stone is at location (3,5). | |
| """ | |
| print("\nRunning test_public_figure_2...") | |
| # 0 1 2 3 4 5 6 7 | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], # 0 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 1 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 2 | |
| [' ',' ',' ','b','b','b','w',' '], # 3 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 4 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 5 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 6 | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] # 7 | |
| # 1. Check is_empty | |
| assert gomoku.is_empty(board) == False, f"Board is not empty, but is_empty returned True. \n{b2s(board)}" | |
| # 2. Check is_bounded | |
| # Sequence ends at (3,5), length 3, direction (0,1) [horizontal] | |
| res_bounded = gomoku.is_bounded(board, 3, 5, 3, 0, 1) | |
| assert res_bounded == "SEMIOPEN", f"The sequence should be SEMIOPEN, got {res_bounded} \n{b2s(board)}" | |
| # 3. Check detect_row | |
| # Check row 3 starting at (3,0) going right (0,1) | |
| res_row = gomoku.detect_row(board, 'b', 3, 0, 3, 0, 1) | |
| assert res_row == (0, 1), f"There should be one semi-open sequence of length 3 for black in row 3, got {res_row} \n{b2s(board)}" | |
| # 4. Check detect_rows | |
| res_rows = gomoku.detect_rows(board, 'b', 3) | |
| assert res_rows == (0, 1), f"There should be one semi-open sequence of length 3 for black on the board, got {res_rows} \n{b2s(board)}" | |
| print("PASSED") | |
| def test_public_figure_3(): | |
| """ | |
| Figure 3: A closed sequence with 4 white stones. The direction is (0,1). | |
| The last stone is at location (3,3). | |
| """ | |
| print("\nRunning test_public_figure_3...") | |
| # 0 1 2 3 4 5 6 7 | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], # 0 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 1 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 2 | |
| ['w','w','w','w','b',' ',' ',' '], # 3 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 4 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 5 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 6 | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] # 7 | |
| # 1. Check is_empty | |
| assert gomoku.is_empty(board) == False, f"Board is not empty, but is_empty returned True. \n{b2s(board)}" | |
| # 2. Check is_bounded | |
| # Sequence ends at (3,3), length 4, direction (0,1) [horizontal] | |
| # Blocked by left edge and black stone at (3,4) | |
| res_bounded = gomoku.is_bounded(board, 3, 3, 4, 0, 1) | |
| assert res_bounded == "CLOSED", f"The sequence should be CLOSED, got {res_bounded} \n{b2s(board)}" | |
| # 3. Check detect_row | |
| # Check row 3 starting at (3,0) going right (0,1) | |
| # Closed sequences are NOT counted in detect_rows usually (returns open, semi_open) | |
| res_row = gomoku.detect_row(board, 'w', 3, 0, 4, 0, 1) | |
| assert res_row == (0, 0), f"There should be no open or semi-open sequences of length 4 for white in row 3, got {res_row} \n{b2s(board)}" | |
| # 4. Check detect_rows | |
| res_rows = gomoku.detect_rows(board, 'w', 4) | |
| assert res_rows == (0, 0), f"There should be no open or semi-open sequences of length 4 for white on the board, got {res_rows} \n{b2s(board)}" | |
| print("PASSED") | |
| def test_public_figure_4(): | |
| """ | |
| Figure 4: A closed sequence with 3 black stones. The direction is (1,1). | |
| The last stone is at location (7,2). | |
| """ | |
| print("\nRunning test_public_figure_4...") | |
| # 0 1 2 3 4 5 6 7 | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], # 0 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 1 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 2 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 3 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 4 | |
| ['b',' ',' ',' ',' ',' ',' ',' '], # 5 | |
| [' ','b',' ',' ',' ',' ',' ',' '], # 6 | |
| [' ',' ','b',' ',' ',' ',' ',' ']] # 7 | |
| # 1. Check is_empty | |
| assert gomoku.is_empty(board) == False, f"Board is not empty, but is_empty returned True. \n{b2s(board)}" | |
| # 2. Check is_bounded | |
| # Sequence ends at (7,2), length 3, direction (1,1) [diagonal] | |
| # Blocked by left edge (start) and bottom edge (end) | |
| res_bounded = gomoku.is_bounded(board, 7, 2, 3, 1, 1) | |
| assert res_bounded == "CLOSED", f"The sequence should be CLOSED, got {res_bounded} \n{b2s(board)}" | |
| # 3. Check detect_row | |
| # Check diagonal starting at (5,0) going (1,1) | |
| res_row = gomoku.detect_row(board, 'b', 5, 0, 3, 1, 1) | |
| assert res_row == (0, 0), f"There should be no open or semi-open sequences of length 3 for black in the diagonal, got {res_row} \n{b2s(board)}" | |
| # 4. Check detect_rows | |
| res_rows = gomoku.detect_rows(board, 'b', 3) | |
| assert res_rows == (0, 0), f"There should be no open or semi-open sequences of length 3 for black on the board, got {res_rows} \n{b2s(board)}" | |
| print("PASSED") | |
| def test_public_figure_5(): | |
| """ | |
| Figure 5: A semi-open sequence with 4 white stones. The direction is (1,-1). | |
| The last stone is at location (3,3). | |
| """ | |
| print("\nRunning test_public_figure_5...") | |
| # 0 1 2 3 4 5 6 7 | |
| board = [[' ',' ',' ',' ',' ',' ','w',' '], # 0 | |
| [' ',' ',' ',' ',' ','w',' ',' '], # 1 | |
| [' ',' ',' ',' ','w',' ',' ',' '], # 2 | |
| [' ',' ',' ','w',' ',' ',' ',' '], # 3 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 4 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 5 | |
| [' ',' ',' ',' ',' ',' ',' ',' '], # 6 | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] # 7 | |
| # 1. Check is_empty | |
| assert gomoku.is_empty(board) == False, f"Board is not empty, but is_empty returned True. \n{b2s(board)}" | |
| # 2. Check is_bounded | |
| # Sequence ends at (3,3), length 4, direction (1,-1) [reverse diagonal] | |
| # Start is (0,6). One side (0,6) is blocked by top edge. End (3,3) is open. | |
| res_bounded = gomoku.is_bounded(board, 3, 3, 4, 1, -1) | |
| assert res_bounded == "SEMIOPEN", f"The sequence should be SEMIOPEN, got {res_bounded} \n{b2s(board)}" | |
| # 3. Check detect_row | |
| # Check diagonal starting at (0,6) going (1,-1) | |
| res_row = gomoku.detect_row(board, 'w', 0, 6, 4, 1, -1) | |
| assert res_row == (0, 1), f"There should be one semi-open sequence of length 4 for white in the diagonal, got {res_row} \n{b2s(board)}" | |
| # 4. Check detect_rows | |
| res_rows = gomoku.detect_rows(board, 'w', 4) | |
| assert res_rows == (0, 1), f"There should be one semi-open sequence of length 4 for white on the board, got {res_rows} \n{b2s(board)}" | |
| print("PASSED") | |
| if __name__ == '__main__': | |
| test_public_figure_1() | |
| test_public_figure_2() | |
| test_public_figure_3() | |
| test_public_figure_4() | |
| test_public_figure_5() | |
| print("All tests passed for test_public_student.py!") | |
| </code></pre> | |
| </div> | |
| </details> | |
| <!-- TEST 8: search_max --> | |
| <details> | |
| <summary>test_search_max_student.py</summary> | |
| <div class="test-description"> | |
| Tests for the AI logic <code>search_max</code>. Ensures the computer picks the optimal move. | |
| </div> | |
| <div class="code-wrapper"> | |
| <button class="copy-btn" onclick="copyCode(this)">Copy</button> | |
| <pre><code>""" | |
| TestSearchMax Student Test Suite | |
| Test Cases: | |
| 1. test_search_max_simple | |
| 2. test_search_max_top_left_corner | |
| 3. test_search_max_no_over_write | |
| """ | |
| import gomoku | |
| def test_search_max_simple(): | |
| """Test Case 1: Search max on a board with vertical columns""" | |
| board = [[' ',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ','b','w',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| print("Testing search_max simple...") | |
| gomoku.print_board(board) | |
| result = gomoku.search_max(board) | |
| expected = (4, 4) | |
| # Note: This test relies on your detect_rows implementation being correct. | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_search_max_simple PASSED") | |
| def test_search_max_top_left_corner(): | |
| """Test Case 2: Search max finding move at (0,0) to block or win""" | |
| board = [[' ',' ',' ',' ',' ',' ',' ',' '], | |
| ['w','b',' ',' ',' ',' ',' ',' '], | |
| ['w',' ','b',' ',' ',' ',' ',' '], | |
| ['w',' ',' ','b',' ',' ',' ',' '], | |
| ['w',' ',' ',' ','b',' ',' ',' '], | |
| ['b',' ',' ',' ',' ','w',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' '], | |
| [' ',' ',' ',' ',' ',' ',' ',' ']] | |
| print("Testing search_max top left corner...") | |
| gomoku.print_board(board) | |
| result = gomoku.search_max(board) | |
| expected = (0, 0) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_search_max_top_left_corner PASSED") | |
| def test_search_max_no_over_write(): | |
| """Test Case 3: Search max should valid empty spot and not overwrite stones""" | |
| board = [['b',' ',' ',' ',' ',' ',' ',' '], | |
| ['w','w',' ',' ',' ',' ',' ',' '], | |
| ['w',' ','b','b',' ',' ',' ',' '], | |
| ['w',' ','b','b',' ',' ',' ',' '], | |
| ['w','b',' ',' ','b',' ',' ',' '], | |
| ['b','w',' ',' ',' ','b',' ',' '], | |
| [' ',' ','w',' ',' ',' ','w',' '], | |
| [' ',' ',' ','w',' ',' ',' ',' ']] | |
| print("Testing search_max no overwrite...") | |
| gomoku.print_board(board) | |
| result = gomoku.search_max(board) | |
| expected = (1, 4) | |
| assert result == expected, f"Expected {expected}, but got {result}" | |
| print("test_search_max_no_over_write PASSED") | |
| if __name__ == '__main__': | |
| # These tests assume your detect_rows and is_bounded functions work correctly. | |
| test_search_max_simple() | |
| test_search_max_top_left_corner() | |
| test_search_max_no_over_write() | |
| print("All tests passed for test_search_max_student.py!") | |
| </code></pre> | |
| </div> | |
| </details> | |
| <script> | |
| function copyCode(button) { | |
| const pre = button.nextElementSibling; | |
| const code = pre.innerText; | |
| navigator.clipboard.writeText(code).then(() => { | |
| const originalText = button.innerText; | |
| button.innerText = 'Copied!'; | |
| button.style.backgroundColor = 'rgba(40, 167, 69, 0.5)'; | |
| button.style.borderColor = 'rgba(40, 167, 69, 0.8)'; | |
| setTimeout(() => { | |
| button.innerText = originalText; | |
| button.style.backgroundColor = ''; | |
| button.style.borderColor = ''; | |
| }, 2000); | |
| }).catch(err => { | |
| console.error('Failed to copy text: ', err); | |
| button.innerText = 'Error'; | |
| }); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment