Created
August 27, 2018 13:32
-
-
Save IvanaGyro/4447cae2ba9318a6076b160b36817075 to your computer and use it in GitHub Desktop.
Simple Chinese Dark Chess playing in the command line mode.
This file contains 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
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <time.h> | |
#define BOARD_H 4 | |
#define BOARD_W 8 | |
typedef struct chess | |
{ | |
int id; | |
int power; | |
int isShow; | |
int isDead; | |
char face[4]; | |
} chess; | |
typedef enum color | |
{ | |
NONE = -1, | |
BLACK = 0, | |
RED = 1 | |
} color; | |
int isRed(chess* c) | |
{ | |
if(c->id & 0x10) return 1; // bin: 10000 | |
else return 0; | |
} | |
void print_board(chess board[][BOARD_W]) | |
{ | |
int i, j; | |
printf(" "); | |
for(j = 0; j < BOARD_W; ++j) printf(" %d ", j); | |
printf("\n"); | |
for(i = 0; i < BOARD_H; ++i) | |
{ | |
printf("%d ", i); | |
for(j = 0; j < BOARD_W; ++j) | |
{ | |
if(board[i][j].isDead) printf(" "); | |
else | |
{ | |
if(board[i][j].isShow) printf("%s ", board[i][j].face); | |
else printf("● "); | |
} | |
} | |
printf("\n"); | |
} | |
} | |
void swap_chess(int ax, int ay, int bx, int by, chess board[][BOARD_W]) | |
{ | |
chess tmp; | |
tmp = board[ay][ax]; | |
board[ay][ax] = board[by][bx]; | |
board[by][bx] = tmp; | |
if(ax < 0 || ax > 7) printf("ax:%d\n", ax); | |
if(ay < 0 || ay > 3) printf("ay:%d\n", ay); | |
if(bx < 0 || bx > 7) printf("bx:%d\n", bx); | |
if(by < 0 || by > 3) printf("by:%d\n", by); | |
} | |
void init_board(chess board[][BOARD_W]) | |
{ | |
int i, j, subId; | |
int ax, ay, bx, by; | |
for(i = 0; i < BOARD_H; ++i) | |
{ | |
for(j = 0; j < BOARD_W; ++j) | |
{ | |
board[i][j].id = i * BOARD_W + j; | |
board[i][j].isShow = 0; | |
board[i][j].isDead = 0; | |
} | |
} | |
for(i = 0; i < 100; ++i) | |
{ | |
ax = rand() % BOARD_W; | |
ay = rand() % BOARD_H; | |
bx = rand() % BOARD_W; | |
by = rand() % BOARD_H; | |
swap_chess(ax, ay, bx, by, board); | |
} | |
for(i = 0; i < BOARD_H; ++i) | |
{ | |
for(j = 0; j < BOARD_W; ++j) | |
{ | |
subId = board[i][j].id & 0xf; | |
if(subId == 0) | |
{ | |
board[i][j].power = 6; | |
if(isRed(&(board[i][j]))) strcpy(board[i][j].face, "帥"); | |
else strcpy(board[i][j].face, "將"); | |
} | |
else if(subId >= 1 && subId <= 2) | |
{ | |
board[i][j].power = 5; | |
if(isRed(&(board[i][j]))) strcpy(board[i][j].face, "仕"); | |
else strcpy(board[i][j].face, "士"); | |
} | |
else if(subId >= 1 && subId <= 2) | |
{ | |
board[i][j].power = 5; | |
if(isRed(&(board[i][j]))) strcpy(board[i][j].face, "仕"); | |
else strcpy(board[i][j].face, "士"); | |
} | |
else if(subId >= 3 && subId <= 4) | |
{ | |
board[i][j].power = 4; | |
if(isRed(&(board[i][j]))) strcpy(board[i][j].face, "相"); | |
else strcpy(board[i][j].face, "象"); | |
} | |
else if(subId >= 5 && subId <= 6) | |
{ | |
board[i][j].power = 3; | |
if(isRed(&(board[i][j]))) strcpy(board[i][j].face, "俥"); | |
else strcpy(board[i][j].face, "車"); | |
} | |
else if(subId >= 7 && subId <= 8) | |
{ | |
board[i][j].power = 2; | |
if(isRed(&(board[i][j]))) strcpy(board[i][j].face, "傌"); | |
else strcpy(board[i][j].face, "馬"); | |
} | |
else if(subId >= 9 && subId <= 10) | |
{ | |
board[i][j].power = 1; | |
if(isRed(&(board[i][j]))) strcpy(board[i][j].face, "炮"); | |
else strcpy(board[i][j].face, "包"); | |
} | |
else if(subId >= 11 && subId <= 15) | |
{ | |
board[i][j].power = 0; | |
if(isRed(&(board[i][j]))) strcpy(board[i][j].face, "兵"); | |
else strcpy(board[i][j].face, "卒"); | |
} | |
} | |
} | |
} | |
int chess_turn(int x, int y, chess board[][BOARD_W]) | |
{ | |
if(board[y][x].isDead) | |
{ | |
printf("請選擇棋子\n"); | |
return 0; | |
} | |
if(!board[y][x].isShow) | |
{ | |
board[y][x].isShow = 1; | |
return 1; | |
} | |
else | |
{ | |
printf("所選棋子已經被翻面\n"); | |
return 0; | |
} | |
} | |
int chess_move(int dx, int dy, int sx, int sy, color pColor, chess board[][BOARD_W]) | |
{ | |
if(!board[dy][dx].isShow) | |
{ | |
printf("目的地棋子未翻開\n"); | |
return 0; | |
} | |
if(board[sy][sx].power == 1) //canon | |
{ | |
if(sx == dx && sy == dy) | |
{ | |
printf("請選擇合法目的地\n"); | |
return 0; | |
} | |
if(sx == dx) | |
{ | |
if(sy - dy == 1 || sy - dy == -1) | |
{ | |
if(board[dy][dx].isDead) | |
{ | |
swap_chess(dx, dy, sx, sy, board); | |
return 1; | |
} | |
else | |
{ | |
printf("請選擇合法目的地\n"); | |
return 0; | |
} | |
} | |
else | |
{ | |
int top, bot; | |
if(sy < dy) | |
{ | |
top = sy; | |
bot = dy; | |
} | |
else | |
{ | |
bot = sy; | |
top = dy; | |
} | |
int count = 0, i; | |
for(i = top + 1; i < bot; ++i) if(!board[i][sx].isDead) ++count; | |
if(count != 1) | |
{ | |
printf("請選擇合法目的地\n"); | |
return 0; | |
} | |
} | |
} | |
else if(sy == dy) | |
{ | |
if(sx - dx == 1 || sx - dx == -1) | |
{ | |
if(board[dy][dx].isDead) | |
{ | |
swap_chess(dx, dy, sx, sy, board); | |
return 1; | |
} | |
else | |
{ | |
printf("請選擇合法目的地\n"); | |
return 0; | |
} | |
} | |
else | |
{ | |
int left, right; | |
if(sx < dx) | |
{ | |
left = sx; | |
right = dx; | |
} | |
else | |
{ | |
right = sx; | |
left = dx; | |
} | |
int count = 0, i; | |
for(i = left + 1; i < right; ++i) if(!board[sy][i].isDead) ++count; | |
if(count != 1) | |
{ | |
printf("請選擇合法目的地\n"); | |
return 0; | |
} | |
} | |
} | |
board[dy][dx].isDead = 1; | |
swap_chess(dx, dy, sx, sy, board); | |
return 1; | |
} | |
else | |
{ | |
if(sx == dx) | |
{ | |
if(sy - dy != 1 && sy - dy != -1) | |
{ | |
printf("請選擇合法目的地\n"); | |
return 0; | |
} | |
} | |
else if(sy == dy) | |
{ | |
if(sx - dx != 1 && sx - dx != -1) | |
{ | |
printf("請選擇合法目的地\n"); | |
return 0; | |
} | |
} | |
if(board[dy][dx].isDead) | |
{ | |
swap_chess(dx, dy, sx, sy, board); | |
return 1; | |
} | |
if(board[sy][sx].power == 6) | |
{ | |
if(board[dy][dx].power == 0) | |
{ | |
printf("不可吃掉目的棋子\n"); | |
return 0; | |
} | |
} | |
else if(board[sy][sx].power == 0) | |
{ | |
if(board[dy][dx].power != 6 && board[dy][dx].power != 0) | |
{ | |
printf("不可吃掉目的棋子\n"); | |
return 0; | |
} | |
} | |
else | |
{ | |
if(board[sy][sx].power < board[dy][dx].power) | |
{ | |
printf("不可吃掉目的棋子\n"); | |
return 0; | |
} | |
} | |
board[dy][dx].isDead = 1; | |
swap_chess(dx, dy, sx, sy, board); | |
return 1; | |
} | |
} | |
int is_over(chess board[][BOARD_W]) | |
{ | |
int i, j; | |
int countBlack = 0, countRed = 0; | |
for(i = 0; i < BOARD_H; ++i) | |
{ | |
for(j = 0; j < BOARD_W; ++j) | |
{ | |
if(!board[i][j].isDead) | |
{ | |
if(isRed(&board[i][j])) ++countRed; | |
else ++countBlack; | |
} | |
} | |
} | |
if(!countRed) return BLACK; | |
if(!countBlack) return RED; | |
return NONE; | |
} | |
int main() | |
{ | |
int i, j, isValid; | |
int isOver = 0; | |
int status; // 1:turn 2:move | |
int turnStatus; | |
int moveStatus; | |
int curPlayer; | |
color p1Color = NONE; // 0:black 1:red | |
color curPlayerColor = NONE; | |
int ax, ay, bx, by; | |
chess board[BOARD_H][BOARD_W]; | |
srand(time(NULL)); | |
init_board(board); | |
printf("遊戲開始!!\n"); | |
print_board(board); | |
curPlayer = 1; | |
while(!isOver) | |
{ | |
if(p1Color != NONE) | |
{ | |
if(p1Color == RED) printf("\n玩家1: 紅 玩家2: 黑\n"); | |
else printf("\n玩家1: 黑 玩家2: 紅\n"); | |
if(curPlayer == 1) curPlayerColor = p1Color; | |
else | |
{ | |
if(p1Color == RED) curPlayerColor = BLACK; | |
else curPlayerColor = RED; | |
} | |
} | |
else printf("\n"); | |
printf("玩家%d 下棋\n", curPlayer); | |
status = 0; | |
while(status == 0) | |
{ | |
if(p1Color != NONE) | |
{ | |
printf("\n請選擇動作(1:翻牌 2:移動/吃):"); | |
scanf("%d", &status); | |
} | |
else | |
{ | |
printf("\n請翻棋\n"); | |
status = 1; | |
} | |
if(status == 1) | |
{ | |
isValid = 0; | |
while(!isValid) | |
{ | |
printf("請輸入x座標:"); | |
scanf("%d", &ax); | |
if(ax < 0 || ax >= BOARD_W) printf("請輸入合法x座標\n"); | |
else isValid = 1; | |
} | |
isValid = 0; | |
while(!isValid) | |
{ | |
printf("請輸入y座標:"); | |
scanf("%d", &ay); | |
if(ay < 0 || ay >= BOARD_H) printf("請輸入合法y座標\n"); | |
else isValid = 1; | |
} | |
if(!chess_turn(ax, ay, board)) status = 0; | |
if(p1Color == NONE) | |
{ | |
p1Color = isRed(&board[ay][ax]); | |
curPlayerColor = p1Color; | |
} | |
} | |
else if(status == 2) | |
{ | |
isValid = 0; | |
while(!isValid) | |
{ | |
printf("棋子x座標:"); | |
scanf("%d", &ax); | |
if(ax < 0 || ax >= BOARD_W) printf("請輸入合法x座標\n"); | |
else isValid = 1; | |
} | |
isValid = 0; | |
while(!isValid) | |
{ | |
printf("棋子y座標:"); | |
scanf("%d", &ay); | |
if(ay < 0 || ay >= BOARD_H) printf("請輸入合法y座標\n"); | |
else isValid = 1; | |
} | |
if(board[ay][ax].isDead) | |
{ | |
printf("請選擇棋子\n"); | |
status = 0; | |
continue; | |
} | |
if(!board[ay][ax].isShow) | |
{ | |
printf("請選擇翻開的棋子\n"); | |
status = 0; | |
continue; | |
} | |
if(curPlayerColor != isRed(&board[ay][ax])) | |
{ | |
printf("請選擇己方旗子\n"); | |
status = 0; | |
continue; | |
} | |
isValid = 0; | |
while(!isValid) | |
{ | |
printf("目的地x座標:"); | |
scanf("%d", &bx); | |
if(bx < 0 || bx >= BOARD_W) printf("請輸入合法x座標\n"); | |
else isValid = 1; | |
} | |
isValid = 0; | |
while(!isValid) | |
{ | |
printf("目的地y座標:"); | |
scanf("%d", &by); | |
if(by < 0 || by >= BOARD_H) printf("請輸入合法y座標\n"); | |
else isValid = 1; | |
} | |
if(!chess_move(bx, by, ax, ay, curPlayerColor, board)) status = 0; | |
} | |
else | |
{ | |
printf("請選擇合法動作\n"); | |
status = 0; | |
} | |
} | |
system("clear"); | |
print_board(board); | |
isOver = is_over(board); | |
if(isOver == curPlayerColor) | |
{ | |
printf("\n玩家%d 勝利\n", curPlayer); | |
isOver = 1; | |
} | |
else isOver = 0; | |
if(curPlayer == 1) curPlayer = 2; | |
else curPlayer = 1; | |
} | |
printf("\n按任Enter結束\n"); | |
getchar(); | |
getchar(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment