什么是井字棋
井字棋,英文名叫Tic-Tac-Toe,是一种在3*3格子上进行的连珠游戏,和五子棋类似,由于棋盘一般不画边框,格线排成井字故得名。游戏需要的工具仅为纸和笔,然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X),任意三个标记形成一条直线,则为获胜。(来自百度百科)
井字棋所要包含的内容
基本框架
我们把该游戏分为逻辑的测试和游戏的实现,分别用两个源文件和一个同文件来实现。
作为一个游戏起码要玩家来决定游戏的开始或结束一直按f5显然不够优雅所以我们使用一个do while循环来实现这一功能
也就是
void text()
{
int a = 0;
do {
//1,游戏开始
//0:游戏结束
scanf("%d", &a);
switch (a)
{
case 1:
game();
break;
case 0:
printf("游戏结束");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (a);
}
菜单的实现;
通知玩家1,游戏开始 0:游戏结束,其实就是菜单函数应该有的功能使用printf函数就可以轻松搞定
void menu()
{
printf("*****************************\n");
printf("******** 1. play ******\n");
printf("******** 0. eixt ******\n");
printf("*****************************\n");
}
`
初始化棋盘
存放棋盘数据很明显是一个二维数组所以我们先创建一个二维数组int board[ROW][COL];这里的行数和列数我们采用全局变量的形式定义在game.h中,方便日后对与棋盘大小的修改。然后将board的数组,行数,列数传入初始化棋盘的函数之中,
void init_board(char board[ROW][COL], int row, int col)
{
int i;
for (i = 0; i < row; i++)
{
int j;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
注:ROW,COL是我们定义的全局变量,而函数声明中要写的应该是变量。
打印棋盘
打印棋盘和初始化其实差不多,都是两个for循环,而要注意的是我们为了方便玩家观看应该”画“上格子,| —,
void print_board(char board[ROW][COL], int row, int col)
{
int i;
for (i = 0; i < row; i++)
{
int j;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}
玩家下棋
在这里我们要考虑的是所下坐标是否有效,及是否是重复下棋或是下到棋盘外,而在下错后我们应该重新进行下棋
void player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下棋:\n");
while (1)
{
printf("请输入你要下的棋的坐标\n");
int x = 0;
int y = 0;
scanf("%d%d", &x, &y);
//坐标合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该坐标被占用,请重新输入\n");
}
}
else//坐标非法
{
printf("坐标非法\n");
}
}
}
电脑无脑下棋
为什么说是无脑呢因为电脑下的棋是随机的,随机数的生成可以观看我之前的猜数字文章
void computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
判断输赢
三子棋的判断方式无非竖,横,斜三种方式只需要if判断就行了。除此之外便是平局。
//我希望is_full这个函数只是为了支持is_win函数的,只是在is_win函数内部使用
//那我们就没必要在头文件中声明
//
//判断棋盘是否满了
static int is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0;
//判断三行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
}
//判断三列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//平局?
if (is_full(board, row, col) == 1)
{
return 'Q';
}
//继续
//没有玩家或者电脑赢,也没有平局,游戏继续
return 'C';
}