基于百度百科的解释为:
是黑白棋的一种。三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、井字棋等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了。但是,有很多时候会出现和棋的情况。
三子棋一共有九个可以落子的空间,所以用二维数组比较方便。后面每一步进行后都通过数组保存状态,最后判定数组里的棋子情况便可知晓玩家输赢。
使用多文件能够比较好的实现解耦,调用起来比较方便,同时也很好维护。
头文件:在头文件中对三子棋行数和列数以及棋子样式和游戏进行状态进行宏定义。使之有利于编程和修改。
主函数文件:在该文件中输出选择菜单,玩家根据选择决定分支,是否调用游戏函数。
游戏文件:将三子棋实现的主体放在一个文件中,并用static对游戏函数的其他功能函数修饰,使之具有很强的独立性。
#define ROW 3//二维数组的行数
#define COL 3//二维数组的列数
#define BLACK 'X'//人输入棋子的样式
#define WHITE 'O'//computer棋子的样式
#define EMPTY ' '//用空格表示为空
#define DRAW 'D'//表示结束
#define NEXT 'N'//表示继续
extern void Game();
void Menu()
{
printf("+----------------------+\n");
printf("|--1.PLAY 2.EXIT--|\n");
printf("+----------------------+\n");
printf("请输入您的选择# ");
}
int main()
{
Menu();
int choice = 1;
while (choice)
{
scanf("%d", &choice);
switch (choice)//根据输入判断是否需要进行游戏
{
case 1:
Game();
Menu();
break;
case 2:
choice = 0;
printf("bye~bye~\n");
break;
default:
printf("您的输入有误,请重新输入# ");
}
}
system("pause");
return 0;
}
void Game()
{
srand((unsigned long)time(NULL));//种随机数种子
char arr[ROW][COL];
memset(arr,EMPTY,sizeof(arr));//初始化棋子
Show(arr);//输出棋盘
char result = 0;//定义接收返回值的变量
while(1)
{
Human_Move(arr);//玩家的落棋位置
result = Game_Judge(arr);//判断是否胜利
if (result != NEXT)//判断是否结束
{
break;
}
Computer_Move(arr);//computer的落棋
result = Game_Judge(arr);//判断是否胜利
if (result != NEXT)//判断是否结束
{
break;
}
Show(arr);
}
switch (result)//根据返回值选择分支
{
case BLACK:
printf("You Win!\n");
break;
case WHITE:
printf("You Lose!\n");
break;
case DRAW:
printf("You == Computer!\n");
break;
default:
printf("BUG!");
break;
}
}
每开始一局新的游戏时,我们都要初始化棋盘。
这里采用memset函数对数组初始化,注意,该函数是按字节初始化的。
memset(arr,EMPTY,sizeof(arr));//初始化棋子
static void Show(char arr[][COL])//输出棋盘
{
system("cls");//清空屏幕
printf(" ");
for (int i = 1;i < 4;i++)
{
printf(" %d", i);
}
printf("\n ------------- \n");
for (int i = 1;i < 4;i++)
{
printf("%-2d|", i);//格式控制
for (int j = 0;j < 3;j++)
{
printf(" %c |", arr[i - 1][j]);
}
printf("\n ------------- \n");
}
}
当用户输入落子的坐标时,我们需要考虑:
static void Human_Move(char arr[][COL])//玩家的落棋位置
{
int row = 0;
int col = 0;
while (1)
{
printf("您的棋子为#" );
scanf("%d %d", &row, &col);
if (row < 1 || row>3 || col < 1 || col>3)//判断落子位置是否合理
{
printf("输入有误,请重新输入\n#");
continue;
}
if (arr[row - 1][col - 1] == EMPTY)//判断该位置是否为空
{
arr[row - 1][col - 1] = BLACK;
break;
}
else
{
printf("该区域有棋子,请重新输入#");
}
}
}
条件判断时,一共有四种返回值:
static char Game_Judge(char arr[][COL])//判断是否胜利
{
for (int row = 0;row < ROW;row++)//判断每行是否存在获胜条件
{
if (arr[row][0] == arr[row][1]&&\
arr[row][1] == arr[row][2]&&\
arr[row][2]!= EMPTY)
{
return arr[row][0];
}
}
for (int col = 0;col < COL;col++)//判断每列是否存在获胜条件
{
if (arr[0][col] == arr[1][col]&&\
arr[1][col] == arr[2][col]&&\
arr[2][col]!= EMPTY)
{
return arr[0][col];
}
}
if ((arr[0][0] == arr[1][1]&&\
arr[1][1] == arr[2][2]&&\
arr[1][1]!= EMPTY)|| \
(arr[0][2] == arr[1][1]&&\
arr[1][1] == arr[2][0]&&\
arr[1][1]!=EMPTY))//判断交叉是否存在获胜条件
{
return arr[1][1];
}
for (int row = 0;row < ROW;row++)//判断是否还有空余棋子
{
for (int col = 0;col < COL;col++)
{
if (arr[row][col] == EMPTY)
{
return NEXT;
}
}
}
return DRAW;//返回平局结束的标志
}
计算机落子时,需要判断该位置是否为空,不为空则一直循环生成随机坐标。这里不用担心没有空余坐标的情况,因为在玩家落子后会进行一次条件判断,能执行到这里说明一定还有空位。
static void Computer_Move(char arr[][COL])//computer的落棋
{
while (1)
{
int row = rand() % ROW;
int col = rand() % COL;//随机的行数,列数
if (arr[row][col] == EMPTY)
{
arr[row][col] = WHITE;
break;
}
}
}
至此,全部功能实现完毕。
需要原码的童鞋点击此处c语言实现三子棋原码