小时候,在学校和小伙伴除了互相追逐着玩闹玩游戏以外,相信很多小伙伴们也有和朋友在课堂上拿一张纸玩井字棋的美好回忆。(如下图酱紫啦~)
那今天呢,我们就用C语言制作一款简易的井字棋来练习一下对代码的感觉,顺便找一下以前儿时美好的回忆。
<一>制作棋盘
首先,我们需要创建一个头文件,两个源文件,方便之后的调用和书写。当然,要注意一件重要的事情,就是注意源文件和头文件的对应~~~~
对于棋盘,很明显,这是一个九宫格,而九宫格大家第一时间能想到什么呢?对的~二维数组,一个三行三列的二维数组。所以刚开始当然是要创建啦,然后在这个二维数组上制作棋盘。
char board[ROW][COL] = { 0 };
第一步当然是要先初始化,给每一个对应的板块赋值"空格",对的,就是space
void InitBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
//memset(board, ' ', row*col*sizeof(char));
}
第二步,我们创建好一个棋盘就相当于有了这张纸,那想要玩的话是不是就要接着做点其他事情?举个栗子:画线?
void ShowBoard(char board[ROW][COL], int row, int col)
{
printf("=====================\n");
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
//三个空格
printf(" %c ", board[i][j]);
//两列竖线
if (j < col - 1)
{
printf("|");
}
}
//换行
printf("\n");
for (int j = 0; j < col; j++)
{
printf("---");
//
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
printf("=====================\n");
}
这里的话,我要对这个棋盘进行一下说明,因为只有代码大家可能会看懵。
这是在vs上执行了代码之后的棋盘,那小伙伴们可能就看懵了呀,你确定这是三行三列的二维数组?
是的,宝贝们~就是你想的那样,这样看可能不太那么明显,那我们再仔细点 ------>
这样看能明白嘛~对应代码,循环加判断,就是这么神奇~
<二> 制定下棋人员
如果我以后技术到了一定的地步,我可以学学大佬,搞个区域网对战,但是现在的话,就只能先和人机battle了。.
void ComputerMove(char board[ROW][COL], int row, int col)
{
while (1)
{
int x = rand() % row;//[0,1,2]
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = 'O';
break;
}
}
}
这段代码唯一需要注意的:这个生成,具有唯一性,就是如果你玩这个三子棋,你如果第两局走和第一局棋一样的路,那么人机也会走一样的路,为了防止这种情况发生,我们需要给主函数加点神奇的魔法:
srand((unsigned)time(NULL));
然后能,接下来就是我们自己走啦,就这九个格子,用相对应的坐标来走,代码设置一下边界防止某些伙伴突发奇想想玩点其他的而导致数组越界后,我们自己的路就简单地制作完成啦。
void PlayerMove(char board[ROW][COL], int row, int col)
{
while (1)
{
printf("请输入你的坐标:\n");
int x = 0;
int y = 0;
scanf("%d%d", &x, &y);
if (x >= 1 && x <= 3 && y >= 1 && y <= 3)
{
//x o
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = 'X';
break;
}
else
{
printf("该位置已经有棋子\n");
}
}
else
{
printf("坐标不合法\n");
}
}
}
然后就是,你走一步我走一步,你走一步我走一步,你走一步我走一步.............(别忘了每走一步之后打印棋盘)
PlayerMove(board, ROW, COL);
//每走一步 都得判断 输赢
ret = IsWin(board, ROW, COL);
if (ret != ' ')
{
break;
}
ShowBoard(board, ROW, COL);
ComputerMove(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != ' ')
{
break;
}
ShowBoard(board, ROW, COL);
<三>胜负判定
如果没人拉着我能和我伙伴玩一宿,哈哈哈哈,但是和电脑的话,emmmmm,先来看看我们的胜负判定。
关于不是平局的情况,那么无非就是我赢或者电脑赢,上面的ret变量和Iswin就是来记录返回值的,我是0,电脑是X,等等,不对我是X电脑是0,也不对,为啥感觉怪怪的...............
if (ret == 'X')
{
printf("玩家赢\n");
}
else if (ret == 'O')
{
printf("电脑赢\n");
}
else if (ret == 'Q')
{
printf("平局\n");
}
那不论是我赢还是电脑赢,其实都只要列出对应情况即可(就是三行,三列,两条对角线):
for (int 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 (int j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j]
&& board[0][j] != ' ')
{
return board[0][j];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2]
&& board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0]
&& board[0][2] != ' ')
{
return board[0][2];
}
接着就是平局啦
static int IsFull(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return -1;//没有满
}
}
}
return 1;//说明当前平局
}
我们每走一步都要判断是否是平局,对了,还有,可能会有小伙伴问了,说上面的胜利与否都是返回字符的,这里怎么就返回整数了呢?那我们在IsWin这个函数最后加个判断就好啦~
//是否是平局
if (IsFull(board, row, col) == 1)
{
return 'Q';//平局
}
return ' ';//没有平局 正常的情况下
<四>总结
首先来张截图玩一把:
所以以后区域网和朋友对战可能还好玩一些。
三子棋是一款特别简单的游戏,而且也没有特别复杂的代码,也特别适合新手练习,写三子棋最最主要的是逻辑思维要清晰,难点主要在于制作棋盘和胜负判定,还有一些其他需要小细节也是需要我们注意的,好了,好久没发博客了,各位小伙伴,一起努力进步呀。
PS:赶紧写递归,拖了有两星期了都......