首先,在编写之前,要创建头文件和相应的.c文件
其中,game.h文件用于写入所有要用的头文件,实现三子棋游戏的所有函数的声明和宏常量的定义。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL], int row, int col); //棋盘的初始化
void print_board(char board[ROW][COL], int row, int col); //打印棋盘
void PlayerMove(char board[ROW][COL], int row, int col);//玩家走棋
void ComeputerMove(char board[ROW][COL], int row, int col);//电脑走棋
char Judge(char board[ROW][COL], int row, int col);//判断输赢
int full(char board[ROW][COL]);//是否平局
三子棋.c是一个主要用于执行并调用game.h里面函数的文件。
三子棋.c的main函数:
int main()
{
srand((unsigned int)time(NULL));//随机
int input = 0;//选择
menu();//菜单调用
printf("请输入你的选择\n");
while (1)
{
scanf("%d", &input);//输入选择
switch (input)
{
case 1:
game();//开始进行游戏
break;
case 0:
printf("退出成功,欢迎下次使用");
system("pause");
exit(0);//退出函数
break;
default:
printf("输入错误,请重新输入");
break;
}
}
return 0;
}
菜单的打印(可以随意)
void menu()
{
printf("******************\n");
printf("******1.play******\n");
printf("******0.exit******\n");
printf("******************\n");
}
游戏的实现game()
void game()
{
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);//数组初始化为空格
print_board(board, ROW, COL);//打印棋盘
char ret;
while (1)
{
PlayerMove(board, ROW, COL);//玩家走
if ((ret = Judge(board, ROW, COL)) != ' ')//判断输赢
{
break;
}
print_board(board, ROW, COL);//打印棋盘
ComeputerMove(board, ROW, COL);//电脑走
if ((ret = Judge(board, ROW, COL)) != ' ')//判断输赢
{
break;
}
print_board(board, ROW, COL);//打印棋盘
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else if (ret == 'p')
{
printf("平局\n");
}
print_board(board, ROW, COL);
printf("游戏结束\n");
}
思路:先进行棋盘的初始化,并打印。在进行游戏环节的时候,写入循环体中,用函数来实现:玩家走–>判断输赢–>打印棋盘–>电脑走–>判断输赢–>打印棋盘。在判断输赢的过程中,如果返回值不等于‘ ’,说明一定有以下三种情况:1.玩家赢 2.电脑赢 3.平局。此时应该break掉循环,进一步判断具体情况。如果返回值等于‘ ’,说明这三种情况都不满足,那么游戏继续。
game函数中真正作用的那些函数在game.c文件中实现
(一)初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col) //初始化
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
用循环遍历二维数组进行空格初始化
(二)打印棋盘
void print_board(char board[ROW][COL],int row,int col) //打印棋盘
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
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 PlayerMove(char board[ROW][COL], int row, int col) //玩家走棋
{
int x = 0, y = 0;
printf("玩家走,请输入坐标:>");
while (1)
{
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("坐标非法,重新输入");
}
}
}
(四)电脑走棋
void ComeputerMove(char board[ROW][COL], int row, int col) //电脑走棋
{
int x = 0, y = 0;
printf("电脑走:>\n");
x = rand() % row;//在[0,2]范围内生成随机数
y = rand() % col;
while (1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
利用生成的随机值形成电脑走棋的坐标。注:在主函数中要写上srand((unsigned int )time( NULL))
(五)判断输赢 玩家赢返回‘ * ’,电脑赢返回’ # ’
char Judge(char board[ROW][COL], int row, int col)//判断输赢 玩家赢返回* 电脑赢返回#
{
int i = 0, j = 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 (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[j][0] != ' ')
{
return board[0][j];
}
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
{
return board[0][2];
}
if (full(board))//如果平局 返回p
{
return 'p';
}
return ' '; //三种情况均不满足
}
思路:判断输赢有三种情况。
1.每行是否为同一个棋子
2.每列是否为同一个棋子
3.对角线的判断
如果满足以上三种情况的任一情况,返回相应的符号,来判断是谁赢;如果平局,返回p;如果均不是,返回‘ ’
(六)是否平局
int full(char board[ROW][COL])
{
int i = 0, j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
{
return 0;//没平局
}
}
}
return 1;//平局
}
思路:看棋盘是否都满了,如果都满了还没有分出胜负,就是平局,平局返回1;如果还有空,就返回0。
总结:三子棋应用了C语言的的二维数组的创建及初始化,函数的调用,一些基本的条件循环语句的使用等知识点。可以很好的强化对C语言的认识。
其中,我写的判断输赢的方法还显得有一些啰嗦和不灵活,希望在日后的学习中可以改进一下,变得更好。