三子棋的棋盘是一个九宫格,双方轮流落子,若有一方横竖或者对角线有三个棋子连成一条直线则胜利。但是三子棋有很多种和棋情况。
1.创建一个用户交互菜单
2.创建一个棋盘并初始化
3.打印一个棋盘
4.玩家落子
5.判定胜负关系
6.电脑落子
7.判定胜负关系
8.结束
void Menu()//游戏选择及面
{
printf("+-------------------------------+\n");
printf("| 1. Play 0. Exit |\n");
printf("+-------------------------------+\n");
}
static void InitBoard(char board[][COL], int row, int col)//初始化棋盘
{
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
//使用一个二维数组初始化棋盘
board[i][j] = INIT; //全部设置为INIT宏定义的空格
}
}
}
我们的棋盘实际上是一个二维数组,初始化过程实际上是我们使用了一个双重for循环,给每一个数组元素赋值为空格。
代码如下(示例):
static void ShowBoard(char board[][COL], int row, int col){
system("cls"); //调用dos命令窗口进行清屏操作,即刷新棋盘
printf(" ");
for (int i = 0; i < col; i++){
printf("%4d", i + 1);
}
printf("\n--+---+---+---\n");
for (int i = 0; i < row; i++){
printf("%-2d", i + 1); //2
for (int j = 0; j < col; j++){
printf("| %c ", board[i][j]); //12
}
printf("\n--+---+---+---\n");
}
}
在这里我们把打印输出棋盘设置为一个函数,这样在后面对方输入坐标的时候直接调用函数再次打印就可以了。
static void PlayerMove(char board[][COL], int row, int col){
//人选择落子位置
int x = 0;
int y = 0;
while (1){
printf("请输入你想落子的位置坐标" );
scanf("%d,%d", &y ,&x);
if (x<1 || x>3 || y<1 || y>3){
//非法性判断,因为棋盘为3x3
printf("超出了棋盘范围,请从新输入!");
continue;
}
if (board[x - 1][y - 1] == INIT){
//只有当这个格子为空的时候才可以落子
board[x - 1][y - 1] = WHITE; //落下的棋子为白子
break;
}
else{
printf("此格子已被占用,请从新输入");
}
}
}
1.玩家需要采用输入x,y的坐标来落子。
2.因为棋盘的大小是3x3的所以要对x和y进行合法性判定。
3.在落子之前还要判定玩家输入的坐标是否已经有棋子。
4.我们在头文件中宏定义了玩家的落子为WHITE 棋子为x。
static void ComputerMove(char board[][COL], int row, int col){
//电脑自动落子
while (1){
int x = rand() % 3; //生成的随机数对三取余,生成的数字只可能为0,1,2
int y = rand() % 3;
if (board[x][y] == INIT){
board[x][y] = BLACK;
break;
}
}
}
对生成的随机数%3取余,这样就得到了0,1,2的随机数。刚好满足我们定义的3x3的二维数组的下标。
static char IsEnd(char board[][COL], int row, int col){
for (int i = 0; i < row; i++){
//判定所有列是否有三个相同的棋子
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] \
&& board[i][0] != INIT) //\为续行符
{
return board[i][0]; //此位置的返回值为WHITE或者BLACK
}
}
for(int j = 0; j < col; j++){
//判定所有行是否有三个相同的棋子
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] \
&& board[0][j] != INIT) //\为续行符
{
return board[0][j]; //此位置的返回值为WHITE或者BLACK
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && //判定对角线是否有三个棋子相等
board[1][1] != INIT){
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && //判定对角线是否有三个棋子相等
board[1][1] != INIT){
return board[1][1];
}
for (int i = 0; i < row; i++){
//判断其格子是否满了,若不满则继续游戏
for (int j = 0; j < col; j++){
if (board[i][j] == INIT){
return NEXT;
}
}
}
return DRAW; //上述所有情况都不满足,则为平局
}
1.若同一行或同一列三个非空元素相同则胜利,返回值为棋子类型。
2.若对角线三个非空元素相同则胜利,返回值为棋子类型。
3.判断其格子是否满了,若不满则继续游戏。
4.其他条件均不满足则为平局。
void Game()
{
char board [ROW][COL]; //定义棋盘
InitBoard(board, ROW, COL); //初始化棋盘
srand((unsigned long)time(NULL)); //生成随机数种子
char result= 0;
while (1){
ShowBoard(board, ROW, COL); //展示棋盘
PlayerMove(board, ROW, COL); //人开始选择落子位置
result = IsEnd(board, ROW, COL); //判断游戏结果,若结果不是继续则退出。
if (result != NEXT){
break;
}
ShowBoard(board, ROW, COL); //展示棋盘
ComputerMove(board, ROW, COL); //电脑随机落子
result = IsEnd(board, ROW, COL); 判断游戏结果,若结果不是继续则退出。
if (result != NEXT){
break;
}
}
ShowBoard(board, ROW, COL); //展示棋盘
switch (result){
//判断棋局结果
case WHITE:
printf("你赢了!\n\n");
break;
case BLACK:
printf("你输了\n\n");
break;
case DRAW:
printf("平局啦!\n\n");
default:
break;
}
}
#ifndef __Test_H__
#define __Test_H__
#include
#include
#include
#include
#pragma warning(disable:4996)
#define ROW 3
#define COL 3
#define INIT ' ' //宏定义初始化输入的值为空
#define WHITE 'X'//白方是Player 棋子为X
#define BLACK 'O'//黑方是Computer 棋子为O
#define DRAW 'D'//
#define NEXT 'N'//
extern void Game();
#endif
void Menu()//游戏选择及面
{
printf("+-------------------------------+\n");
printf("| 1. Play 0. Exit |\n");
printf("+-------------------------------+\n");
}
int main()
{
int select = 0;
int quit = 0;
while (!quit )
{
Menu();
printf("请选择开始或退出");
scanf("%d", &select);
switch (select){
case 1: //选择1则开始游戏
Game();
break;
case 0:
quit = 1;
break;
default:
printf("输入错误,请从新输入\n");
break;
}
}
system("pause");
}
static void InitBoard(char board[][COL], int row, int col);//初始化棋盘
static void ShowBoard(char board[][COL], int row, int col);
static char IsEnd(char board[][COL], int row, int col);
static void ComputerMove(char board[][COL], int row, int col);
static void PlayerMove(char board[][COL], int row, int col);
void Game()
{
char board [ROW][COL]; //定义棋盘
InitBoard(board, ROW, COL); //初始化棋盘
srand((unsigned long)time(NULL)); //生成随机数种子
char result= 0;
while (1){
ShowBoard(board, ROW, COL); //展示棋盘
PlayerMove(board, ROW, COL); //人开始选择落子位置
result = IsEnd(board, ROW, COL); //判断游戏结果,若结果不是继续则退出。
if (result != NEXT){
break;
}
ShowBoard(board, ROW, COL); //展示棋盘
ComputerMove(board, ROW, COL); //电脑随机落子
result = IsEnd(board, ROW, COL); 判断游戏结果,若结果不是继续则退出。
if (result != NEXT){
break;
}
}
ShowBoard(board, ROW, COL); //展示棋盘
switch (result){
//判断棋局结果
case WHITE:
printf("你赢了!\n\n");
break;
case BLACK:
printf("你输了\n\n");
break;
case DRAW:
printf("平局啦!\n\n");
default:
break;
}
}
static void InitBoard(char board[][COL], int row, int col)//初始化棋盘
{
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
//使用一个二维数组初始化棋盘
board[i][j] = INIT; //全部设置为INIT宏定义的空格
}
}
}
static void ShowBoard(char board[][COL], int row, int col){
//展示棋盘
system("cls"); //调用dos命令窗口进行清屏操作,即刷新棋盘
printf(" ");
for (int i = 0; i < col; i++){
printf("%4d", i + 1);
}
printf("\n--+---+---+---\n");
for (int i = 0; i < row; i++){
printf("%-2d", i + 1); //2
for (int j = 0; j < col; j++){
printf("| %c ", board[i][j]); //12
}
printf("\n--+---+---+---\n");
}
}
static void PlayerMove(char board[][COL], int row, int col){
//人选择落子位置
int x = 0;
int y = 0;
while (1){
printf("请输入你想落子的位置坐标" );
scanf("%d,%d", &y ,&x);
if (x<1 || x>3 || y<1 || y>3){
//非法性判断,因为棋盘为3x3
printf("超出了棋盘范围,请从新输入!");
continue;
}
if (board[x - 1][y - 1] == INIT){
//只有当这个格子为空的时候才可以落子
board[x - 1][y - 1] = WHITE; //落下的棋子为白子
break;
}
else{
printf("此格子已被占用,请从新输入");
}
}
}
static void ComputerMove(char board[][COL], int row, int col){
//电脑自动落子
while (1){
int x = rand() % 3; //生成的随机数对三取余,生成的数字只可能为0,1,2
int y = rand() % 3;
if (board[x][y] == INIT){
board[x][y] = BLACK;
break;
}
}
}
static char IsEnd(char board[][COL], int row, int col){
//判断结果
for (int i = 0; i < row; i++){
//判定所有列是否有三个相同的棋子
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] \
&& board[i][0] != INIT) //\为续行符
{
return board[i][0]; //此位置的返回值为WHITE或者BLACK
}
}
for(int j = 0; j < col; j++){
//判定所有行是否有三个相同的棋子
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] \
&& board[0][j] != INIT) //\为续行符
{
return board[0][j]; //此位置的返回值为WHITE或者BLACK
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && //判定对角线是否有三个棋子相等
board[1][1] != INIT){
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && //判定对角线是否有三个棋子相等
board[1][1] != INIT){
return board[1][1];
}
for (int i = 0; i < row; i++){
//判断其烦是否满了,若不满则继续游戏
for (int j = 0; j < col; j++){
if (board[i][j] == INIT){
return NEXT;
}
}
}
return DRAW; //上述所有情况都不满足,则为平局
}