我为我的任务建立了一个简单的国际象棋程序。我在我的Linux机器里试过它,它运行得很好。我也在我的Windows机器中尝试过它。我在Windows机器上遇到的问题是Unicode字符没有像Linux那样正确显示。这是我的代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#ifdef _WIN32
#include <windows.h>
#endif
using namespace std;
/*
player 1 = 0 (black)
player 2 = 1 (white)
*/
char unicodePieces[2][6][4] =
{
{ "\u2654", "\u2655", "\u2656", "\u2657", "\u2658", "\u2659" },
{ "\u265A", "\u265B", "\u265C", "\u265D", "\u265E", "\u265F" }
};
typedef struct pieceinfo
{
// coordinate x & y on graph
int x, y;
// 1 = alive, 0 = dead
int status;
// belong to which player number (0 or 1)
int belong;
// location at unicodePieces
// also represent which piece this struct is
int pos;
} PieceInfo;
typedef struct chessplayer
{
PieceInfo king, queen, rooks[2], knights[2], bishops[2];
// pawns start from left to right from 1 until 8
PieceInfo pawns[8];
} ChessPlayer;
// functions definition
void init_chess(ChessPlayer *, unsigned char, int, int);
PieceInfo *get_player_at_coordinate(ChessPlayer *, int, int);
int check_dest_can_move(ChessPlayer *, int, int, int, int);
int if_move_have_barrier(ChessPlayer *, int, int, int, int, double *, int, int);
void display_board(ChessPlayer *);
int check_if_king_has_dead(ChessPlayer *);
int main()
{
/*
0 - player 1
1 - player 2
*/
ChessPlayer player[2];
init_chess(&player[0], 0, 1, 2);
init_chess(&player[1], 1, 8, 7);
int src_x, src_y, dest_x, dest_y, turn = 0, get_winner;
PieceInfo *get, *get_temp;
while(1)
{
#ifdef _WIN32
system("cls");
// make cmd to support unicode characters
SetConsoleOutputCP(1251);
#else
system("clear");
#endif
// get 1 space
cout << endl;
// display the board below here
display_board(player);
if((get_winner = check_if_king_has_dead(player)) != -2)
{
cout << endl << "Player " << unicodePieces[get_winner - 1][player[get_winner - 1].pawns[0].pos] << " [" << get_winner << "] win!" << endl << endl;
break;
}
cout << endl << "Player " << unicodePieces[turn][player[turn].pawns[0].pos] << " 's turn..\n";
while(1)
{
cout << "Please enter source coordinate of your piece : ";
scanf("%d %d", &src_x, &src_y);
get = get_player_at_coordinate(player, src_x, src_y);
if(src_x > 8 || src_y > 8 || get == NULL)
{
cout << endl << "Error! Invalid source coordinate [" << src_x << "] [" << src_y << "]" << endl << endl;
continue;
}
else if(get->belong != turn)
{
cout << endl << "Sorry! That piece isn't belong to you!" << endl <<endl;
continue;
}
break;
}
cout << "You have selected -> " << unicodePieces[get->belong][get->pos] << " at [" << get->x << "] [" << get->y << "] \n";
while(1)
{
cout << "Please enter destination coordinate : ";
scanf("%d %d", &dest_x, &dest_y);
if(dest_x > 8 || dest_y > 8)
{
cout << endl << "Error! Invalid destination coordinate [" << dest_x << "] [" << dest_y << "]" << endl << endl;
continue;
}
// check for common errors made by player
if(!check_dest_can_move(player, src_x, src_y, dest_x, dest_y)) continue;
break;
}
if((get_temp = get_player_at_coordinate(player, dest_x, dest_y)) != NULL) get_temp->status = 0;
get->x = dest_x, get->y = dest_y;
// xor variable turn with 1 to switch between first & second player
turn ^= 1;
}
}
void init_chess(ChessPlayer *chess_struct, unsigned char player_num, int first, int second)
{
chess_struct->king = { .x = 5, .y = first, .status = 1, .belong = player_num, .pos = 0};
chess_struct->queen = { .x = 4, .y = first, .status = 1, .belong = player_num, .pos = 1};
chess_struct->bishops[0] = { .x = 3, .y = first, .status = 1, .belong = player_num, .pos = 3};
chess_struct->bishops[1] = { .x = 6, .y = first, .status = 1, .belong = player_num, .pos = 3};
chess_struct->knights[0] = { .x = 2, .y = first, .status = 1, .belong = player_num, .pos = 4};
chess_struct->knights[1] = { .x = 7, .y = first, .status = 1, .belong = player_num, .pos = 4};
chess_struct->rooks[0] = { .x = 1, .y = first, .status = 1, .belong = player_num, .pos = 2};
chess_struct->rooks[1] = { .x = 8, .y = first, .status = 1, .belong = player_num, .pos = 2};
for(int i = 0; i < 8; i++)
chess_struct->pawns[i] = { .x = i+1, .y = second, .status = 1, .belong = player_num, .pos = 5 };
}
//
// get pointer to PieceInfo struct
// else return NULL if not exist
//
// this function is involving pointer, so ignore this if you can't understand
//
PieceInfo *get_player_at_coordinate(ChessPlayer *player, int x, int y)
{
for(int i = 0; i < 2; i++)
{
for(int z = 0, each_chessplayer = sizeof(ChessPlayer) / sizeof(PieceInfo); z < each_chessplayer; z++)
{
PieceInfo *each_piece = (PieceInfo *)((char *)(player + i) + (z * sizeof(PieceInfo)));
if(each_piece->x == x && each_piece->y == y && each_piece->status == 1)
return each_piece;
}
}
return NULL;
}
int check_if_king_has_dead(ChessPlayer *player)
{
for(int i = 0; i < 2; i++)
{
for(int z = 0, each_chessplayer = sizeof(ChessPlayer) / sizeof(PieceInfo); z < each_chessplayer; z++)
{
PieceInfo *each_piece = (PieceInfo *)((char *)(player + i) + (z * sizeof(PieceInfo)));
if(each_piece->pos == 0 && each_piece->status == 0)
return each_piece->belong;
}
}
return -2;
}
int check_dest_can_move(ChessPlayer *player, int src_x, int src_y, int dest_x, int dest_y)
{
PieceInfo *get, *get_temp;
get = get_player_at_coordinate(player, src_x, src_y);
get_temp = get_player_at_coordinate(player, dest_x, dest_y);
char replace_error[] = "Error! You can't place step into your own piece!";
if(get_temp != NULL && get_temp->belong == get->belong)
{
cout << endl << replace_error << endl << endl;
return 0;
}
else if(get->pos == 0) //king
{
// king can't move more than 1 step
if(abs(src_y - dest_y) > 1 || abs(src_x - dest_x) > 1)
{
cout << endl << "Error! King can only move 1 step!" << endl << endl;
return 0;
}
}
else if(get->pos == 1) // queen
{
double gradients[3] = { -1, 1, 0};
int check = if_move_have_barrier(player, src_x, src_y, dest_x, dest_y, gradients, 3, 1);
if(check != 1)
return 0;
}
else if(get->pos == 2) // bishop
{
double gradients[1] = {0};
int check = if_move_have_barrier(player, src_x, src_y, dest_x, dest_y, gradients, 1, 1);
if(check != 1)
return 0;
}
else if(get->pos == 3) // rooks
{
double gradients[2] = {-1, 1};
int check = if_move_have_barrier(player, src_x, src_y, dest_x, dest_y, gradients, 2, 0);
if(check != 1)
return 0;
}
else if(get->pos == 4) // knight
{
// knight have 8 possible movements with L shape
int move[8][2] =
{
{-2, 1}, {-1, 2}, {1, 2},
{2, 1}, {2, -1}, {1, -2},
{-1, -2}, {-2, -1}
}, check = 0;
for(int i = 0; i < 8 && !check; i++)
if((src_x + move[i][0]) == dest_x && (src_y + move[i][1]) == dest_y)
check++;
if(!check)
{
cout << endl << "Error! Knight movement must equivalent to L shape movement!" << endl << endl;
return 0;
}
}
else // pawns
{
char movetwosteps[] = "Error! Pawn can only move 2 steps at the initial of the game!";
char cantmovepawn[] = "Error! You can't move into that position!";
// sure this is hard to get
if((get->belong == 0 && src_y >= dest_y) ||
(get->belong == 1 && src_y <= dest_y))
{
cout << endl << "Error! Pawn can only move forward!" << endl << endl;
return 0;
}
// and this one too
if((get->belong == 0 && (((src_x - 1) == dest_x && (src_y + 1) == dest_y) || ((src_x + 1) == dest_x && (src_y + 1) == dest_y))) ||
(get->belong == 1 && (((src_x - 1) == dest_x && (src_y - 1) == dest_y) || ((src_x + 1) == dest_x && (src_y - 1) == dest_y))))
{
if(get_temp == NULL)
{
cout << endl << cantmovepawn << endl << endl;
return 0;
}
else if(get->belong == get_temp->belong)
{
cout << endl << replace_error << endl << endl;
return 0;
}
}
//
// abs = absolute value, because distant is always positive
//
if(abs(dest_y - src_y) == 2)
{
if((get->belong == 0 && src_y != 2) || (get->belong == 1 && src_y != 7))
{
cout << endl << movetwosteps << endl << endl;
return 0;
}
else if(get->belong == 1 && src_y != 7)
{
cout << endl << movetwosteps << endl << endl;
return 0;
}
}
else if(abs(dest_y - src_y) > 1)
{
cout << endl << "Error! Pawn can only move 1 step!" << endl << endl;
return 0;
}
else if(abs(dest_y - src_y) == 1 && src_x == dest_x && get_temp != NULL)
{
cout << endl << cantmovepawn << endl << endl;
return 0;
}
}
return 1;
}
/*
return code value :-
1 = no problem at all :)
-3 = has problem(s)
*/
int if_move_have_barrier(ChessPlayer *player, int src_x, int src_y, int dest_x, int dest_y, double *gradients, int size_gradients, int check_x)
{
char invalid_coordinate[] = "Error! Invalid destination coordinate! Please check again.";
char barrier_error[] = "Error! Piece can't move because there's a barrier before destination.";
// only 3 gradients, 1 is undefined (have to check manually)
double m = 0, check = 0;
PieceInfo *get;
int test = 0;
if(check_x && src_x == dest_x) // if same line at x, then +1 into check variable
{
check = 10.0, test++; // special gradient value
}
else if(src_x != dest_x)
m = (dest_y - src_y)/(dest_x - src_x);
for(int i = 0; i < size_gradients && !test; i++)
if(m == gradients[i])
check = gradients[i], test++;
if(!test)
{
cout << endl << invalid_coordinate << endl << endl;
return -3;
}
else if(check == 10.0 || check == -1.0 || check == 1.0 || check == 0.0) // if 4 graph gradients direction (10 is special value)
{
for(int i = 0; !(src_y == dest_y && src_x == dest_x); )
{
if(i++ && get_player_at_coordinate(player, src_x, src_y) != NULL)
{
cout << endl << barrier_error << endl << endl;
return -3;
}
if(check) // if gradient is not zero (which is 1 ,-1 or 10)
{
if(dest_y > src_y)
{
src_y++;
if(check == -1.0) src_x--;
else if(check == 1.0) src_x++;
}
else
{
src_y--;
if(check == 1.0) src_x--;
else if(check == -1.0) src_x++;
}
}
else
{
if(src_x < dest_x) src_x++;
else src_x--;
}
}
}
return 1;
}
//
// u can make ur own board if u want :)
//
void display_board(ChessPlayer *player)
{
PieceInfo *get;
char alphabet[] = " 1 2 3 4 5 6 7 8";
char line[] = " ---------------------------------";
cout << alphabet << endl;
cout << line << endl;
for(int i = 1; i <= 8; i++) // y-axis
{
cout << " " << (9-i) << " |";
for(int z = 1; z <= 8; z++) // x-axis
{
get = get_player_at_coordinate(player, z, 9 - i);
if(get == NULL || !get->status)
cout << " |";
else
cout << " " << unicodePieces[get->belong][get->pos] << " |";
}
cout << " " << (9-i) << endl;
cout << line << endl;
}
cout << alphabet << endl;
}
我还尝试使用SetConsoleOutputCP
到65001
设置代码页,但Windows CMD仍未正确显示Unicode。