Skip to content

Instantly share code, notes, and snippets.

@IvanaGyro
Created August 27, 2018 13:32
Show Gist options
  • Save IvanaGyro/4447cae2ba9318a6076b160b36817075 to your computer and use it in GitHub Desktop.
Save IvanaGyro/4447cae2ba9318a6076b160b36817075 to your computer and use it in GitHub Desktop.
Simple Chinese Dark Chess playing in the command line mode.
#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