Reputation: 23
I'm looking to implement a board that looks something like this:
UUUU
UWBU
UBWU
UUUU
or
UUBU
BWBU
WBWU
UUUU
Conditions for legal move:
check for 'U' in array
if 'U' is found, check surrounding (8?) directions to find 'B' (I'm stuck on how to stay within the bounds of the outer ring, i.e only checking 3 directions for corner pieces)
if 'B' is found, continue in that direction, continue while this is true until 'W' is found. if 'W' is found, print the original position of 'U'
edit updated code I've looked up some more resources and I've changed the logic of my code, however the configured board is now printing incorrectly and the function runs to print some moves, but not all, is something flawed in my logic?
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void initializeBoard(char board[][26], int n){
int i, j;
for (i=0; i<n; i++){
for (j=0; j<n; j++){
board[i][j] = 'U';
}
}
board[(n/2)-1][(n/2)-1] = 'W';
board[(n/2)-1][n/2] = 'B';
board[n/2][n/2] = 'W';
board[n/2][(n/2)-1] = 'B';
// prints alphabet
char rowletter[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
printf(" ");
int c;
for(c=0; c<n; c++){
printf("%c", rowletter[c]);
}
printf("\n");
//prints board with alphabet
int e=0;
int a, b;
for (a=0; a<n; a++){
printf("%c ", rowletter[e]);
for (b=0; b<n; b++){
printf("%c", board[a][b]);
}
e++;
printf("\n");
}
}
//prints board depending on what player inputs
void configuredBoard(char playerBoard[][26], int n){
char colour=0, row = 0, col = 0;
//player enters move for desired colour i.e Wba is white on row b column a
scanf("%c%c%c", &colour, &row, &col);
int i, j;
for (i=0; i<n; i++){
for (j=0; j<n; j++){
playerBoard[i][j] = 'U';
}
}
playerBoard[(n/2)-1][(n/2)-1] = 'W';
playerBoard[(n/2)-1][n/2] = 'B';
playerBoard[n/2][n/2] = 'W';
playerBoard[n/2][(n/2)-1] = 'B';
while(colour != '!'){
row = (int)row-97;
col = (int)col-97;
playerBoard[row][col] = colour;
scanf(" %c%c%c", &colour, &row, &col);
}
// prints alphabet
char rowletter[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
printf(" ");
int c;
for(c=0; c<n; c++){
printf("%c", rowletter[c]);
}
printf("\n");
//prints board with alphabet
int e=0;
int a, b;
for (a=0; a<n; a++){
printf("%c ", rowletter[e]);
for (b=0; b<n; b++){
printf("%c", playerBoard[a][b]);
}
e++;
printf("\n");
}
}
bool checkLineMatch(char colour, int dr, int dc, int r, int c, char playerBoard[][26], int n){
if(playerBoard[r][c] == colour){
return true;
}
if((r+dr < 0) || (r+dr > n)){
return false;
}
if((c+dc <0 ) || (c+dc >n)){
return false;
}
if (playerBoard[r][c] == 'U'){
return false;
}
checkLineMatch(colour, dr, dc, r+dr, c+dc, playerBoard, n);
}
bool validMove(char colour, int dr, int dc, int r, int c, char playerBoard[][26], int n){
char oppositeColour;
if(colour == 'B'){
oppositeColour = 'W';
}
else if(colour == 'W'){
oppositeColour = 'B';
}
if((r+dr < 0) || (r+dr > n)){
return false;
}
if((c+dc <0 ) || (c+dc >n)){
return false;
}
if(playerBoard[r+dr][c+dc] != oppositeColour){
return false;
}
if((r+dr+dr < 0) || (r+dr+dr > n)){
return false;
}
if((c+dc+dc <0 ) || (c+dc+dc >n)){
return false;
}
return checkLineMatch(colour, dr, dc, r+dr+dr, r+dc+dc, playerBoard, n);
}
void findAvailableMoves(char colour, char playerBoard[][26], int n){
printf("Available Moves for %c: \n", colour);
int i, j;
for (int i=0; i<n; i++){
for (int j=0; j<n; j++){
if (playerBoard[i][j] == 'U'){
//nw is northwest, etc.
bool nw = validMove(colour, -1, -1, i, j, playerBoard, n);
bool nn = validMove(colour, -1, 0, i, j, playerBoard, n);
bool ne = validMove(colour, -1, 1, i, j, playerBoard, n);
bool ww = validMove(colour, 0, -1, i, j, playerBoard, n);
bool ee = validMove(colour, 0, 1, i, j, playerBoard, n);
bool sw = validMove(colour, 1, -1, i, j, playerBoard, n);
bool ss = validMove(colour, 1, 0, i, j, playerBoard, n);
bool se = validMove(colour, 1, 1, i, j, playerBoard, n);
// if direction is valid,
if (nw || nn || ne || ww || ee || sw || ss ||se){
//is valid move
printf("%c%c\n", (char)i+97, (char)j+97); //typecast to ascii
}
}
}
}
}
int main(void){
int n;
char board[26][26];
printf("Enter the board dimension: ");
scanf("%d", &n);
initializeBoard(board, n);
char playerBoard[26][26];
printf("Enter board configuration: \n");
configuredBoard(playerBoard, n);
findAvailableMoves('W', playerBoard, n);
findAvailableMoves('B', playerBoard, n);
printf("Enter a move: ");
}
Here is expected output vs actual output:
Upvotes: 1
Views: 432
Reputation: 3995
I've modified your code with explanation in the code comments.
Now it compiles and matches the expected output:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
/*
I have used this format of commenting
So that it does not conflict with your comments that are in // format
*/
/* Prefer 4 space indentation over 2 spaces, just a matter of taste */
/* It would have been better to have function prototypes to make the code more readable */
/* You are reusing this code many times, so I moved it to a function */
void displayBoard(char board[26][26], int n)
{
/*
// prints alphabet
char rowletter[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
printf(" ");
int c;
for(c=0; c<n; c++){
printf("%c", rowletter[c]);
}
printf("\n");
A Better way:
*/
char marker = 'a';
printf(" ");
for (int i = 0; i < n; ++i, ++marker)
printf("%c", marker);
printf("\n");
/*
//prints board with alphabet
int e=0;
int a, b;
for (a=0; a<n; a++){
printf("%c ", rowletter[e]);
for (b=0; b<n; b++){
printf("%c", board[a][b]);
}
e++;
printf("\n");
}
A better way:
*/
marker = 'a';
for (int i = 0; i < n; ++i, ++marker)
{
printf("%c ", marker);
for (int j = 0; j < n; ++j)
{
printf("%c", board[i][j]);
}
printf("\n");
}
}
void initializeBoard(char board[][26], int n){
int i, j;
for (i=0; i<n; i++){
for (j=0; j<n; j++){
board[i][j] = 'U';
}
}
board[(n/2)-1][(n/2)-1] = 'W';
board[(n/2)-1][n/2] = 'B';
board[n/2][n/2] = 'W';
board[n/2][(n/2)-1] = 'B';
/* INITIALIZE != DISPLAY
// prints alphabet
char rowletter[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
printf(" ");
int c;
for(c=0; c<n; c++){
printf("%c", rowletter[c]);
}
printf("\n");
//prints board with alphabet
int e=0;
int a, b;
for (a=0; a<n; a++){
printf("%c ", rowletter[e]);
for (b=0; b<n; b++){
printf("%c", board[a][b]);
}
e++;
printf("\n");
}
*/
}
/*
//prints board depending on what player inputs
NO, CONFIGURING != PRINTING
Each function should serve a specific purpose, not multiple purposes
You are violating the modular design and making your code less maintainable
*/
/*
// void configuredBoard(char playerBoard[][26], int n){
configured?
*/
void configureBoard(char playerBoard[][26], int n){
char colour=0, row = 0, col = 0;
/* Also have two ints for storing the coordinates of char input */
int x, y;
/*
You are doing this inside the while loop
//player enters move for desired colour i.e Wba is white on row b column a
scanf("%c%c%c", &colour, &row, &col);
*/
/*
You have already done this in initializeBoard()
int i, j;
for (i=0; i<n; i++){
for (j=0; j<n; j++){
playerBoard[i][j] = 'U';
}
}
playerBoard[(n/2)-1][(n/2)-1] = 'W';
playerBoard[(n/2)-1][n/2] = 'B';
playerBoard[n/2][n/2] = 'W';
playerBoard[n/2][(n/2)-1] = 'B';
*/
/* Make this an infinite loop and break it when the user enters "!!!"
Otherwise, playerBoard[!][!] = '!' will happen at the end of the loop
while(colour != '!'){/
*/
while (true) {
scanf(" %c%c%c", &colour, &row, &col);
/* Check for "!!!" */
if (colour == '!' && row == '!' && col == '!')
break;
/*
Array subscript has type 'char'
row = (int)row-97;
col = (int)col-97;
playerBoard[row][col] = colour;
*/
x = row - 97;
y = col - 97;
playerBoard[x][y] = colour;
/* Problem with the order of execution
playerBoard[x][y] = colour;
scanf(" %c%c%c", &colour, &row, &col);
*/
}
/* I guess, I don't have to repeat it again
// prints alphabet
char rowletter[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
printf(" ");
int c;
for(c=0; c<n; c++){
printf("%c", rowletter[c]);
}
printf("\n");
//prints board with alphabet
int e=0;
int a, b;
for (a=0; a<n; a++){
printf("%c ", rowletter[e]);
for (b=0; b<n; b++){
printf("%c", playerBoard[a][b]);
}
e++;
printf("\n");
}
*/
}
/*
x and y would have been a better choice over r and c in this function
Just a matter of convention:
r and c are more like constants
x and y are more like arbitrary constants
i and j are more like variables
Your r and c are actually the (x, y) coordinates of the board here
*/
/*
I'm finding it hard to correct the following three functions because
I'm unable to understand the logic:
Unwanted recursion,
Control reaches the end of non-void function,
Ambiguous comparisons,
...
Though you tried to implement Alin's approach,
I'll make it clear
*/
/*
bool checkLineMatch(char colour, int dr, int dc, int r, int c, char playerBoard[][26], int n){
if(playerBoard[r][c] == colour){
return true;
}
if((r+dr < 0) || (r+dr > n)){
return false;
}
if((c+dc <0 ) || (c+dc >n)){
return false;
}
if (playerBoard[r][c] == 'U'){
return false;
}
checkLineMatch(colour, dr, dc, r+dr, c+dc, playerBoard, n);
}
bool validMove(char colour, int dr, int dc, int r, int c, char playerBoard[][26], int n){
char oppositeColour;
if(colour == 'B'){
oppositeColour = 'W';
}
else if(colour == 'W'){
oppositeColour = 'B';
}
if((r+dr < 0) || (r+dr > n)){
return false;
}
if((c+dc <0 ) || (c+dc >n)){
return false;
}
if(playerBoard[r+dr][c+dc] != oppositeColour){
return false;
}
if((r+dr+dr < 0) || (r+dr+dr > n)){
return false;
}
if((c+dc+dc <0 ) || (c+dc+dc >n)){
return false;
}
return checkLineMatch(colour, dr, dc, r+dr+dr, r+dc+dc, playerBoard, n);
}
void findAvailableMoves(char colour, char playerBoard[][26], int n){
printf("Available Moves for %c: \n", colour);
int i, j;
for (int i=0; i<n; i++){
for (int j=0; j<n; j++){
if (playerBoard[i][j] == 'U'){
//nw is northwest, etc.
bool nw = validMove(colour, -1, -1, i, j, playerBoard, n);
bool nn = validMove(colour, -1, 0, i, j, playerBoard, n);
bool ne = validMove(colour, -1, 1, i, j, playerBoard, n);
bool ww = validMove(colour, 0, -1, i, j, playerBoard, n);
bool ee = validMove(colour, 0, 1, i, j, playerBoard, n);
bool sw = validMove(colour, 1, -1, i, j, playerBoard, n);
bool ss = validMove(colour, 1, 0, i, j, playerBoard, n);
bool se = validMove(colour, 1, 1, i, j, playerBoard, n);
// if direction is valid,
if (nw || nn || ne || ww || ee || sw || ss ||se){
//is valid move
printf("%c%c\n", (char)i+97, (char)j+97); //typecast to ascii
}
}
}
}
}
*/
/* Bring back your old function */
bool positionInBounds(int n, int x, int y)
{
return (x >= 0 && x < n && y >= 0 && y < n);
}
/* I've rewritten this function */
void findAvailableMoves(const char colour, const char board[][26], const int n)
{
int x, y;
const int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1};
const int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};
const char oppositeColour = colour == 'W' ? 'B' : 'W';
printf("Available Moves for %c: \n", colour);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
if (board[i][j] == 'U')
{
for (int k = 0; k < 8; k++)
{
x = i + dx[k];
y = j + dy[k];
while (positionInBounds(n, x, y) && board[x][y] == oppositeColour)
{
x += dx[k];
y += dy[k];
if (positionInBounds(n, x, y) && board[x][y] == colour)
{
printf("%c%c\n", (char)i + 97, (char)j + 97);
break;
}
}
}
}
}
}
}
int main(void){
int n;
char board[26][26];
printf("Enter the board dimension: ");
scanf("%d", &n);
initializeBoard(board, n);
/* Make a separate call to displayBoard instead of putting it inside initializeBoard */
displayBoard(board, n);
/* THIS TOOK A LOT OF TIME TO FIGURE OUT!
Why are you having a different board here!?
char playerBoard[26][26];
*/
printf("Enter board configuration: \n");
// configuredBoard(playerBoard, n);
configureBoard(board, n);
/* Make a separate call to displayBoard instead of putting it inside configureBoard */
displayBoard(board, n);
/* This would have been much cleaner if OOP was available */
// findAvailableMoves('W', playerBoard, n);
// findAvailableMoves('B', playerBoard, n);
findAvailableMoves('W', board, n);
findAvailableMoves('B', board, n);
printf("Enter a move: ");
/*
There are still many issues regarding
Formatting
Algorithm efficiency
Invalid input handling
and much more...
But, I hope that I've removed the 'errors'
*/
}
Upvotes: 1
Reputation: 51
I'm stuck on how to stay within the bounds of the outer ring, i.e only checking 3 directions for corner pieces
Based on this objective, of checking the neighbors, if they exist, this function should help:
bool checkNeighbours( int n, int row, int col ) {
// set up directions for all the neighbor cells
int dx[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
int dy[8] = { 0, 1, 1, 1, 0, -1, -1, -1 };
int x, y;
for( int i=0; i<8; i++ ) {
x = row + dx[i];
y = col + dy[i];
if( positionInBounds( n, x, y ) ) { // check if out of bounds
if( playerBoard[x][y] == oppositeColor ) { // add legalibility condition
return true;
// I don't understand exactly what this legality means
// but here you can add up any logic you want
// The idea is that here you can return either true or false based on your legality meaning
}
}
}
}
Upvotes: 1