目录
[打印菜单,让玩家选择是否玩游戏 --- game.c](#打印菜单,让玩家选择是否玩游戏 --- game.c)
[玩家对局完后多次选择是否再次进行游戏 --- test.c](#玩家对局完后多次选择是否再次进行游戏 --- test.c)
[将二维数组board的行和列定义为常变量 --- game.h](#将二维数组board的行和列定义为常变量 --- game.h)
[初始化二维数组board --- game.h](#初始化二维数组board --- game.h)
[打印棋盘 --- game.c](#打印棋盘 --- game.c)
[玩家下棋 --- game.c](#玩家下棋 --- game.c)
[电脑下棋 --- game.c](#电脑下棋 --- game.c)
[判断棋盘是否填满 --- game.c](#判断棋盘是否填满 --- game.c)
[判断输赢 --- game.c](#判断输赢 --- game.c)
实现三子棋游戏的简介
1. 在控制台上生成三子棋棋盘
2. 和电脑对局,玩家走一步,电脑走一步
3. 判断输赢后能让玩家选择是否再次进行游戏
三子棋游戏代码的测试文件、实现文件、头文件
实现三子棋游戏时创建:test.c文件 、game.c文件 、Tic_Tac_Toe.h文件
game.h文件 用来声明函数和包含函数所需的头文件
game.c文件 用来定义实现函数
test.c文件 用来测试 game.c文件,并完成三子棋游戏逻辑
且 test.c文件 和game.c文件 只需要包含game.h文件即可
实现三子棋游戏
打印菜单,让玩家选择是否玩游戏 --- game.c
void menu()
{
printf("*******************************************\n");
printf("***** 1.play 0.next *****\n");
printf("*******************************************\n");
}
玩家对局完后多次选择是否再次进行游戏 --- test.c
int main()
{
int input = 0;
do
{
menu();
printf("请输入:");
scanf("%d", &input);
if (input == 1)
{
game();
}
else if(input == 0)
{
printf("退出游戏\n");
}
else
{
printf("输入错误,请重新输入\n");
}
} while (input);
return 0;
}
三子棋棋子的存储
创建一个三行三列的二维数组board[3][3],用来存储棋子,但如果需要更换为五子棋的时候,所有使用了3的地方都需要更改,使用可以使用 #define 将 3 重命名为常变量
将二维数组board的行和列定义为常变量 --- game.h
#define ROW 3
#define COL 3
初始化二维数组board --- game.h
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] = ' ';
}
}
}
打印棋盘 --- game.c
/*
1 2 3
| | 1
---|---|---
| | 2
---|---|---
| | 3
*/
void DisplayBoard(char board[ROW][COL], int row, int col)
{
// 打印横坐标
for (int i = 1; i <= row; i++)
{
printf(" %d ", i);
printf(" ");
}
printf("\n");
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
// 打印每一行
printf(" %c ", board[i][j]);
if (j < row - 1)
{
printf("|");
}
}
// 打印纵坐标
printf(" %d\n", i + 1);
// 打印分割线
if (i < col - 1)
{
for (int k = 0; k < row; k++)
{
printf("---");
if (k < row - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
玩家下棋 --- game.c
void PlayerMove(char board[ROW][COL], int row, int col)
{
// 创建横纵坐标
int x = 0;
int y = 0;
while (1)
{
printf("\n请输入要落子的横纵坐标(用空格隔开):");
scanf("%d %d", &x, &y);
if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
{
if (board[x - 1][y - 1] != ' ')
{
printf("坐标已被占用,请重新输入\n");
}
else
{
board[x - 1][y - 1] = '*';
break;
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
电脑下棋 --- game.c
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑落子:\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
判断棋盘是否填满 --- game.c
此函数是用来判断是否为平局
// 填满返回1
// 未填满返回0
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 0;
}
}
return 1;
}
判断输赢 --- game.c
// 玩家赢返回 '*'
// 电脑赢返回 '#'
// 平局赢返回 'P'
// 继续返回 'J'
char IsWin(char board[ROW][COL], int row, int col)
{
// 判断行赢
for (int i = 0; i < row; i++)
{
int j = 0;
int flag = 1;
while (j < col - 1)
{
if ((board[i][j] == board[i][j + 1]) && board[i][j] != ' ')
{
j++;
}
else
{
flag = 0;
break;
}
}
if (flag)
return board[i][j];
}
// 判断列赢
for (int j = 0; j < col; j++)
{
int i = 0;
int flag = 1;
while (i < row - 1)
{
if ((board[i][j] == board[i + 1][j]) && board[i][j] != ' ')
{
i++;
}
else
{
flag = 0;
break;
}
}
if (flag)
return board[i][j];
}
// 判断从左上到右下赢
int x = 0;
int y = 0;
int flag = 1;
while (x < row - 1 && y < col - 1)
{
if ((board[x][y] == board[x + 1][y + 1]) && board[x][y] != ' ')
{
x++;
y++;
}
else
{
flag = 0;
break;
}
}
if (flag)
return board[x][y];
// 判断从右上到左下赢
x = 0;
y = col - 1;
flag = 1;
while (x < row - 1 && y > 0)
{
if ((board[x][y] == board[x + 1][y - 1]) && board[x][y] != ' ')
{
x++;
y--;
}
else
{
flag = 0;
break;
}
}
if (flag)
return board[x][y];
// 判断平局
if (IsFull(board, ROW, COL))
return 'P';
// 以上判断都没返回时,说明游戏还需继续
return 'J';
}
代码总览
test.c
#include"Tic_Tac_Toe.h"
void game()
{
char board[ROW][COL];
// 初始化棋盘为空格
InitBoard(board, ROW, COL);
// 打印棋盘
DisplayBoard(board, ROW, COL);
// 下棋
char ret = 0;
while (1)
{
// 玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
// 判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'J')
break;
// 电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
// 判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'J')
break;
}
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else
printf("平局\n");
}
int main()
{
int input = 0;
// 随机数生成器
srand((unsigned int)time(NULL));
do
{
menu();
printf("请输入:");
scanf("%d", &input);
if (input == 1)
{
game();
}
else if(input == 0)
{
printf("退出游戏\n");
}
else
{
printf("输入错误,请重新输入\n");
}
} while (input);
return 0;
}
game.h
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
// 打印菜单
void menu();
// 初始化棋盘为空格
void InitBoard(char board[ROW][COL], int row, int col);
// 打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
// 玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
// 电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);
// 判断输赢
char IsWin(char board[ROW][COL], int row, int col);
game.c
#include"Tic_Tac_Toe.h"
// 打印菜单
void menu()
{
printf("*******************************************\n");
printf("***** 1.play 0.next *****\n");
printf("*******************************************\n");
}
// 初始化棋盘为空格
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] = ' ';
}
}
}
// 打印棋盘
/*
1 2 3
| | 1
---|---|---
| | 2
---|---|---
| | 3
*/
void DisplayBoard(char board[ROW][COL], int row, int col)
{
// 打印横坐标
for (int i = 1; i <= row; i++)
{
printf(" %d ", i);
printf(" ");
}
printf("\n");
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
// 打印每一行
printf(" %c ", board[i][j]);
if (j < row - 1)
{
printf("|");
}
}
// 打印纵坐标
printf(" %d\n", i + 1);
// 打印分割线
if (i < col - 1)
{
for (int k = 0; k < row; k++)
{
printf("---");
if (k < row - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
// 玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
// 创建横纵坐标
int x = 0;
int y = 0;
while (1)
{
printf("\n请输入要落子的横纵坐标(用空格隔开):");
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 ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑落子:\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
// 判断棋盘是否填满
// 填满返回1
// 未填满返回0
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 0;
}
}
return 1;
}
// 判断输赢
// 玩家赢返回 '*'
// 电脑赢返回 '#'
// 平局赢返回 'P'
// 继续返回 'J'
char IsWin(char board[ROW][COL], int row, int col)
{
// 判断行赢
for (int i = 0; i < row; i++)
{
int j = 0;
int flag = 1;
while (j < col - 1)
{
if ((board[i][j] == board[i][j + 1]) && board[i][j] != ' ')
{
j++;
}
else
{
flag = 0;
break;
}
}
if (flag)
return board[i][j];
}
// 判断列赢
for (int j = 0; j < col; j++)
{
int i = 0;
int flag = 1;
while (i < row - 1)
{
if ((board[i][j] == board[i + 1][j]) && board[i][j] != ' ')
{
i++;
}
else
{
flag = 0;
break;
}
}
if (flag)
return board[i][j];
}
// 判断从左上到右下赢
int x = 0;
int y = 0;
int flag = 1;
while (x < row - 1 && y < col - 1)
{
if ((board[x][y] == board[x + 1][y + 1]) && board[x][y] != ' ')
{
x++;
y++;
}
else
{
flag = 0;
break;
}
}
if (flag)
return board[x][y];
// 判断从右上到左下赢
x = 0;
y = col - 1;
flag = 1;
while (x < row - 1 && y > 0)
{
if ((board[x][y] == board[x + 1][y - 1]) && board[x][y] != ' ')
{
x++;
y--;
}
else
{
flag = 0;
break;
}
}
if (flag)
return board[x][y];
// 判断平局
if (IsFull(board, ROW, COL))
return 'P';
// 以上判断都没返回时,说明游戏还需继续
return 'J';
}
小结
未将代码写死,以上代码适用于三子棋、五子棋、十子琪............
只需更改 #define ROW 3 以及 #define COL 3 即可