五子棋是一种两人对弈的纯策略型棋类游戏,目标是先在棋盘上形成一个五个棋子连成一线的局面。
本程序实现了人机对战和人人对战两种模式,其中人机对战使用了随机算法来实现电脑下棋。
程序中使用了二维数组来表示棋盘,并通过绘制函数将棋盘展示出来。
使用常量来代表不同的棋子类型,使用函数来判断棋盘状态以及实现下棋逻辑。同时,还实现了保存游戏记录的功能,将游戏记录保存到文件中。
#include<stdlib.h>
#include<stdio.h>
#include<Windows.h>
#include<time.h>
#define 白色 2
#define 黑色 1
#define 空白 0
#define BOARD_SIZE 15 // 棋盘大小
void draw_menu(void);
void draw_chessboard(int row, int col, int chessboard[][BOARD_SIZE]);
void print_chessboard(char chessboard[][BOARD_SIZE]);
void draw_chess(int type, char* tableline);
int is_win(int chessboard[][BOARD_SIZE], int row, int col);
int is_full(int chessboard[][BOARD_SIZE], int row, int col);
void humanVsHuman();
void humanVsAI();
void end_game();
int mune2();
void save_game(char chessboard[][BOARD_SIZE]);
//绘制主菜单
void draw_menu(void)
{
printf("******************************\n");
printf("******* 欢迎使用五子棋 *******\n");
printf("*** 请选择对战方式 ***\n");
printf("* 1.人-人对战 *\n");
printf("* 2.人-机对战(随机算法) *\n");
printf("* 3.退出 *\n");
printf("******************************\n");
printf("请选择:");
}
int main()
{
int choice;
draw_menu();
while (1)
{
scanf("%d", &choice);
switch (choice)
{
case 1:
humanVsHuman();
break;
case 2:
humanVsAI();
break;
case 3:
exit(0);
break;
default:
printf("输入错误,请重新选择\n");
}
}
return 0;
}
//绘制棋盘
void draw_chessboard(int row, int col, int chessboard[][BOARD_SIZE])
{
int i, j;
char tableline[] = "┼";
for (i = 0; i < row; i++)
{
if (i == 0)
{
for (j = 0; j < 14; j++)
{
if (j == 0) printf("┌");
else if (j == 14) printf("┐");
else printf("┬");
}
printf("\n");
}
else if (i == 14)
{
for (j = 0; j < 14; j++)
{
if (j == 0) printf("└");
else if (j == 14) printf("┘ ");
else printf("┴ ");
}
printf("\n");
}
else
{
for (j = 0; j < 14; j++)
{
if (j == 0) printf("├ ");
else if (j == 14) printf("┤ ");
else printf("%s", tableline);
}
printf("\n");
}
}
}
// 打印当前棋盘
void print_chessboard(char chessboard[][BOARD_SIZE])
{
printf("\n ");
for (int i = 0; i < BOARD_SIZE; i++)
{
printf("%c ", 'A' + i);
}
printf("\n");
for (int i = 0; i < BOARD_SIZE; i++)
{
printf("%2d ", i + 1);
for (int j = 0; j < BOARD_SIZE; j++)
{
draw_chess(chessboard[i][j], " ");
}
printf("%2d\n", i + 1);
}
printf(" ");
for (int i = 0; i < BOARD_SIZE; i++)
{
printf("%c ", 'A' + i);
}
printf("\n\n");
}
//定义棋子
void draw_chess(int type, char* tableline)
{
if (type == 白色)
{
printf("○");
}
else if (type == 黑色)
{
printf("●");
}
else
{
printf("%s", tableline);
}
}
// 判断是否胜利
int is_win(int chessboard[][BOARD_SIZE], int row, int col)
{
int i, j;
int cur = chessboard[row][col];
// 水平方向
for (i = col - 4; i <= col; i++)
{
if (i < 0 || i + 4 >= BOARD_SIZE)
{
continue;
}
if (chessboard[row][i] == cur && chessboard[row][i + 1] == cur &&
chessboard[row][i + 2] == cur && chessboard[row][i + 3] == cur &&
chessboard[row][i + 4] == cur)
{
return 1;
}
}
// 垂直方向
for (i = row - 4; i <= row; i++)
{
if (i < 0 || i + 4 >= BOARD_SIZE)
{
continue;
}
if (chessboard[i][col] == cur && chessboard[i + 1][col] == cur &&
chessboard[i + 2][col] == cur && chessboard[i + 3][col] == cur &&
chessboard[i + 4][col] == cur)
{
return 1;
}
}
// 左上到右下方向
for (i = row - 4, j = col - 4; i <= row, j <= col; i++, j++)
{
if (i < 0 || i + 4 >= BOARD_SIZE || j < 0 || j + 4 >= BOARD_SIZE)
{
continue;
}
if (chessboard[i][j] == cur && chessboard[i + 1][j + 1] == cur &&
chessboard[i + 2][j + 2] == cur && chessboard[i + 3][j + 3] == cur &&
chessboard[i + 4][j + 4] == cur)
{
return 1;
}
}
// 左下到右上方向
for (i = row + 4, j = col - 4; i >= row, j <= col; i--, j++)
{
if (i >= BOARD_SIZE || i - 4 < 0 || j < 0 || j + 4 >= BOARD_SIZE)
{
continue;
}
if (chessboard[i][j] == cur && chessboard[i - 1][j + 1] == cur &&
chessboard[i - 2][j + 2] == cur && chessboard[i - 3][j + 3] == cur &&
chessboard[i - 4][j + 4] == cur)
{
return 1;
}
}
return 0;
}
// 判断棋盘是否已满
int is_full(int chessboard[][BOARD_SIZE], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (chessboard[i][j] == 空白)
{
return 0;
}
}
}
return 1;
}
// 人机对战
void humanVsAI()
{
char chessboard[BOARD_SIZE][BOARD_SIZE];
int i, j, row, col;
int player = 黑色;
int computer = 白色;
int is_computer_turn = 0;
int level;
printf("请选择难度等级:\n1.简单\n2.中等\n3.困难\n");
scanf("%d", &level);
srand(time(NULL));
// 初始化棋盘
for (i = 0; i < BOARD_SIZE; i++)
{
for (j = 0; j < BOARD_SIZE; j++)
{
chessboard[i][j] = 空白;
}
}
while (1)
{
print_chessboard(chessboard);
if (is_win(chessboard, row, col))
{
printf("%s 赢了!\n", player == 黑色 ? "黑方" : "白方");
end_game();
return;
}
if (is_full(chessboard, row, col))
{
printf("平局!\n");
end_game();
return;
}
if (is_computer_turn)
{
// 电脑走棋
int x, y;
switch (level)
{
case 1: // 简单难度,随机下棋
do
{
x = rand() % BOARD_SIZE;
y = rand() % BOARD_SIZE;
} while (chessboard[x][y] != 空白);
break;
case 2: // 中等难度,实现基本的防守和进攻
// TODO: 实现中等难度下棋逻辑
break;
case 3: // 困难难度,实现更高级的防守和进攻
// TODO: 实现困难难度下棋逻辑
break;
}
printf("电脑下子:%c%d\n", 'A' + y, x + 1);
chessboard[x][y] = computer;
is_computer_turn = 0;
}
else
{
// 人走棋
printf("请%s下子:", player == 黑色 ? "黑方" : "白方");
scanf("%d %c", &row, &col);
getchar(); // 把回车符读掉
if (row < 1 || row > BOARD_SIZE || col < 'A' || col > 'A' + BOARD_SIZE - 1)
{
printf("输入错误,请重新输入!\n");
continue;
}
int x = row - 1;
int y = col - 'A';
if (chessboard[x][y] != 空白)
{
printf("该位置已有棋子,请重新输入!\n");
continue;
}
chessboard[x][y] = player;
is_computer_turn = 1;
}
}
}
// 游戏结束
void end_game()
{
printf("游戏结束!\n");
printf("是否保存游戏记录?(Y/N)");
char choice = getchar();
if (choice == 'Y' || choice == 'y')
{
save_game(chessboard);
}
}
// 保存游戏记录
void save_game(char chessboard[][BOARD_SIZE])
{
FILE* fp;
fp = fopen("game_record.txt", "a");
if (fp == NULL)
{
printf("无法打开文件!\n");
return;
}
fprintf(fp, "游戏记录:\n");
fprintf(fp, "----------\n");
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
fprintf(fp, "%d", chessboard[i][j]);
if (j == BOARD_SIZE - 1)
{
fprintf(fp, "\n");
}
else
{
fprintf(fp, " ");
}
}
}
fclose(fp);
printf("保存成功!\n");
}