Last active
June 23, 2024 14:23
-
-
Save gjain-7/84d507054e28353f8166665d731e2091 to your computer and use it in GitHub Desktop.
Chess implementation in C. Does not work, some error in code.
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
| // borrwed from https://codereview.stackexchange.com/questions/234619/chess-game-in-c | |
| #include <math.h> | |
| #include <stdbool.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| void drawMoves(); | |
| enum Type { | |
| NONE = 0, | |
| PAWN, | |
| ROOK, | |
| BISHOP, | |
| KNIGHT, | |
| QUEEN, | |
| KING, | |
| }; | |
| enum Color { | |
| BLACK = 0, | |
| WHITE, | |
| }; | |
| struct Piece { | |
| enum Type type; | |
| enum Color color; | |
| }; | |
| // struct Piece board[8][8] = {{{ROOK, BLACK}, | |
| // {KNIGHT, BLACK}, | |
| // {BISHOP, BLACK}, | |
| // {QUEEN, BLACK}, | |
| // {KING, BLACK}, | |
| // {BISHOP, BLACK}, | |
| // {KNIGHT, BLACK}, | |
| // {ROOK, BLACK}}, | |
| // {{PAWN, BLACK}, | |
| // {PAWN, BLACK}, | |
| // {PAWN, BLACK}, | |
| // {PAWN, BLACK}, | |
| // {PAWN, BLACK}, | |
| // {PAWN, BLACK}, | |
| // {PAWN, BLACK}, | |
| // {PAWN, BLACK}}, | |
| // {{NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}}, | |
| // {{NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}}, | |
| // {{NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}}, | |
| // {{NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}, | |
| // {NONE, BLACK}}, | |
| // {{PAWN, WHITE}, | |
| // {PAWN, WHITE}, | |
| // {PAWN, WHITE}, | |
| // {PAWN, WHITE}, | |
| // {PAWN, WHITE}, | |
| // {PAWN, WHITE}, | |
| // {PAWN, WHITE}, | |
| // {PAWN, WHITE}}, | |
| // {{ROOK, WHITE}, | |
| // {KNIGHT, WHITE}, | |
| // {BISHOP, WHITE}, | |
| // {QUEEN, WHITE}, | |
| // {KING, WHITE}, | |
| // {BISHOP, WHITE}, | |
| // {KNIGHT, WHITE}, | |
| // {ROOK, WHITE}}}; | |
| struct Piece board[8][8] = { | |
| {{ROOK, BLACK}, {KNIGHT, BLACK}, {BISHOP, BLACK}, {QUEEN, BLACK}, | |
| {KING, BLACK}, {NONE, BLACK}, {NONE, BLACK}, {ROOK, BLACK}}, | |
| {{NONE, BLACK}, {PAWN, BLACK}, {PAWN, BLACK}, {PAWN, BLACK}, | |
| {NONE, BLACK}, {PAWN, BLACK}, {PAWN, BLACK}, {PAWN, BLACK}}, | |
| {{PAWN, BLACK}, {NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}, | |
| {NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}, {KNIGHT, BLACK}}, | |
| {{NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}, | |
| {QUEEN, WHITE}, {NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}}, | |
| {{NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}, | |
| {PAWN, WHITE}, {NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}}, | |
| {{KNIGHT, WHITE}, {NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}, | |
| {NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}, {NONE, BLACK}}, | |
| {{PAWN, WHITE}, {PAWN, WHITE}, {PAWN, WHITE}, {NONE, BLACK}, | |
| {NONE, BLACK}, {PAWN, WHITE}, {PAWN, BLACK}, {PAWN, WHITE}}, | |
| {{ROOK, WHITE}, {NONE, WHITE}, {BISHOP, WHITE}, {NONE, BLACK}, | |
| {KING, WHITE}, {BISHOP, WHITE}, {KNIGHT, WHITE}, {ROOK, WHITE}} | |
| }; | |
| int moves[8][8]; | |
| enum Color currentTurn; | |
| int findKing(enum Color col) { | |
| for (int i = 0; i < 8; i++) | |
| for (int j = 0; j < 8; j++) | |
| if (board[i][j].type == KING && board[i][j].color == col) | |
| return i * 8 + j; | |
| return -1; | |
| } | |
| int getValidBishopMoves(int x, int y, enum Color color) { | |
| int canMove = 1; | |
| for (int xDir = -1; xDir < 2; xDir += 2) { | |
| for (int yDir = -1; yDir < 2; yDir += 2) { | |
| int count = 1; | |
| while (1) { | |
| if (x + (count * xDir) <= 7 && x + (count * xDir) >= 0 && | |
| y + (count * yDir) <= 7 && y + (count * yDir) >= 0) { | |
| struct Piece p = | |
| board[y + (count * yDir)][x + (count * xDir)]; | |
| if (p.type != NONE) { | |
| if (p.color != color) { | |
| moves[y + (count * yDir)][x + (count * xDir)] = 3; | |
| canMove = 0; | |
| } | |
| break; | |
| } else { | |
| moves[y + (count * yDir)][x + (count * xDir)] = 1; | |
| canMove = 0; | |
| } | |
| } else { | |
| break; | |
| } | |
| count++; | |
| } | |
| } | |
| } | |
| return canMove; | |
| } | |
| int getValidRookMoves(int x, int y, enum Color color) { | |
| int canMove = 1; | |
| for (int dir = -1; dir < 2; dir += 2) { | |
| for (int tx = x + dir; tx >= 0 && tx <= 7; tx += dir) { | |
| if (board[y][tx].type != NONE) { | |
| if (board[y][tx].color != color) { | |
| moves[y][tx] = 3; | |
| canMove = 0; | |
| } | |
| break; | |
| } else { | |
| moves[y][tx] = 1; | |
| canMove = 0; | |
| } | |
| } | |
| for (int ty = y + dir; ty >= 0 && ty <= 7; ty += dir) { | |
| if (board[ty][x].type != NONE) { | |
| if (board[ty][x].color != color) { | |
| moves[ty][x] = 3; | |
| canMove = 0; | |
| } | |
| break; | |
| } else { | |
| moves[ty][x] = 1; | |
| canMove = 0; | |
| } | |
| } | |
| } | |
| return canMove; | |
| } | |
| int getValidPawnMoves(int x, int y, enum Color color) { | |
| int canMove = 1; | |
| if (color == WHITE) { | |
| if (y == 6 && board[y - 2][x].type == NONE) { | |
| moves[y - 2][x] = 1; | |
| canMove = 0; | |
| } | |
| if (y - 1 >= 0) { | |
| if (board[y - 1][x].type == NONE) { | |
| moves[y - 1][x] = 1; | |
| canMove = 0; | |
| } | |
| if (x + 1 <= 7 && board[y - 1][x + 1].color == BLACK && | |
| board[y - 1][x + 1].type != NONE) { | |
| moves[y - 1][x + 1] = 3; | |
| canMove = 0; | |
| } | |
| if (x - 1 >= 0 && board[y - 1][x - 1].color == BLACK && | |
| board[y - 1][x - 1].type != NONE) { | |
| moves[y - 1][x - 1] = 3; | |
| canMove = 0; | |
| } | |
| } | |
| } else { | |
| if (y == 1 && board[y + 2][x].type == NONE) { | |
| moves[y + 2][x] = 1; | |
| canMove = 0; | |
| } | |
| if (y + 1 <= 7) { | |
| if (board[y + 1][x].type == NONE) { | |
| moves[y + 1][x] = 1; | |
| canMove = 0; | |
| } | |
| if (x + 1 <= 7 && board[y + 1][x + 1].color == WHITE && | |
| board[y + 1][x + 1].type != NONE) { | |
| moves[y + 1][x + 1] = 3; | |
| canMove = 0; | |
| } | |
| if (x - 1 >= 0 && board[y + 1][x - 1].color == WHITE && | |
| board[y + 1][x - 1].type != NONE) { | |
| moves[y + 1][x - 1] = 3; | |
| canMove = 0; | |
| } | |
| } | |
| } | |
| return canMove; | |
| } | |
| int getValidKnightMoves(int x, int y, enum Color color) { | |
| // define a knight move in xdir and ydir | |
| int xdir[] = {1, 2, 2, 1, -1, -2, -2, -1}; | |
| int ydir[] = {2, 1, -1, -2, -2, -1, 1, 2}; | |
| int canMove = 1; | |
| for (int i = 0; i < 8; i++) { | |
| // out of bounds check | |
| if (x + xdir[i] > 7 || x + xdir[i] < 0 || y + ydir[i] > 7 || | |
| y + ydir[i] < 0) | |
| continue; | |
| // move to empty square | |
| if (board[y + ydir[i]][x + xdir[i]].type == NONE) { | |
| moves[y + ydir[i]][x + xdir[i]] = 1; | |
| canMove = 0; | |
| } | |
| // capture | |
| else if (board[y + ydir[i]][x + xdir[i]].color != color) { | |
| moves[y + ydir[i]][x + xdir[i]] = 3; | |
| canMove = 0; | |
| } | |
| } | |
| return canMove; | |
| } | |
| int getValidKingMoves(int x, int y, enum Color col) { | |
| int canMove = 1; | |
| for (int xDir = -1; xDir < 2; xDir++) { | |
| for (int yDir = -1; yDir < 2; yDir++) { | |
| if (xDir + x <= 7 && xDir + x >= 0 && y + yDir >= 0 && | |
| yDir + y <= 7 && !(xDir == 0 && yDir == 0)) { | |
| if (board[yDir + y][xDir + x].type != NONE) { | |
| if (board[yDir + y][xDir + x].color != col) | |
| moves[yDir + y][xDir + x] = 3; | |
| canMove = 0; | |
| } else { | |
| moves[yDir + y][xDir + x] = 1; | |
| canMove = 0; | |
| } | |
| } | |
| } | |
| } | |
| return canMove; | |
| } | |
| int getValidMoves(int x, int y) { | |
| if (x > 7 || x < 0 || y > 7 || y < 0) return 1; | |
| // clear the board | |
| for (int i = 0; i < 8; i++) | |
| for (int j = 0; j < 8; j++) moves[i][j] = 0; | |
| struct Piece piece = board[y][x]; | |
| moves[y][x] = 2; | |
| if (piece.type == NONE) { | |
| return 1; | |
| } | |
| if (piece.type == PAWN) { | |
| return getValidPawnMoves(x, y, piece.color); | |
| } | |
| if (piece.type == KNIGHT) { | |
| return getValidKnightMoves(x, y, piece.color); | |
| } | |
| if (piece.type == BISHOP) { | |
| return getValidBishopMoves(x, y, piece.color); | |
| } | |
| if (piece.type == ROOK) { | |
| return getValidRookMoves(x, y, piece.color); | |
| } | |
| if (piece.type == QUEEN) { | |
| int rk = getValidRookMoves(x, y, piece.color); | |
| int bs = getValidBishopMoves(x, y, piece.color); | |
| return rk && bs; | |
| } | |
| if (piece.type == KING) { | |
| return getValidKingMoves(x, y, piece.color); | |
| } | |
| return 1; | |
| } | |
| bool isCheck(enum Color currerntTurn) { | |
| int kingX, kingY; | |
| kingX = findKing(currentTurn); | |
| kingY = kingX % 8; | |
| kingX /= 8; | |
| printf("king is here %d %d\n", kingY+1, kingX+1); | |
| printf("%d\n", getValidMoves(5-1,4-1)); | |
| printf("%d\n", moves[kingX][kingY]); | |
| drawMoves(); | |
| // exit(0); | |
| for (int x = 0; x < 8; x++) { | |
| for (int y = 0; y < 8; y++) { | |
| // if (board[x][y].color != currentTurn && getValidMoves(x, y) == 0 && | |
| // ((moves[kingX][kingY] == 1 || moves[kingX][kingY] == 3))) { | |
| // printf("here i am\n"); | |
| // return 1; | |
| // } | |
| } | |
| } | |
| return 0; | |
| } | |
| /** | |
| * @brief if the king is in check, and for each valid move of king, there is a | |
| * check then its a check mate | |
| * @param currentTurn | |
| * @return true if the king is in checkmate otherwise false | |
| */ | |
| bool isCheckmate(enum Color currentTurn) { | |
| if (!isCheck(currentTurn)) return false; | |
| // find king | |
| int kingX, kingY; | |
| kingX = findKing(currentTurn); | |
| kingY = kingX % 8; | |
| kingX /= 8; | |
| getValidMoves(kingX, kingY); | |
| for (int i = 0; i < 8; i++) { | |
| for (int j = 0; j < 8; j++) { | |
| if (moves[i][j] == 1 || moves[i][j] == 3) { | |
| struct Piece temp = board[i][j]; | |
| board[i][j] = board[kingX][kingY]; | |
| board[kingX][kingY].type = NONE, | |
| board[kingX][kingY].color = BLACK; | |
| bool result = isCheck(currentTurn); | |
| board[kingX][kingY] = board[i][j]; | |
| board[i][j] = temp; | |
| if (!result) return false; | |
| } | |
| } | |
| } | |
| return true; | |
| } | |
| void drawBoard() { | |
| printf(" "); | |
| for (int y = 0; y < 8; y++) { | |
| printf("%d: ", y + 1); | |
| } | |
| printf("\n"); | |
| for (int x = 0; x < 8; x++) { | |
| printf("%d: ", x + 1); | |
| for (int y = 0; y < 8; y++) { | |
| if (board[x][y].type != NONE) { | |
| printf("%d%d", board[x][y].type, board[x][y].color); | |
| } else { | |
| printf("--"); | |
| } | |
| printf(" "); | |
| } | |
| printf("\n"); | |
| } | |
| } | |
| void drawMoves() { | |
| printf(" "); | |
| for (int y = 0; y < 8; y++) { | |
| printf("%d: ", y + 1); | |
| } | |
| printf("\n"); | |
| for (int x = 0; x < 8; x++) { | |
| printf("%d: ", x + 1); | |
| for (int y = 0; y < 8; y++) { | |
| if (moves[x][y] == 0) { | |
| printf("--"); | |
| } else { | |
| printf("%d%d", moves[x][y], moves[x][y]); | |
| } | |
| printf(" "); | |
| } | |
| printf("\n"); | |
| } | |
| } | |
| void play() { | |
| currentTurn = WHITE; | |
| while (1) { | |
| system("@cls||clear"); | |
| // if current state is checkmate then end game | |
| if (isCheckmate(currentTurn)) { | |
| printf("Checkmate\n"); | |
| if (currentTurn == WHITE) | |
| printf("Black wins\n"); | |
| else | |
| printf("White wins\n"); | |
| return; | |
| } | |
| if (currentTurn == WHITE) | |
| printf("White's turn\n\n"); | |
| else | |
| printf("Black's turn\n\n"); | |
| drawBoard(); | |
| // take input for selecting piece | |
| int x, y; | |
| scanf("%d %d", &x, &y); | |
| x--, y--; | |
| if (board[y][x].type == NONE || board[y][x].color != currentTurn || | |
| getValidMoves(x, y) == 1 || isCheck(currentTurn)) | |
| continue; | |
| system("@cls||clear"); | |
| drawBoard(); | |
| printf("\n"); | |
| drawMoves(); | |
| // take input for selecting move | |
| int x1, y1; | |
| scanf("%d %d", &x1, &y1); | |
| x1--, y1--; | |
| // How to check if the move is valid | |
| // if the piece is of self (checking while 1st input) | |
| // its is running the correct move and likewise capturing in right | |
| // square (move matrix) move does not result in check (add check | |
| // condition) | |
| // if the move is valid then make the move and change the turn | |
| if ((moves[y1][x1] == 1 || moves[y1][x1] == 3) && | |
| !isCheck(currentTurn)) { | |
| board[y1][x1] = board[y][x]; | |
| board[y][x].type = NONE, board[y][x].color = BLACK; | |
| currentTurn = (enum Color)((currentTurn + 1) % 2); | |
| } | |
| } | |
| } | |
| int main() { | |
| drawBoard(); | |
| int res = isCheck(BLACK); | |
| printf("%d\n", res); | |
| // printf() | |
| // play(); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment