Gomoku Stage 2: Try It Yourself
Test your problem-solving skills in the Gomoku n player challenging exercise.
We'll cover the following
Now that we know how to start and continue the game, let’s implement the second stage, where we decide how and when to stop the game.
- The game will end in one of two ways: when a player wins or when the game is a draw.
- We will also implement a tournament format, which allows players to play multiple games with the option to end the tournament after each game.
So let us now incorporate the stopping conditions in our code.
Implementation playground for stage II
Write your code in this playground. The implementation for Stage 1 and the function prototypes for Stage 2 (which will be discussed in the directions section) have already been provided.
#include <iostream> #include <iomanip> #include<time.h> #define CAPACITY 100 using namespace std; void init(char Board[][CAPACITY], int& dim, char pName[2][30], char pSym[], int&NOP, int& turn, int& winCount); void printBoard(char Board[][CAPACITY], int dim); void userInput(int& ri, int& ci, char pName[], char pSym); bool validInput(int ri, int ci, char Board[][CAPACITY], int dim); void updateBoard(char Board[][CAPACITY], int dim, int ri, int ci, char pSym); void turnChange(int& turn, int NOP); // Assume: The above 6 functions implementations are available bool horizontalCheck(char Board[][CAPACITY], int dim, int winCount, char pSym, int ri, int ci) { // Write your code here } bool vericalCheck(char Board[][CAPACITY], int dim, int winCount, char pSym, int ri, int ci) { // Write your code here } bool rightDiagonalCheck(char Board[][CAPACITY], int dim, int winCount, char pSym, int ri, int ci) { // Write your code here } bool leftDiagonalCheck(char Board[][CAPACITY], int dim, int winCount, char pSym, int ri, int ci) { // Write your code here } bool isWinHere(char Board[][CAPACITY], int dim, int winCount, char pSym, int ri, int ci) { // Write your code here } bool isWin(char Board[][CAPACITY], int dim, int winCount, char pSym) { // Write your code here } bool isDraw(char Board[][CAPACITY], int dim) { // Write your code here } int main() { cout <<"\n\n\t\t\tThe Game of Gomoku...!!!\n\n"; cout <<"\n\n\t\t\t Let us play...!\n\n"<<endl; srand(time(0)); char choice; char Board[CAPACITY][CAPACITY]; char pName[2][30]; char pSym[2]; int NOP, winCount, dim; int turn, ri, ci; cout <<"Initializing..."<<endl; // passing the function arguments in the same // order as the function expects them init(Board, dim, pName, pSym, NOP, turn, winCount); // steps to repeat for each player's turn do { printBoard(Board, dim); // do while loop to ensure the input entered is valid do { askForMove(ri, ci, pName[turn], pSym[turn]); if(!isValidMove(ri, ci, Board, dim)) { cout << "Invalid Input" << endl; } } while(!isValidMove(ri, ci, Board, dim)); // Add code for Stage II: Add winning and draw conditions updateBoard(Board, dim, ri, ci, pSym[turn]); turnChange(turn, NOP); } while(true); // Add code for Stage II: displaying winner and drawn msg }
Stage 2 (directions)
The first thing we need to do is to make two functions. First, to decide the winning of the current player. Second, for the drawn case. Let’s make these two functions first and then call them later in the main-flow.
Extending the memory
To declare a game to be over, we need to check if someone has won the game after each turn.
We would need a bool
variable called gameOver
, which can initially be set to false
.
We can have a variable called winner
set to -1
initially.
Checking for the winner
After displaying the updated board, we can have a function that checks if we have a winner after each turn. Let’s call this function isWin()
.
What arguments should be included when calling this function to determine if a victory has been achieved?
We would need the following:
-
winCount
(to determine if a player has achieved a certain number of consecutive occupied cells, represented by thewinCount
variable). -
pSym
(to check that particular symbol forwinCount
condition). -
Board[][CAPACITY]
(on which we are playing) of the dimensiondim
.
Our function prototype would then be as follows:
bool isWin(char Board[][CAPACITY], int dim, int winCount, char pSym)
The primary win-check logic of the isWin()
function would be contained inside the isWinHere()
function. This function checks the specified cell of the board for the winning condition.
All of the parameters of this function is similar to its predecessor, with just one addition:
It would take the row and column indexes of the cell to check (
ri
andci
).
The following will be its prototype:
bool isWinHere(char Board[][CAPACITY], int dim, int winCount, char pSym, int ri, int ci)
In this function, we’ll be checking 4 directions (why not 8?) for winning, horizontally, vertically, and two diagonally. If any of the conditions are satisfied, the isWinHere()
function should return true
.
a. Checking win horizontally
Starting with the bool
function, horizontalCheck()
, we want to check if there are winCount
numbers of symbols from left to right.
Now, when checking horizontally, what has changed in terms of rows and columns?
The row remains the same but the number of columns increases.
Let’s create the following function:
bool horizontalCheck(char Board[][CAPACITY], int dim, int winCount, char pSym, int ri, int ci)
Instruction: Write your function implementation in the above playground.
b. Checking win vertically
Our verticalCheck()
function is very similar to the function above, except it checks for the winCount
number of symbols vertically.
Your function should return true
if there are vertical winCount
numbers of symbols.
Let’s create the following function:
bool vericalCheck(char Board[][CAPACITY], int dim, int winCount, char pSym, int ri, int ci)
Instruction: Write your function implementation in the above playground.
c. Checking win diagonally 1 (from top-left to down-right)
Next, we have the rightDiagonalCheck()
function that checks for the winCount
number of symbols from left to right diagonally.
Again, this function is also very similar, except here, both the number of rows and columns increase as we go down diagonally.
Let’s create the following function:
bool rightDiagonalCheck(char Board[][CAPACITY], int dim, int winCount, char pSym, int ri, int ci)
Instruction: Write your function implementation in the above playground.
d. Checking win diagonally 2 (from top-right to down-left)
Similarly, the leftDiagonalCheck()
function checks for the winCount
number of symbols from right to left diagonally.
For this direction, the number of rows increases, and the number of columns decreases as we go down diagonally from right to left.
Let’s create the following function:
bool leftDiagonalCheck(char Board[][CAPACITY], int dim, int winCount, char pSym, int ri, int ci)
Instruction: Write your function implementation in the above playground.
Checking for the game drawn
Now, let’s check for the other game-stopping conditions to see if the game is drawn or not.
For this, we can simply return false
if any one cell is equal to the dash -
. If none equals the dash, then we return true
.
So, the function prototype would be as follows:
bool isDraw(char Board[][CAPACITY], int dim)
Instruction: Write your function implementation in the above playground.
Changes in the main-flow
Let’s incorporate main()
to handle these three things one by one.
- Memory update—we need to save some variables to determine if the game is over, if it has been won, and by whom
- Winning conditions
- Match-drawn condition
- Output appropriate message when the game ends (drawn or win message)
- Converting the game into a tournament format will allow players to play repeatedly after each game, with the option to continue or end the tournament being prompted after each game