简单
只有一个玩家,无交互,无胜负判断
#include<stdio.h>
#define BOARD_SIZE 15
int main(){
char board[BOARD_SIZE][BOARD_SIZE];
//初始化
for(int i = 0; i < BOARD_SIZE; i++){
for(int j = 0; j < BOARD_SIZE; j++){
board[i][j] = '.';
}
}
//循环条件,游戏是否继续
char decision = 'y';
while(decision == 'y' || decision == 'Y'){
//打印棋盘
for(int i = 0; i < BOARD_SIZE; i++){
for(int j = 0; j < BOARD_SIZE; j++){
printf("%c ", board[i][j]);
}
printf("\n");
}
//输入落子位置
printf("please input piece position (0 - %d), spacing by space\n", BOARD_SIZE - 1);
int x;
int y;
scanf("%d %d", &x, &y);
//是否可以落子
if(x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE && board[x][y] == '.'){
board[x][y] = 'x';
}else{
printf("Invalid inputs!Please input again\n");
}
//是否继续游戏
printf("continue?(y or n)\n");
getchar();
scanf("%c", &decision);
//清屏
printf("\033[H\033[J");
}
printf("GAME OVER!");
return 0;
}
printf(“\033[H\033[J”)实现屏幕刷新的原理
printf("\033[H\033[J");
能实现屏幕刷新的原因在于它利用了 ANSI 转义序列(ANSI escape sequences)来控制终端显示。这些序列是由 ESC(\033 或 \x1B)字符开头的字符串,后面跟着一些指令字符。具体来说:
①\033[H
:这个序列将光标移动到屏幕的左上角。\033
是 ESC 字符(ASCII 值为 27),[
是开始一个控制序列的字符,H
是光标定位命令。它等同于\033[1;1H
,即将光标移动到第 1 行第 1 列。
②\033[J
:这个序列清除从光标位置到屏幕末端的所有内容。J
是清屏命令。
当这两个序列组合在一起使用时,首先将光标移动到屏幕的左上角,然后从光标位置(也就是屏幕的左上角)清除到屏幕末端,这样就达到了刷新屏幕的效果。
进阶
有两个玩家交互,且可以检测胜负
重点:
① 游戏获胜条件?
② 两个玩家如何交互胜负判断函数中的方向检测:
① 单看当前位置的正方向:
② 单看当前位置的反方向:
③ 从整个for循环来看(两个一组):
自己仿写时出现的问题:
① 棋盘打印函数传参出错(传二维数组时写成了board[BOARD_SIZE][BOARD_SIZE],传的是一个字符,而且数组下标还越界了)
② 交换玩家部分逻辑判断有问题,逻辑有点混乱(我想的是board[x][y]==current_player,此种写法或许需要再引入一个变量记录用户)
#include<stdio.h>
#define BOARD_SIZE 15
#define DEFAULT_PIECE '.'
#define PLAYER_ONE_PIECE 'O'
#define PLAYER_TWO_PIECE 'X'
//打印当前棋盘
void print_board(char board[BOARD_SIZE][BOARD_SIZE]);
//胜负判定
char check_winner(char board[BOARD_SIZE][BOARD_SIZE], int x, int y, int current_player);
int main(){
char board[BOARD_SIZE][BOARD_SIZE];
//初始化
for(int i = 0; i < BOARD_SIZE; i++){
for(int j = 0; j < BOARD_SIZE; j++){
board[i][j] = DEFAULT_PIECE;
}
}
//当前玩家
char current_player = PLAYER_ONE_PIECE;
char winner = DEFAULT_PIECE;
while(winner == DEFAULT_PIECE){
print_board(board);
//输入落子位置
printf("player %c: please input piece position (0 - %d), spacing by space\n", current_player, BOARD_SIZE - 1);
int x;
int y;
scanf("%d %d", &x, &y);
//是否可以落子
if(x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE && board[x][y] == DEFAULT_PIECE){
board[x][y] = current_player;
//检测获胜者
winner = check_winner(board, x, y, current_player);
//交换玩家
current_player = (current_player == PLAYER_ONE_PIECE) ? PLAYER_TWO_PIECE : PLAYER_ONE_PIECE;
}else{
printf("Invalid inputs!Please input again\n");
continue;
}
//是否有人获胜
if(winner != DEFAULT_PIECE){
print_board(board);
printf("Winner is %c", current_player);
break;
}
}
return 0;
}
void print_board(char board[BOARD_SIZE][BOARD_SIZE]){
for(int i = 0; i < BOARD_SIZE; i++){
for(int j = 0; j < BOARD_SIZE; j++){
printf("%c ", board[i][j]);
}
printf("\n");
}
}
char check_winner(char board[BOARD_SIZE][BOARD_SIZE], int x, int y, int current_player){
int direction[4][2] = {{0, 1}, {1, 0}, {1, 1}, {1, -1}};
for(int i = 0; i < 4; i++){
//连续棋子数
int count = 1;
int dx = direction[i][0];
int dy = direction[i][1];
//检测当前位置的正方向
int tx = x + dx;
int ty = y + dy;
while(tx >= 0 && tx < BOARD_SIZE && ty >= 0 && ty < BOARD_SIZE && board[tx][ty] == current_player){
count ++;
tx += dx;
ty += dy;
}
//检测当前位置的反方向
tx = x - dx;
ty = y - dy;
while(tx >= 0 && tx < BOARD_SIZE && ty >= 0 && ty < BOARD_SIZE && board[tx][ty] == current_player){
count ++;
tx -= dx;
ty -= dy;
}
if(count >= 5){
return current_player;
}
}
return DEFAULT_PIECE;
}